Jump to content

bfo

Members
  • Content Count

    3
  • Joined

  • Last visited

  1. Hadn't it been for a logic analyzer, I wouldn't have solved it. This is what happened during single transfer: 0x02 0x03 0x03 0x00 0x07 0xd0 0x91. RTS (second timeline) is asserted just before entering stateTransision() and deasserted just after return from this function. Notice how, after the address byte, the code in stateTransition executes swiftly. The gap between address byte and the payload, which allows the address byte to be received correctly, is caused by the fact that, in order to emulate 9-bit UART on a laptop virtual COM, I have to change parity from 'Mark' to 'Space'. Then a byte 0x03 comes into the buffer and there happens the magic. Only vital, and, as it turned out, crucial for this case part of the software stack that I allowed myself to omit was the actual HW_UARTget() procedure, which had a nasty greasy while buried in its flesh: static inline uint8_t HW_UARTget(void) { while (HW_UART_RXbusy()); return UCA0RXBUF; } By the time the 'while' condition got evaluated, the UART machinery had already started receiving another byte. Thus, the received sequence was: 0x02 0x00 0x91. Without that abominable loop, the code executes as fast as when receiving address byte, and all bytes are received: I hope this explanation will save those debugging UART issues some time in the future.
  2. Aha, I forgot to add, that the same function is invoked on TX interrupt, thus the 'if' part.
  3. Hello, Lastly I have whipped up a state machine based protocol for sending small frames using 9-bit address mode. Ft232rl, wrapped up in the MMusb232rl board, doesn't support this mode directly, so I am leaning on changing the parity bit to mark or space to simulate the address bit on the PC side. Everything works as a charm when I single step the program on the PC. Just on a sidenote, this program is coded in Qt using QtSerialPort. However, when I let the program run as it normally would in a production environment, the uC only receives several bytes out of the whole packet. I have observed the following happen. After reset, the uC receives 4 bytes out of 7. Then, I send the packet again, the uC gets 2/7. After that only 1/7th of every packet makes it to the uC, so only an address byte is being received and the state machine waits in the next state, which is 'wait for the number of parameters'. I think the most simple causes like incorrect wiring or voltage level mismatch can be ruled out right away, because single-stepping the PC program makes all the bytes come through successfully. That might suggest a baudrate mismatch, but I have checked hundreds of times and 9600 is used on both ends. That leaves, among others, a broken driver in the field. Right now I am using Linux kernel 3.9.9. I have also tried replacing literally every element of the system, including the 232 chip, the launchpad and moving the 232 chip over a breadboard to no avail. Unfortunately, I don't have access to neither a logic analyzer nor an oscilloscope. Has any of you encountered a similar problem? Below are the most important code snippets: static inline void HW_UARTinit(void) { //---- Select and initialize pin to control RS485 transceiver direction ---------------- P1DIR |= BIT0; P1OUT &= ~BIT0; // Set RS485 transceiver to receive. //assign P1.1 and P1.2 to be used as Rx and Tx P1SEL |= BIT1 + BIT2; P1SEL2 |= BIT1 + BIT2; //no parity, //LSB first, //8-bit data, //one stop bit, //address-bit multiprocessor mode, //async mode UCA0CTL0 |= UCMODE_2; //select clock source - SMCLK, //erroneous characters rejected and UCAxRXIFG is not set, UCA0CTL1 |= UCSSEL_2; //example prescaler settings: //minimal error rate without external oscillator //BRCLK == SMCLK == 1MHz //baud == 9600 //UCBRx == 104 //UCBRSx == 1 //UCBRFx == 0 UCA0BR0 = 104; UCA0BR1 = 0; UCA0MCTL = UCBRS_1; //release USCI for operation UCA0CTL1 &= ~UCSWRST; //enable Rx interrupt IE2 |= UCA0RXIE; } #pragma vector=USCIAB0RX_VECTOR __interrupt void USCIAB0RX_ISR(void){ //ISR(USART_RXC_vect) stateTransition(); } void stateTransition(void){ uint8_t receivedByte = 0; if (HW_UARTaddress()){ vars.state = AWAIT_REQUEST_FETCH_ADDRESS; } // When TXC interrupt it may cause some problems and delays if(vars.state < VALIDITY_CHECK){ receivedByte = HW_UARTget(); lumpBytesRcvd++; } ... } inline static void _INIT(void) { ... //DCO 1MHz if (CALDCO_1MHZ == 0xFF || CALBC1_1MHZ == 0xFF) { //calibration data was erased! we can't proceed while (true); } else { BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; } //MCLK - default DCO/1 //SMCLK - default DCO/1 } HW_UARTaddress() returns true if a last received byte has the address bit set, otherwise returns false. My last idea is that the internal RC oscillator is not stable enough to allow error-free reception of a few subsequent bytes, but that's not so likely. Thanks to everyone who has taken time read this post. Any help will be much appreciated.
×