• AVR Freaks

Helpful ReplyHot![SOLVED] UART (or code) having different behaviors for different baudrates - PIC32MX

Author
seccoxiru
Junior Member
  • Total Posts : 96
  • Reward points : 0
  • Joined: 2011/10/27 13:42:59
  • Location: 0
  • Status: offline
2019/05/10 14:01:49 (permalink)
0

[SOLVED] UART (or code) having different behaviors for different baudrates - PIC32MX

Hi.
I'm using PIC32MX470F512L, MPLAB X v5.15 and XC32 v1.43, but I already used the latest XC32 compiler v2.15 and got the same results.
 
I have made a lib to deal with uarts for PIC32MX and I use circular buffer. My implementation of the ring buffer is not the best but in fact it works.
 
The test that I'm doing is: every byte received is transmitted back to PC via HC-05 bluetooth module. I have tested the code at 19200 bps and 115200 bps. At 19200 bps all works perfectly, but at 115200 bps not. At 19200 bps, for example, if I transmit a packet of chars "0123456789" from PC to the PIC, the PIC always send the same packet back to PC. I left PC serial terminal to transmit that packet every 50ms, and after 1 minute I do stop, and begin to send the packets manually by clicking the send button (one packet by click), and the PIC is still transmitting back each packet received, correctly, the same values, but thats at 19200 bps. At 115200 bps there's another behavior. After send some packets (random quantity after start-up), RxInI is getting higher value than RxOutI (code), like it is was receiving more bytes than reading, or reading less than receiving. The packet sent by PC is "0123456789". For the first packets (random quantity) it receives the same packet back, and then it begin to receive "9012345678", then "8901234567", then "7890123456", then "6789012345" packets back, with random quantity of packets between the change on the response (packet sent back).
 
Also I have monitored overrun error bit and it is always in 0. And I get the same resut with bluetooth module HM-10.
 
I'm not figuring out what is the problem, it is strange that it works perfectly at 19200 bps and have a strange/erroneous behavior at 115200 bps.
 
Help!
 
//-----------------------------------------------------------------------------
void UartReceiveISR_32bit (uint8_t uart_n, UART_32bit *ptr_uarts)
{
uint8_t i = --uart_n;

while ((*(ptr_uarts+i)->p_sta_reg & (ptr_uarts+i)->rxda_bit) && (ptr_uarts+i)->BytesToRead < RxBuffLen_32bit)
{
     (ptr_uarts+i)->BytesToRead++;
     (ptr_uarts+i)->RxBuff[(ptr_uarts+i)->RxInI] = *(ptr_uarts+i)->p_rx_reg;
 
 
 
     if ((ptr_uarts+i)->RxInI != RxBuffLen_32bit-1) { (ptr_uarts+i)->RxInI++; }
     else { (ptr_uarts+i)->RxInI = 0; }
}

*(ptr_uarts+i)->p_ifs_rx_reg &= (~(ptr_uarts+i)->rxif_bit);
}
//-----------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
//-----------------------------------------------------------------------------
uint8_t UartReadByte_32bit (uint8_t uart_n, UART_32bit *ptr_uarts)
{
uint8_t byte;
uint8_t i = --uart_n;

byte = (ptr_uarts+i)->RxBuff[(ptr_uarts+i)->RxOutI];
(ptr_uarts+i)->BytesToRead--;
if ((ptr_uarts+i)->RxOutI != RxBuffLen_32bit-1) { (ptr_uarts+i)->RxOutI++; }
else { (ptr_uarts+i)->RxOutI = 0; }

return byte;
}
//-----------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
//-----------------------------------------------------------------------------
uint16_t UartBytesAvailable_32bit (uint8_t uart_n, UART_32bit *ptr_uarts)
{
uart_n--;
return (ptr_uarts+uart_n)->BytesToRead;
}
//-----------------------------------------------------------------------------

 
 //main loop
while (UartBytesAvailable_32bit(SERIAL_BT, UARTS()))
{
uint8_t byte = UartReadByte_32bit(SERIAL_BT, UARTS());

if (byte != 'Z')
{
     UartPutByte_32bit(SERIAL_BT, byte, UARTS());
}

else
{
     UartPutByte_32bit(SERIAL_BT, uarts[2].RxInI, UARTS());
     UartPutByte_32bit(SERIAL_BT, uarts[2].RxOutI, UARTS());
     UartPutByte_32bit(SERIAL_BT, uarts[2].TxInI, UARTS());
     UartPutByte_32bit(SERIAL_BT, uarts[2].TxOutI, UARTS());
}
}

 
 
Regards.
 
post edited by seccoxiru - 2019/05/12 13:39:00

Attached Image(s)

#1
al_bin
Super Member
  • Total Posts : 169
  • Reward points : 0
  • Joined: 2011/02/11 06:28:47
  • Location: 0
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/10 14:56:31 (permalink)
0
So you receive some chars twice.
Try https://www.microchip.com/forums/m824389.aspx
 
Albert
#2
seccoxiru
Junior Member
  • Total Posts : 96
  • Reward points : 0
  • Joined: 2011/10/27 13:42:59
  • Location: 0
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/10 15:29:24 (permalink)
0
al_bin
So you receive some chars twice.Try https://www.microchip.com/forums/m824389.aspx Albert

He was clearing the rxif flag before reading the received bytes and the solution was on reading the received bytes before clearing the rxif flag. In my case I always read the received bytes and then I clear the rxif flag. This is not the same problem that I'm facing. Actually I can't understand why my code behaves perfect in 19200 bps, and if I only change the baud to 115200 bps I get weird behavior.
#3
al_bin
Super Member
  • Total Posts : 169
  • Reward points : 0
  • Joined: 2011/02/11 06:28:47
  • Location: 0
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/11 01:44:41 (permalink)
4.5 (2)
Then you probably affected race condition on change BytesToRead in main and interrupt context.
 
In main thread instruction : (ptr_uarts+i)->BytesToRead-- is non atomic.
1. read BytesToRead to register x
2. decrement reg x
3. store x to ptr_uarts
 
If you receive IRQ between point 2 and 3
then incrementing in irq handler is lost.
 
Albert
#4
seccoxiru
Junior Member
  • Total Posts : 96
  • Reward points : 0
  • Joined: 2011/10/27 13:42:59
  • Location: 0
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/11 10:55:27 (permalink)
0
There was other funtions being called from main at each main cycle.
I realized that if I left only the uart function on main, alone, it works perfect also in 115200 bps. But if I uncomment outputs and digital inputs routines, just one of them or both, the wrong behavior of uart function appear.
 
This works:
    while (1) 
    {
        while (UartBytesAvailable_32bit(SERIAL_BT, UARTS()))
        {
                uint8_t byte;
                byte = UartReadByte_32bit(SERIAL_BT, UARTS());
                UartPutByte_32bit(SERIAL_BT, byte, UARTS());
        }
        
        WDTCONbits.WDTCLR = 1;
        //RoutineDigitalInputs_32bit(QTY_DIGITAL_IN, INPUTS());
        //RoutineOutputs_32bit(QTY_OUTPUTS, OUTPUTS());
        RoutineLcd_32bit(LCD());
    }

 
 
This does not work:
    while (1) 
    {
        while (UartBytesAvailable_32bit(SERIAL_BT, UARTS()))
        {
                uint8_t byte;
                byte = UartReadByte_32bit(SERIAL_BT, UARTS());
                UartPutByte_32bit(SERIAL_BT, byte, UARTS());
        }
        
        WDTCONbits.WDTCLR = 1;
        RoutineDigitalInputs_32bit(QTY_DIGITAL_IN, INPUTS());
        RoutineOutputs_32bit(QTY_OUTPUTS, OUTPUTS());
        RoutineLcd_32bit(LCD());
    }

 
If RoutineDigitalInputs_32bit() or RoutineOutputs_32bit() is called (both or only one) in main the error appears
LcdRoutine does not interfere. These functions have nothing to do with the uarts or interrupts.
post edited by seccoxiru - 2019/05/11 11:22:34
#5
cobusve
Super Member
  • Total Posts : 493
  • Reward points : 0
  • Joined: 2012/04/02 16:15:40
  • Location: Chandler
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/11 13:55:05 (permalink) ☄ Helpfulby seccoxiru 2019/05/11 15:00:44
5 (1)
You have a race condition.
 
The best way to understand this kind of interactions is probably to go through the first 4 examples on this site :
https://deadlockempire.github.io/
 
What is happening is that you are busy reading the one byte when the next one arrives. This causes you to access the same variable from mainline code and the ISR, and the ISR happening while the mainline code is reading the same variable causes this result.

At least one place where this could happen is when the ISR for the next byte happens in the middle of this line (ptr_uarts+i)->BytesToRead--;

If you look at the ASM it is probably doing something like this:
tmp = (ptr_uarts+i)->BytesToRead
tmp++ (in a register)
(ptr_uarts+i)->BytesToRead = tmp
 
If the ISR happens after the first step but before the last step you will receive the same byte twice.
 
You can prevent this from happening by disabling interrupts before calling UartReadByte_32bit(SERIAL_BT, UARTS()) and re-enabling them after it returns.

For better performance you can make the duration of the interrupts being disabled smaller by disabling them inside of that function only when you are accessing a variable that is also being accessed from the ISR.

I will write you a blog post on Microforum.cc to explain this in a lot more detail tomorrow :)




Also take a look at https://www.microforum.cc/ - a great resource for information on PIC and AVR microcontrollers and embedded programming in general. You can also post questions to the experts there.
#6
cobusve
Super Member
  • Total Posts : 493
  • Reward points : 0
  • Joined: 2012/04/02 16:15:40
  • Location: Chandler
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/11 13:58:54 (permalink)
0
I see al_bin has also pointed this out, but you seem to be ignoring his advice?
 

Also take a look at https://www.microforum.cc/ - a great resource for information on PIC and AVR microcontrollers and embedded programming in general. You can also post questions to the experts there.
#7
seccoxiru
Junior Member
  • Total Posts : 96
  • Reward points : 0
  • Joined: 2011/10/27 13:42:59
  • Location: 0
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/11 14:33:49 (permalink)
0
al_bin
Then you probably affected race condition on change BytesToRead in main and interrupt context.
 
In main thread instruction : (ptr_uarts+i)->BytesToRead-- is non atomic.
1. read BytesToRead to register x
2. decrement reg x
3. store x to ptr_uarts
 
If you receive IRQ between point 2 and 3
then incrementing in irq handler is lost.
 
Albert


Hi Albert.
What do you mean with "non atomic"?
Could you explain your post better? I did not understood clearly.
Regards.
#8
seccoxiru
Junior Member
  • Total Posts : 96
  • Reward points : 0
  • Joined: 2011/10/27 13:42:59
  • Location: 0
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/11 14:52:22 (permalink)
4 (1)
cobusve
I see al_bin has also pointed this out, but you seem to be ignoring his advice?

Hi. I have answered him now.
I'm checking your answer. But please take a look at my second post, where I said that I have commented all the other functions called from main (only uart on main), and it worked well at 115200 bps (but I will test this again to have sure). If I call one of these functions (input and output routines) from main the problem appears.
 
About disabling the interrupt, do you mean something like this?
[EDIT]: This solved the problem. Thanks for you.
//-----------------------------------------------------------------------------
uint8_t UartReadByte_32bit (uint8_t uart_n, UART_32bit *ptr_uarts)
{
     uint8_t byte;
     uint8_t i = --uart_n;
 

     byte = (ptr_uarts+i)->RxBuff[(ptr_uarts+i)->RxOutI];
     INTDisableInterrupts();
     (ptr_uarts+i)->BytesToRead--;
     INTEnableInterrupts();
     if ((ptr_uarts+i)->RxOutI != RxBuffLen_32bit-1) { (ptr_uarts+i)->RxOutI++; }
     else { (ptr_uarts+i)->RxOutI = 0; }
 
     return byte;
}
//-----------------------------------------------------------------------------

 
Regards
 
 
 
post edited by seccoxiru - 2019/05/12 13:38:15
#9
cobusve
Super Member
  • Total Posts : 493
  • Reward points : 0
  • Joined: 2012/04/02 16:15:40
  • Location: Chandler
  • Status: offline
Re: UART (or code) having different behaviors for different baudrates - PIC32MX 2019/05/12 17:53:37 (permalink)
0
Here is the link to the detailed explanation I promised to write for you :
https://www.microforum.cc/blogs/entry/39-concurrency-and-race-conditions/
 

Also take a look at https://www.microforum.cc/ - a great resource for information on PIC and AVR microcontrollers and embedded programming in general. You can also post questions to the experts there.
#10
Jump to:
© 2019 APG vNext Commercial Version 4.5