Hi,
I'm trying to implement following protocol for variable length packet reception over UART.
Using non blocking DMA functions - LPUART_ReceiveEDMA().
Running EmbOS.
Packet Structure
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte n | Byte 3+Length-1|
| Start Byte | Length MSB | Length LSB | Data[0] | Data[n-3] | Data[Length-1] |
Firmware Operation
1. Prepare receive of header size (3 bytes)
2. Receive interrupt, read out the length
3. Prepare a second receive using the length in header (inside the IRQ)
4. Receive interrupt after full length has been received
The issue is, that sometimes I get to the interrupt handler and the buffer I provided to DMA is empty.
Meaning the interrupt occurred, but no data is placed in the destination buffer.
Could there be an issue with calling LPUART_ReceiveEDMA from an interrupt handler?
What could cause the described scenario?
Thanks,
Ira.
Hi,
Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
According to your description, it needs to receive the first three bytes via interrupt handler prior to setting the DMA TCD to receive the rest of the incoming data. Is my understanding right?
Meanwhile, I'd like to know the probability of arising the phenomenon? In further, is the incoming packet data continuous?
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi @jeremyzhou ,
The first 3 bytes are also received using DMA. The interrupt handler mentioned is of the LPUART EDMA transfer.
This happens every time I start the application, I receive only the first 3 bytes and then get an empty destination buffer although DMA interrupt occurred.
Due to the nature of the data handling in upper layers, the rest of the application is prevented from running in this case.
Thanks,
Ira.
Hi,
Thanks for your reply.
I was wondering if you can introduce the refinement of LPUART_ReceiveEDMA() to implement your goal in detail,
further, I'd like to know the probability of arising the phenomenon? And is the incoming packet data continuous?
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi @jeremyzhou ,
What do you mean by "introduce the refinement of LPUART_ReceiveEDMA()"?
"I'd like to know the probability of arising the phenomenon?"
This happens every time I start the application, I receive only the first 3 bytes and then get an empty destination buffer although DMA interrupt occurred.
"And is the incoming packet data continuous?"
Yes
Thanks,
Ira.
Hi,
Thanks for your reply.
1) What do you mean by "introduce the refinement of LPUART_ReceiveEDMA()"?
-- I was wondering if you can introduce what code modification you did to implement your purpose in detail.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi @jeremyzhou ,
I did not change the LPUART_ReceiveEDMA() function internal implementation.
I'm just using it as is, 2 times for each packet- once for the header, and the second time for the packet body.
Each time I receive the DMA interrupt saying that transfer is done, I activate the DMA for next transaction.
This is the callback function:
if (RX_STATE_HEADER == g_rxDblBuff[ch].state)
{
/* Header received */
uint16_t body_length = g_rxDblBuff[ch].p_curr->buff[RX_HEADER_LENGTH-1];
g_rxDblBuff[ch].state = RX_STATE_BODY;
g_rxDblBuff[ch].p_curr->len = RX_HEADER_LENGTH + body_length;
g_rxDblBuff[ch].p_curr->uartCh = ch;
/* Restart Rx DMA for Body*/
Uart_RxTransfer.data = &g_rxDblBuff[ch].p_curr->buff[RX_HEADER_LENGTH];
Uart_RxTransfer.dataSize = body_length;
Uart_Status = LPUART_ReceiveEDMA(LPUART7_PERIPHERAL, &LPUART7_LPUART_eDMA_Handle, &Uart_RxTransfer);
}
else if (RX_STATE_BODY == g_rxDblBuff[ch].state)
{
/* Keep current pointer */
UART_RxBuffItem_t* p_curr = g_rxDblBuff[ch].p_curr;
/* Restart Rx DMA for header */
g_rxDblBuff[ch].state = RX_STATE_HEADER;
g_rxDblBuff[ch].p_curr = g_rxDblBuff[ch].p_next;
Uart_RxTransfer.data = &g_rxDblBuff[ch].p_curr->buff[0];
Uart_RxTransfer.dataSize = RX_HEADER_LENGTH;
Uart_Status = LPUART_ReceiveEDMA(LPUART7_PERIPHERAL, &LPUART7_LPUART_eDMA_Handle, &Uart_RxTransfer);
}
Thanks,
Ira.
Hi,
Thanks for your reply.
In my opinion, you'd better take advantage of the OS benefit and use two separate tasks to call the LPUART_SendEDMA to receive the head and body parts, for instance, the Task1 call the LPUART_SendEDMA to receive the head and after finishing, send a message to activate the Task2 and set data size of the body to receive the rest data, just like the below figure shows.
Please give it a try.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Thanks for your reply @jeremyzhou !
I'm afraid that in the change proposed by you, some bytes from the packet will be missed, since UART mechanism wasn't reset fast enough.
Header and data are sent contentiously, without a pause between them.
Could you please tell me what seems to be the issue in my initial implementation?
Thanks,
Ira.
Hi,
Thanks for your reply.
1) Could you please tell me what seems to be the issue in my initial implementation?
-- Just as you said above, header and data are sent continuously, without a pause between them and I think it's the cause.
Maybe you can modify the packet frame structure, for instance, insert some null data between length parameter and body partials and use the interrupt way to receive the length parameter, after receiving it, update the DMA TCD to receive the incoming body data later, null data in front of the body data, which allow MCU gain enough time to handle the length parameter
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi @jeremyzhou ,
Changing the protocol timing isn't an option.
This has been implemented before on STM32 chip with FreeRTOS, and the goal is to imlement it again on NXP with EmbOS.
I believe I'm currently not using TCD, can you please elaborate on that?
Thanks,
Ira.
Hi,
Thanks for your reply.
I was wondering if you can describe the software flow of the implementation in the ST32 in detail, then I can share some more appropriate advice.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi @jeremyzhou ,
It's the same implementation.
UART+DMA. DMA is reset for next part (body/header) inside the interrupt handler.
What can TCD be used for? I tried looking into it in the user manual, but am still missing information.
Please advise.
Thanks,
Ira.
Hi,
Thanks for your reply.
1)What can TCD be used for?
-- The TCD means Transfer Control Descriptor which is used to configure the DMA registers to initiate a new DMA transfer.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------