Hi everyone, I need some advice or help.
I’m having an issue with a uart1 ISR and active object implementation. I have an ISR that is triggered when the uart buffer has data. On entering the ISR a new from ISR event is requested from QF, data from the uart buffer is saved into the new event object, the same data is output to the terminal using another (Uart0) with in the ISR.
This part is working as expected the second uart0 echo’s the data received by uart1. If 1234 is sent 1234 is echoed back. After the echo process, the data is posted to the AO_uart for processing ending the ISR.
In the AO the uart event handler just passes the data out to the terminal on uart0. With the same input of 1234 the uart from the AO prints out the last 2 values 34. Sending 1 char at time rapidly works perfectly, no data is lost. Sending 2 or 4 char at the same time, results in the first char is lost, sending 6 chars only the 2nd,4th and 6th are received by the AO.
I’m using the DPP FreeRTOS port example version 6.4.0 as a starting point on the tm4c123, the baud rate is 9600
it takes about 10us for the uart ISR to collect data and post an evt. Any ideas as to why I’m losing the data bytes, are the events coming too fast for the AO? Which would not make any sense as the events will still be stored in the event queue.
caseNEW_UART_DATA_SIG:{chartemp=Q_EVT_CAST(UartEvt)->temp;UART0_OutChar(Q_EVT_CAST(UartEvt)->temp);status_=Q_HANDLED();break;}voidUART1_IRQHandler(void){BaseType_txHigherPriorityTaskWoken=pdFALSE;uint32_tstatus=UART1->RIS;/* get the raw interrupt status */UART1->ICR=status;/* clear the asserted interrupts */UartEvt*character=Q_NEW_FROM_ISR(UartEvt,NEW_UART_DATA_SIG);while(((UART1->FR&UART_FR_RXFE)==0)){/* while RX FIFO NOT empty */character->temp=UART1_CHAR;QACTIVE_POST_FROM_ISR(AO_BLE_uart,(QEvt*)character,&xHigherPriorityTaskWoken,&UART0_IRQHandler);}}
I guess that your intention was to create a new event for every character received.
You should move Q_NEW_FROM_ISR()into your while loop to achieve that. Otherwise you are just overwriting character->temp of the same event while sitting in the loop.
Last edit: Gawie de Vos 2021-09-01
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Eddie,
Your code seems to be wrong in so many ways that I'm not sure where to begin.
So, perhaps first let's talk about your design. Your UART apparently has a FIFO, so it can transmit or receive several characters at a time, up to the FIFO capacity. Consequently, it seems reasonable to actually use this feature. Specifically, instead of receiving one character at a time, and then posting an event with this one character as parameter, you could receive all characters from the FIFO into a single event and then post that event. Similarly, you can load the FIFO with several characters to send and then let the UART do the sending. If the FIFO has, say 16 slots, this would be 16 times more efficient than your design. That's the whole point of having a hardware FIFO.
So, here is your custom UartEvt event that can hold :
As you can see, you build the the event in the while() loop and fill it with all the bytes currently available in the FIFO. You also store the actual number of bytes in the evt->len parameter. Then you post the whole event just once per ISR invocation, instead of many times as before.
Also, your ISR code did not have the FreeRTOS call to portEND_SWITCHING_ISR(). This is a bizarre aspect of the FreeRTOS design, and that's why you have the "xHigherPriorityTaskWoken" variable.
Now, regarding the processing of the NEW_UART_DATA_SIG signal in your active object, here is some pseudocode:
Hi Miro
Thanks for the very detailed explanation much appreciated, learning a lot. Your explanation (example) is in line with what I discovered after extensive debugging and datasheet reading, I had made bad assumptions. I was not of the best way to proceed, your example and explanation helped solve that issue. Thanks again.
Eddie.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi everyone, I need some advice or help.
I’m having an issue with a uart1 ISR and active object implementation. I have an ISR that is triggered when the uart buffer has data. On entering the ISR a new from ISR event is requested from QF, data from the uart buffer is saved into the new event object, the same data is output to the terminal using another (Uart0) with in the ISR.
This part is working as expected the second uart0 echo’s the data received by uart1. If 1234 is sent 1234 is echoed back. After the echo process, the data is posted to the AO_uart for processing ending the ISR.
In the AO the uart event handler just passes the data out to the terminal on uart0. With the same input of 1234 the uart from the AO prints out the last 2 values 34. Sending 1 char at time rapidly works perfectly, no data is lost. Sending 2 or 4 char at the same time, results in the first char is lost, sending 6 chars only the 2nd,4th and 6th are received by the AO.
I’m using the DPP FreeRTOS port example version 6.4.0 as a starting point on the tm4c123, the baud rate is 9600
it takes about 10us for the uart ISR to collect data and post an evt. Any ideas as to why I’m losing the data bytes, are the events coming too fast for the AO? Which would not make any sense as the events will still be stored in the event queue.
Uart ISR----------------------------------------------------------
~~~
Last edit: Eddie_1066 2021-09-01
I guess that your intention was to create a new event for every character received.
You should move
Q_NEW_FROM_ISR()
into your while loop to achieve that. Otherwise you are just overwritingcharacter->temp
of the same event while sitting in the loop.Last edit: Gawie de Vos 2021-09-01
Hi Eddie,
Your code seems to be wrong in so many ways that I'm not sure where to begin.
So, perhaps first let's talk about your design. Your UART apparently has a FIFO, so it can transmit or receive several characters at a time, up to the FIFO capacity. Consequently, it seems reasonable to actually use this feature. Specifically, instead of receiving one character at a time, and then posting an event with this one character as parameter, you could receive all characters from the FIFO into a single event and then post that event. Similarly, you can load the FIFO with several characters to send and then let the UART do the sending. If the FIFO has, say 16 slots, this would be 16 times more efficient than your design. That's the whole point of having a hardware FIFO.
So, here is your custom
UartEvt
event that can hold :Now, the UART receive ISR:
As you can see, you build the the event in the while() loop and fill it with all the bytes currently available in the FIFO. You also store the actual number of bytes in the evt->len parameter. Then you post the whole event just once per ISR invocation, instead of many times as before.
Also, your ISR code did not have the FreeRTOS call to portEND_SWITCHING_ISR(). This is a bizarre aspect of the FreeRTOS design, and that's why you have the "xHigherPriorityTaskWoken" variable.
Now, regarding the processing of the NEW_UART_DATA_SIG signal in your active object, here is some pseudocode:
Again, you process all the "len" received bytes in the event.
I hope that this design makes some sense to you.
--MMS
Hi Miro
Thanks for the very detailed explanation much appreciated, learning a lot. Your explanation (example) is in line with what I discovered after extensive debugging and datasheet reading, I had made bad assumptions. I was not of the best way to proceed, your example and explanation helped solve that issue. Thanks again.
Eddie.
Last edit: Eddie_1066 2021-09-01