2022-01-13 07:59 AM
Hi everyone, im using an STM32WB and i just managed to get my own BLE<->UART bridge to "half work".
But my problem is about UART managing.
If i receive data with length of less than 247bytes(set by me) just stays in the rx bufer and no DMA transfer complete happens.
I set up the DMA to listen for the next incoming 247 bytes
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, NotifyCharData, RxBuf_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);//we dont want the half done transaction interrupt
Whenever the data arrives(stream of data uartRx) ,it gets written into a BLE characteristic, everything works like a charm, but if the last uart received message is less than 247length DMA rx doesnt trigger after an idle time.
No IDLE event occurs.
/**
* @brief Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs.
* @note Reception is initiated by this function call. Further progress of reception is achieved thanks
* to DMA services, transferring automatically received data elements in user reception buffer and
* calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
* reception phase as ended. In all cases, callback execution will indicate number of received data elements.
* @note When the UART parity is enabled (PCE = 1), the received data contain
* the parity bit (MSB position).
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
* of uint16_t available through pData.
* @note Dual core specific: there is no support for unaligned accesses on the Cortex-M0+ processor.
* When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* address of user data buffer for storing data to be received, should be aligned on a half word frontier (16 bits)
* (as received data will be handled by DMA from halfword frontier). Depending on compilation chain,
* use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData.
* @param huart UART handle.
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
I dont even know what does an "IDLE event" mean, i tought DMA triggered after a short time of bus inactivity (as seen in this video ) but no.
Solved! Go to Solution.
2022-01-14 04:22 AM
The code of HAL_UARTEx_ReceiveToIdle_DMA() will enable the IDLEIE bit, so enable the IDLE interrupt source inside the UART instance. Now in order to be genrated and processed the UART IRQ at NVIC side should also be enabled.
If you generate your code using STM32CubeMx tool, please make sure you do it in your UART configuration panel. (See below pic).
If not, IRQ could be enabled in MSP_Init functions (as HAL_UART_MspInit) by below code :
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
Guenael
2022-01-13 08:24 AM
Do you have HAL_UARTEx_RxEventCallback implemented?
The TC IRQ won't fire unless you receive all characters.
2022-01-13 08:27 AM
Hi @TDK , yes, it is implemented
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
//restarts the DMA listening of the UART rx (next 247 bytes)
if(huart->Instance ==USART1){
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, NotifyCharData, RxBuf_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
}
return;
}
>>The TC IRQ won't fire unless you receive all characters.
What about that "idle event".
Isnt there a programmable timeout i can use for the TC interruption to trigger even if the buffer is not full?
2022-01-13 08:40 AM
Hi @Javier Muñoz
DMA Transfer complete is a DMA interrupt, whilst IDLE Line event will be indicated through the USART interrupt. Please make sure USART interrupt, is enabled and handled using HAL IRQ handler.
Regards
2022-01-13 08:45 AM
The HAL_UARTEx_RxEventCallback function gets called at every HT, TC, or IDLE event. You should do your character reception within there. Probably better to use the buffer in circular mode rather than restarting as the reception may still be going when that function is called.
See one possible implementation of HAL_UARTEx_RxEventCallback here:
Some explanation of how it all works is here:
2022-01-14 02:13 AM
@TDK
Im working on implementing that circular buffer you suggested, ill post the result of that.
I still dont know what IDLE event is, (from the readme.txt you sent me)
- Idle Event on Rx line : Triggered when RX line has been in idle state (normally high state)
for 1 frame time, after last received byte.
I dont think the STLINK's uart does that IDLE line thing when no activity happened.
2022-01-14 02:29 AM
HI @Javier Muñoz
An Idle character is considered to be an entire frame of “1�?s (the number of “1�?s includes the number of stop bits). See below picture to be more clear.
After some activity on RX line, when an inactivity period lasting at least one character is detected (Idle state), the IDLE event is considered as occurring. If IDLEIE interrupt is enabled, then an interrupt is raised. This interrupt is used to inform application, in case HAL_UARTEx_ReceiveToIdle_DMA() has been called.
It corresponds to an inactivity period occuring after some reception.
Hope this helps.
Guenael
2022-01-14 02:40 AM
Thanks @Guenael Cadier , so after sniffing the uart line i recognice IDLE times that should be detected by the ST32WB's uart
>>If IDLEIE interrupt is enabled,
Ill look into this
I only found this enables: (stm32wbxx_hal_dma.h)
/** @defgroup DMA_interrupt_enable_definitions DMA interrupt enable definitions
* @{
*/
#define DMA_IT_TC LL_DMA_CCR_TCIE /*!< Transfer complete interrupt */
#define DMA_IT_HT LL_DMA_CCR_HTIE /*!< Half Transfer interrupt */
#define DMA_IT_TE LL_DMA_CCR_TEIE /*!< Transfer error interrupt */
/**
* @}
*/
Found it: (stm32wbxx_hal_uart,h)
/** @defgroup UART_Interrupt_definition UART Interrupts Definition
* Elements values convention: 000ZZZZZ0XXYYYYYb
* - YYYYY : Interrupt source position in the XX register (5bits)
* - XX : Interrupt source register (2bits)
* - 01: CR1 register
* - 10: CR2 register
* - 11: CR3 register
* - ZZZZZ : Flag position in the ISR register(5bits)
* Elements values convention: 000000000XXYYYYYb
* - YYYYY : Interrupt source position in the XX register (5bits)
* - XX : Interrupt source register (2bits)
* - 01: CR1 register
* - 10: CR2 register
* - 11: CR3 register
* Elements values convention: 0000ZZZZ00000000b
* - ZZZZ : Flag position in the ISR register(4bits)
* @{
*/
#define UART_IT_PE 0x0028U /*!< UART parity error interruption */
#define UART_IT_TXE 0x0727U /*!< UART transmit data register empty interruption */
#define UART_IT_TXFNF 0x0727U /*!< UART TX FIFO not full interruption */
#define UART_IT_TC 0x0626U /*!< UART transmission complete interruption */
#define UART_IT_RXNE 0x0525U /*!< UART read data register not empty interruption */
#define UART_IT_RXFNE 0x0525U /*!< UART RXFIFO not empty interruption */
#define UART_IT_IDLE 0x0424U /*!< UART idle interruption <------------------------------------ */
#define UART_IT_LBD 0x0846U /*!< UART LIN break detection interruption */
#define UART_IT_CTS 0x096AU /*!< UART CTS interruption */
#define UART_IT_CM 0x112EU /*!< UART character match interruption */
#define UART_IT_WUF 0x1476U /*!< UART wake-up from stop mode interruption */
#define UART_IT_RXFF 0x183FU /*!< UART RXFIFO full interruption */
#define UART_IT_TXFE 0x173EU /*!< UART TXFIFO empty interruption */
#define UART_IT_RXFT 0x1A7CU /*!< UART RXFIFO threshold reached interruption */
#define UART_IT_TXFT 0x1B77U /*!< UART TXFIFO threshold reached interruption */
#define UART_IT_RTO 0x0B3AU /*!< UART receiver timeout interruption */
#define UART_IT_ERR 0x0060U /*!< UART error interruption */
#define UART_IT_ORE 0x0300U /*!< UART overrun error interruption */
#define UART_IT_NE 0x0200U /*!< UART noise error interruption */
#define UART_IT_FE 0x0100U /*!< UART frame error interruption */
/**
* @}
*/
2022-01-14 03:08 AM
im trying out __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); but no luck either....
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
//restarts the DMA listening of the UART rx (next 247 bytes)
if(huart->Instance ==USART1){
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, NotifyCharData, RxBuf_SIZE);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
}
return;
}
2022-01-14 04:22 AM
The code of HAL_UARTEx_ReceiveToIdle_DMA() will enable the IDLEIE bit, so enable the IDLE interrupt source inside the UART instance. Now in order to be genrated and processed the UART IRQ at NVIC side should also be enabled.
If you generate your code using STM32CubeMx tool, please make sure you do it in your UART configuration panel. (See below pic).
If not, IRQ could be enabled in MSP_Init functions (as HAL_UART_MspInit) by below code :
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
Guenael