2017-10-03 10:54 AM
MCU: STM32F765
Using FreeRtos
2017-10-03 11:07 AM
The data is of variable length, so fixed length DMA transfer is not suitable
2017-10-03 11:44 AM
A good rule of thumb is to use SIGNALS for ISRs and have the receiving and transmissions in separatetasks.
Here's anexample:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3)
{
osSemaphoreRelease(host_tx_semHandle);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3 )
{
osSignalSet( host_rx_taskHandle, HOST_RX_ISR_FLAG );
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
These are the handlers for the tasks. On the transmission, I'm using DMA, so when the UART is finished transmission the semaphore is released.
Here are the tasks:
void host_rx_process(void const * argument)
{
// Buffer to hold message
static uint8_t rx_buffer[HOST_RX_BUFFER] = {0};
static uint8_t index = 0;
static bool in_frame = false;
uint8_t tmp_char = 0;
HAL_UART_Receive_IT( &huart3, rx_tmp_buffer, 1 );
for(;;)
{
osSignalWait( HOST_RX_ISR_FLAG, osWaitForever );
tmp_char = *( huart3.pRxBuffPtr - huart3.RxXferSize );
// Do whatever needs to be done to the new char that just arrived
//....
// Be sure to set the interrupt for the next char
if( HAL_UART_Receive_IT( &huart3, (huart3.pRxBuffPtr - huart3.RxXferSize), 1 ) != HAL_OK)
{
Error_Handler();
}
}
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
What's important here is that I'm waiting for the signal to the rx process which is set by the ISR handler. Doing this saves the most amount of cycles on the ISR so the RTOS can manage the tasks effectively.
2017-10-03 02:18 PM
Read it into a buffer? State machine processing/parsing in the USART IRQHandler?
2017-10-03 02:36 PM
Thanks Clive, Yes, I was thinking I'll have to use receive interrupt and write to a fifo, then read it out and process in a task.
2017-10-03 02:42 PM
DMA does a great job of transferring data using the FIFO buffer, and writing 32b words into memory. You need to use a communication protocol that is understandable for both sides. Even if you use your own unique data container, the required number of received or transmitted data will always be known. It came with an error in the transfer - just request the whole package again. Make it once, and use it in all your projects. Because it is a universal thing. It does not depend on the processor used, it does not depend on the compiler, it's just an algorithm - which will always be executed. Although it is much more logical to take a suitable example from an open repository, for example with GIT.
Option when the amount of data is unknown, or just laziness.
Use of cyclic variant of DMA operation, without checks, without detectors, without hardware capabilities of the uart block. This is a mega custom level of arduino in programming - where the contents of the memory of the receiving buffer are checked programmatically in continuous mode. Search there the same.2017-10-03 02:49 PM
Depends a lot of the type and volume of the data. I tend to create a sufficiently deep FIFO buffer to hold a packet, or manage processing latency, with a rapid IRQ and then have a consuming task pull and process the data in a less time critical manner.
I would generally avoid using the USART IRQ handler from causing a task switch
2017-10-10 10:58 AM
Thanks Richard. The receive process works well.
How would the transmit process work please ?
2017-10-10 11:32 AM
Something like:
void host_tx_process(void const * argument)
{
osEvent evt;
for(;;)
{
evt = osMessageGet(host_tx_handle, WDT_MAX_WAIT_TIME );
if( evt.status == osEventMessage )
{
message_t *msg = (message_t*)evt.value.p;
// Take binary semaphore for UART
osSemaphoreWait(host_tx_semHandle, osWaitForever);
memcpy( (void*)&tx_buffer[4], (void*)msg->buffer, msg->msg_len );
tx_buffer[msg->msg_len++] = END_OF_FRAME;
HAL_UART_Transmit_DMA( &huart3, (uint8_t*)tx_buffer, msg->msg_len );
osPoolFree( message_pool, msg );
}
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
My application is specific, but the idea is passing a message to the host transmit thread and it sends everything over DMA.
2017-11-06 02:29 PM
This goes wrong if data received very fast (streamed) and can only recover with another call to
HAL_UART_Receive_IT( &huart5, RxBuffer, 1 );
Somehow the signal is missed.
Any ideas what's wrong?
void vGPRSTaskRx(void * pvParameters)
{ HAL_UART_Receive_IT( &huart5, RxBuffer, 1 );while(1)
{ osSignalWait( HOST_RX_ISR_FLAG, osWaitForever );ch = *( huart5.pRxBuffPtr - huart5.RxXferSize );
/* Echo .... */
GPRSSendByte(ch);if ( HAL_UART_Receive_IT(&huart5, RxBuffer, 1) != HAL_OK )
{ Error_Handler(); } }}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){ if(UartHandle->Instance == UART5) { osSignalSet( xGPRSRxTaskHandle, HOST_RX_ISR_FLAG ); }}