I would like to point out a problem in the Traffic example program for the C166 toolset. The program contains SERIAL.C file which implements interrupt-driven serial IO for the on-chip UART of the C16x microcontroller family. The implementation is very good and I used it with minor modifications in some projects. It is likely that others used it too. That's why I want to point out a problem with this implementation. I'll try to describe the problem in detail, so please excuse me for the long posting. Occasionally the SERIAL.C module sends characters to the serial line in wrong order, i.e. it swaps two adjacent characters. The problem showed in a program that used serial IO heavily. To see where the problem comes from, let's look at the source code:
/******************************************************************************/ /* putbuf: write a character to SBUF or transmission buffer */ /******************************************************************************/ void putbuf (char c) { if (!sendfull) { /* transmit only if buffer not full */ !!! if (!sendactive && !sendstop) { /* if transmitter not active: */ sendactive = 1; /* transfer the first character direct */ S0TBUF = c; /* to S0TBUF to start transmission */ } else { /* otherwise: */ !!! S0TIE = 0; /* disable transmit interrupt */ _nop_ (); /* avoid pipeline effects */ _nop_ (); outbuf[oend++ & (OLEN-1)] = c; /* transfer char to transmission buffer */ if (((oend ^ ostart) & (OLEN-1)) == 0) sendfull = 1; S0TIE = 1; /* enable transmit interrupt */ } /* set flag if buffer is full */ } } /* ... */ /******************************************************************************/ /* serial_transmit: serial transmitter interrupt */ /******************************************************************************/ void serial_transmit (void) interrupt SERIAL_TRANSMIT0 = 0x2A using S_RBANK { if (ostart != oend) { /* if characters in buffer and */ if (!sendstop) { /* if not Control+S received */ S0TBUF = outbuf[ostart++ & (OLEN-1)]; /* transmit character */ sendfull = 0; /* clear 'sendfull' flag */ /* if task waiting: signal ready */ if (otask != -1) isr_send_signal (otask); } } else sendactive = 0; /* if all transmitted clear 'sendactive' */ }