Content originally posted in LPCWare by jenswilly on Wed Jan 23 03:23:36 MST 2013 Since I spent som many hours tearing my hair out in frustration over this I thought I should share my findings with the rest of you. Hopefully, that will help avoid some tearing out of hair...
The code for soft UART in AN10955 contains a bug that causes reception of data to stop at random times. Sometimes it will start again, sometimes not...
In the swu_isr_rx() method, the timer's MR1 is loaded with the timer value for when the stop bit is expected. That value is simply 9 * BIT_LENGTH. The value is checked for "wrap around" – i.e. if the value becomes so high that is overflows. This is the code (lines 314-317 in lpc_swu.c in the LPCXpresso_Soft_UART_1343/Soft_UART/Application/src folder):
edge_stop = edge_sample + STOP_BIT_SAMPLE; //estimate the end of the byte
if (edge_stop < edge_last) //adjust the end of byte...
edge_stop |= ADJUST; //... if needed
RX_ISR_TIMER->MR1 = edge_stop; //set MR1 (stop bit center)
The problem is that the timer only runs to 0x3FFFFFFF so the if-statement above will never be true. In order for edge_stop to overflow and become less and edge_last it would need to become greater than 0xFFFFFFFF.
Now imagine that the value of edge_sample is 0x3FFFFDFF (which is perfectly possible). edge_stop would then become 0x400105AB (if we're using a bit length of 7500 PCLKs). And this is the bug: the timer ony runs up to 0x3FFFFFFF so the MR1 interrupt will never happen since the timer will never reach 0x400105AB. Thus, the "byte received" event never happens and no more data is received.
[B]The fix[/B] Fortunately, the fix is easy. What we really want to do is, "If the calculated stop bit time is greater than the timer's maximum, wrap it around". So simple replace these two lines:
if (edge_stop < edge_last) //adjust the end of byte...
edge_stop |= ADJUST; //... if needed
with:
if( edge_stop >= ADJUST ) // Adjust the stop bit time if necessary
edge_stop -= ADJUST;
And everything works again. (Yeah, I know: you could do it even more efficiently with an AND statement or somesuch.)