cancel
Showing results for 
Search instead for 
Did you mean: 

Modifying STM32FCubeMX HAL Drivers for UART RX (IT mode) with unknown size data size

pdu-fr
Associate II
Posted on December 30, 2014 at 12:07

Hello,

I am programming a shell based on HAL UART and I experienced difficulties with the HAL UART API provided with CUBEMX. I was using the non-blocking UART Reveice IO function (IT mode).

I have modified the CUBEMX source code (stm32f4xxx_hal_uart.h and.c) to provided theses functionalities :

- New IO functions from Arduino world : Available(), GetChar()

- UART Receive IT handles a circular buffer to store each received byte.

- Receiving a byte does not disable UART Rx IT.

You will find the source code in the next posts of this thread.

Let me know if you know a better solution. Any feedback is appreciated.

Patrick.

#uart-hal-it-byte
18 REPLIES 18
taraben
Senior
Posted on February 03, 2015 at 20:30

Hello Heisenberg,

I do request IT CIRCULAR mode for Receiving and Transmitting in STM HAL.

I implemented the described DMA CIRCULAR receive method.

However sending in nonblocking IT mode is not possible. I have to wait for finishing the current transfer first before initiating the next transfer.

Also I do not know how does DMA CIRCULAR buffer overrun can be detected.

Where can I see the bugtracker for cube libraries / STM HAL?

regards Adib.

--

pdu-fr
Associate II
Posted on February 04, 2015 at 22:35

UART in DMA (circular) mode seems to work fine in RX and TX for me. If you have to send many data at the same time, you should simply use a FIFO between your app and the HAL API.

taraben
Senior
Posted on February 05, 2015 at 12:27

Hello pdu-fr,

could you post a sample for CIRCULAR DMA please.

How can I detect buffer overrun conditions?

Regards,

Adib.

pdu-fr
Associate II
Posted on February 05, 2015 at 18:55

Hey,

I use DMA in normal mode for TX. You just have to give a pointer and a length, to send data over the TX line.

bignukejan
Associate
Posted on August 30, 2015 at 19:02

Hello! Having no experience with this driver in particular and DMA and circular mode specifically, I attempted to recreate your implementation by generating an empty project using STM32CubeMX with USART2 set to asynchronous and configuring the peripheral's DMA settings with an RX Request in circular mode, checking the increment memory address checkbox. The software generated the code (almost) just like you posted.

It placed some of the code (which pretty much matches your code) in functions which I can't see how they're called such asvoid HAL_UART_MspInit(UART_HandleTypeDef* huart). I'm assuming this is called somehow but I can't confirm it. Assuming the generated code is correct, I then copied your snippets in what I thought was a logical way and pieced together this program:

/* USER CODE BEGIN 0 */
#define size_of_rx_circular_buffer 128
uint8_t rx_circular_buffer[size_of_rx_circular_buffer];
uint8_t 
const
* rx_tail_ptr;
/* USER CODE END 0 */
int
main(
void
)
{
/* USER CODE BEGIN 1 */
HAL_UART_Receive_DMA(&huart2, rx_circular_buffer, size_of_rx_circular_buffer);
rx_tail_ptr = rx_circular_buffer;
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
SER_Initialize(); 
//this is from the STM32Cube example which redirects printf 
//to UART2 so I can write debug comments to the COM port. This shouldn't 
//interfer with the Rx DMA, right?
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t 
const
* head = rx_circular_buffer + size_of_rx_circular_buffer - __HAL_DMA_GET_COUNTER(huart2.hdmarx);
uint8_t 
const
* tail = rx_tail_ptr; 
uint8_t count;
while
(1)
{
/* USER CODE END WHILE */

if
( head>=tail )
count = head-tail;
else
count = head-tail+size_of_rx_circular_buffer;
if
(count > 0)
printf
(
''Counting %u
''
, count);
HAL_Delay(1000); 
//I understand this would certainly interfere with blocking mode receiving,
//but does it interfere with DMA mode?
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

The count variable reads 128 no matter what happens on my COM Port console (I use the one from the Arduino IDE for simplicity's sake). I thought the pointer arithmetic seemed a bit off but considering the number is the same regardless of whether I type things on the console or not, I'm guessing there's other problems as well. If you could help me get this simple code to run, I'm sure I could figure out the rest by myself! Thanks a lot! Edit: Noticing an error in the code, I have since added these lines to the start of the while (1) loop:

head = rx_circular_buffer + size_of_rx_circular_buffer - __HAL_DMA_GET_COUNTER(huart2.hdmarx);
tail = rx_tail_ptr;

Cristea.Catalin
Associate III
Posted on September 25, 2015 at 18:38

Hi Heisenberg,

The Cube doesn't allow me to ''un-check'' the ''DMA1 stream 1 global interrupt''.

I suppose could do that manually but the Borg would undo it every time it attacks.

I don't want the interrupt, I just need to get any char that comes over UART3 to get to a circular DMA buffer automagically.

I don't know what I'm missing; I posted my problem/setup in the forum ''Trouble migrating UART USART DMA RX from SPL to HAL''.

pdu-fr
Associate II
Posted on December 30, 2014 at 12:08

How to use :

At setup (call once, IT will remain active during execution):

#define size_of_rx_circular_buffer 80
uint8_t rx_circular_buffer[size_of_rx_circular_buffer];
HAL_UART_Receive_IT(&huart, rx_circular_buffer, size_of_rx_circular_buffer);

In your interpreter :

while( HAL_UART_Available_IT(&huart) > 0 )
{
char c = HAL_UART_GetChar_IT(&huart);
/// your code here...
}

pdu-fr
Associate II
Posted on December 30, 2014 at 12:18

Header patch :

/**
* @brief UART handle Structure definition
*/
typedef struct
{
USART_TypeDef *Instance; /* UART registers base address */
UART_InitTypeDef Init; /* UART communication parameters */
uint8_t *pTxBuffPtr; /* Pointer to UART Tx transfer Buffer */
uint16_t TxXferSize; /* UART Tx Transfer size */
uint16_t TxXferCount; /* UART Tx Transfer Counter */
uint8_t *pRxBuffPtr; /* Pointer to UART Rx transfer Buffer */

/// (===) Patch : Reused as size of Rx circular buffer (Rx IT mode only)

uint16_t RxXferSize; /* UART Rx Transfer size */
///
uint16_t RxXferCount; /* UART Rx Transfer Counter */

/// (+++) Patch : Head of Rx circular buffer (Rx IT mode only)

uint16_t RxXferHead; /* UART Rx Transfer Head */
///

/// (+++) Patch : Tail of Rx circular buffer (Rx IT mode only)

uint16_t RxXferTail; /* UART Rx Transfer Tail */
///
DMA_HandleTypeDef *hdmatx; /* UART Tx DMA Handle parameters */
DMA_HandleTypeDef *hdmarx; /* UART Rx DMA Handle parameters */
HAL_LockTypeDef Lock; /* Locking object */
__IO HAL_UART_StateTypeDef State; /* UART communication state */
__IO HAL_UART_ErrorTypeDef ErrorCode; /* UART Error code */

}UART_HandleTypeDef;

/* IO operation functions *******************************************************/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart);
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
/// (+++) Patch : New IO functions for Rx IT mode
uint16_t HAL_UART_Available_IT(UART_HandleTypeDef *huart);
uint8_t HAL_UART_GetChar_IT(UART_HandleTypeDef *huart);
///

________________

Attachments :

stm32f4xx_hal_uart.h : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzSg&d=%2Fa%2F0X0000000bMi%2FhXBVxofwAUUyqKB9Fk875y3l4K75b.b_FR8KB38OhmU&asPdf=false
pdu-fr
Associate II
Posted on December 30, 2014 at 12:23

Source code patch :

/**
* @brief Receives an amount of data in non blocking mode
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint32_t tmp1 = 0;
tmp1 = huart->State;
if((tmp1 == HAL_UART_STATE_BUSY_RX) || (tmp1 == HAL_UART_STATE_BUSY_TX_RX))
{
if(huart->Init.WordLength == UART_WORDLENGTH_9B)
{
/// (---) Patch : Point to the head of Rx circular buffer
//tmp = (uint16_t*) huart->pRxBuffPtr;
/// (+++) Patch : Point to the head of Rx circular buffer
tmp = (uint16_t*)( huart->pRxBuffPtr + huart->RxXferHead );
///
if(huart->Init.Parity == UART_PARITY_NONE)
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
/// (---) Patch : Do not auto inc memory
//huart->pRxBuffPtr += 2;
/// (+++) Patch : Auto inc head of Rx circular buffer
huart->RxXferHead += 2;
huart->RxXferHead %= huart->RxXferSize;
///
}
else
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
/// (---) Patch : Do not auto inc memory
//huart->pRxBuffPtr += 1;
/// (+++) Patch : Auto inc head of Rx circular buffer
huart->RxXferHead += 1;
huart->RxXferHead %= huart->RxXferSize;
///
}
}
else
{
if(huart->Init.Parity == UART_PARITY_NONE)
{
/// (---) Patch : Do not auto inc memory & Point to the head of the Rx circular buffer
//*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
/// (+++) Patch : Point to the head of the Rx circular buffer & Auto inc head of Rx circular buffer
huart->pRxBuffPtr[huart->RxXferHead] = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
++huart->RxXferHead;
huart->RxXferHead %= huart->RxXferSize;
///
}
else
{
/// (---) Patch : Do not auto inc memory & Point to the head of the Rx circular buffer
//*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
/// (+++) Patch : Point to the head of the Rx circular buffer & Auto inc head of Rx circular buffer
huart->pRxBuffPtr[huart->RxXferHead] = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
++huart->RxXferHead;
huart->RxXferHead %= huart->RxXferSize;
///
}
}
/// (---) Patch : Do not DISABLE IT
// if(--huart->RxXferCount == 0)
// {
// __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
//
// /* Check if a transmit process is ongoing or not */
// if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
// {
// huart->State = HAL_UART_STATE_BUSY_TX;
// }
// else
// {
// /* Disable the UART Parity Error Interrupt */
// __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
//
// /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
// __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
//
// huart->State = HAL_UART_STATE_READY;
// }
// //HAL_UART_RxCpltCallback(huart);
//
// return HAL_OK;
// }
///
/// (+++) Patch : Call it fot every received byte
HAL_UART_RxCpltCallback(huart);
///
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
uint16_t HAL_UART_Available_IT(UART_HandleTypeDef *huart)
{
if( huart->RxXferHead >= huart->RxXferTail )
{
return huart->RxXferHead - huart->RxXferTail;
}
else
{
return huart->RxXferHead + huart->RxXferSize - huart->RxXferTail;
}
}
uint8_t HAL_UART_GetChar_IT(UART_HandleTypeDef *huart)
{
if( huart->RxXferTail == huart->RxXferHead )
return 0;
uint8_t c = huart->pRxBuffPtr[huart->RxXferTail];
++huart->RxXferTail;
huart->RxXferTail %= huart->RxXferSize;
return c;
}

________________

Attachments :

stm32f4xx_hal_usart.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzUR&d=%2Fa%2F0X0000000bMf%2F9s9rJCIj9KPOc1RjyDMU6KCyGxVzkn1rG5l1LoexlCA&asPdf=false