2025-02-13 07:48 AM
Hello,
I am trying to use the HAL_UARTEx_ReceiveToIdle_DMA function() but the IDLE function don't work.
I call the function here :
/* Extern variables */
extern UART_HandleTypeDef huart4;
extern osEventFlagsId_t comEventHandle;
extern osMessageQueueId_t sensorQueueHandle;
extern osEventFlagsId_t regEventHandle;
extern DMA_HandleTypeDef hdma_uart4_rx;
static void modbus_receive_DMA(void) {
buf_rec = 0; // reset the counter of received bytes in the buffer
/* Reset pin for receiving data */
HAL_GPIO_WritePin(RS485_SIEMENS_RE_GPIO_Port, RS485_SIEMENS_RE_Pin, GPIO_PIN_RESET);
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart4, nmbs.msg.buf, sizeof(nmbs.msg.buf)) != HAL_OK) {
log_debug("HAL_UARTEx_ReceiveToIdle_DMA error");
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart4) {
modbus_receive_DMA();
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart == &huart4) {
switch (HAL_UARTEx_GetRxEventType(huart)) {
case HAL_UART_RXEVENT_IDLE: // when Idle event occurred prior reception has
// been completed (nb of received data is lower
// than expected one).
packet_sended = 0; // clear flag of transmit
buf_rec = Size; // set size of received data
nmbs_error res_poll = nmbs_server_poll(&nmbs);
if (NMBS_ERROR_NONE != res_poll) {
// This will probably never happen, since we don't return < 0 in our
// platform funcs
}
// If there was no packet transmission, then we immediately switch to
// receive mode. Otherwise, this function will trigger an interrupt at the
// end of DMA packet transmission
if (!packet_sended)
modbus_receive_DMA();
break;
}
}
}
I have tryed to replace sizeof(nmbs.msg.buf) by 1 or 2 or 3 and it works but not in IDLE mode. So the function HAL_UARTEx_RxEventCallback works but not in the right way. I have seen on the forum lot of topics with the same problem but I am not able to fix it with my micro..
Do you have any idea ?
2025-02-13 08:08 AM
Probably you are not handling the half-complete interrupt.
What is sizeof(nmbs.msg.buf)?
How many bytes are you expecting at the IDLE event?
How many bytes does it say are received?
/**
* @brief Provide Rx Event type that has lead to RxEvent callback execution.
* @note When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
* of reception process is provided to application through calls of Rx Event callback (either default one
* HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
* Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
* to Rx Event callback execution.
* @note This function is expected to be called within the user implementation of Rx Event Callback,
* in order to provide the accurate value :
* In Interrupt Mode :
* - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
* - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
* received data is lower than expected one)
* In DMA Mode :
* - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
* - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
* - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
* received data is lower than expected one).
* In DMA mode, RxEvent callback could be called several times;
* When DMA is configured in Normal Mode, HT event does not stop Reception process;
* When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
* @PAram huart UART handle.
* @retval Rx Event Type (return vale will be a value of @ref UART_RxEvent_Type_Values)
*/
HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(const UART_HandleTypeDef *huart)
2025-02-13 08:15 AM - edited 2025-02-13 08:22 AM
Hello TDK,
I have tried to disabled the IT at the half-complete :
if (HAL_UARTEx_ReceiveToIdle_DMA(&huart4, nmbs.msg.buf, sizeof(nmbs.msg.buf)) != HAL_OK) {
log_debug("HAL_UARTEx_ReceiveToIdle_DMA error");
}
__HAL_DMA_DISABLE_IT(&hdma_uart4_rx, DMA_IT_HT);
but nothing changed
the size of sizeof(nmbs.msg.buf) is 260. I just tested it now with a lenght of 20. Nothing changed.. :
typedef struct nmbs_t {
struct {
uint8_t buf[260];
uint16_t buf_idx;
uint8_t unit_id;
uint8_t fc;
uint16_t transaction_id;
bool broadcast;
bool ignored;
} msg;
nmbs_callbacks callbacks;
int32_t byte_timeout_ms;
int32_t read_timeout_ms;
nmbs_platform_conf platform;
uint8_t address_rtu;
uint8_t dest_address_rtu;
uint16_t current_tid;
} nmbs_t;
I am expecting (for my current test) 8bytes.
How many bytes does it say are received? I don't know how to check that.
2025-02-13 09:22 AM
Size is not technically the amount of bytes received, but actually a pointer to where the DMA saved the last byte in the buffer. Size is not zero based, so it starts at 1 and goes up to <size of your buffer>
See this project. This uses a pointer to keep track of the DMA data that is being received.
https://github.com/karlyamashita/Nucleo-G071RB_UART_DMA_Idle_Circular/wiki