cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 StEmWin CMSIS + USART DMA Issue

Grozea.Ion
Associate II
Posted on July 05, 2017 at 23:58

Hi,

I have a small code for for UART7 Rx DMA circular buffer and Tx DMA normal buffer, this code runs normal with a basic setup generated using CubeMX.

Once i am adding the code in in LCD application running CMSIS on a GUI thread, the UART DMA code doesn't run as expected.

I have created a new thread for the UART DMA with normal/high priority and 1024bytes for stack, the behavior is better but still unreliable.

Does anyone can help me on how to set up CMSIS in order to have the UART DMA work in a reliable way?

Thank you

#stemwin #uart-dma #cmsis-rtx
3 REPLIES 3
Posted on July 06, 2017 at 01:01

Just sticking in arbitrary stack sizes in hopes of remediating problems is not the way to go, understand what you're using and should expect to be using, look at your call-trees and how the code is expected to act.

Using the stack for DMA is generally problematic, the HW DMA can significantly outlive the scope of auto/local space allocated on the stack frame, and cause corruption.

Reliability in multi-thread systems frequently comes down to appropriate ownership of resources and serialization of those resources. Not sure what 'unreliable' in your context actually means, you'll need to debug and refine that somewhat so you understand what interactions are occurring.

With HAL related code watch carefully for code that blocks, if code is appropriate in interrupt (callback) context, and if you have loops dependent on interrupts at the same or lower priority.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 06, 2017 at 22:42

Hello Clive,

The stack size is not arbitrary, it was determined based on needs (the UART DMA was in the GUI thread).

In my case unreliable means that the transmitting side of the UART DMA (i have check the RX and i don't notice any issue) is loosing bytes, when i put in the Tx buffer abcdef only adef is sent but this doesn't happen all the time.

I belive that the NVIC is set ok for CMSIS usage

/* UART7 interrupt Init */

HAL_NVIC_SetPriority(UART7_IRQn, 5, 0);

HAL_NVIC_EnableIRQ(UART7_IRQn);

/* DMA1_Stream1_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0);

HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

/* DMA1_Stream3_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0);

HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);

I am trying to find a CMSIS example for UART and maybe i will notice something there.

Thank you for your reply.

Grozea.Ion
Associate II
Posted on July 11, 2017 at 08:07

Hi,

I am still stuck here , below is the code used

in the main

extern volatile uint8_t TxBuffer[RXBUFFERSIZE];

uint8_t cnt, myVal, myToogle;

int main(void)

{

MPU_Config();

CPU_CACHE_Enable();

#ifdef RTE_CMSIS_RTOS // when using CMSIS RTOS

osKernelInitialize(); // initialize CMSIS-RTOS

#endif

HAL_Init();

BSP_SDRAM_Init();

/* Configure the System clock to have a frequency of 216 MHz */

SystemClock_Config();

myGPIO_Init();

myUART_Init();

myADC_Init();

#ifdef RTE_CMSIS_RTOS // when using CMSIS RTOS

Init_GUIThread();

//Init_Thread_UART();

osKernelStart(); // start thread execution

#endif

myTime = HAL_GetTick();

Xbee_Init();

while (1)

{

cnt = 0;

while(Xbee_hasData())

{

myVal = Xbee_Read();

TxBuffer[cnt] = myVal;

printf('Rx-> %c Tx->%c\n', myVal, TxBuffer[cnt]);

cnt++;

}

if(cnt){

SendToXbee(cnt);

}

osDelay(5);

}

}

In myUART.h 

extern UART_HandleTypeDef huart7;

#define RXBUFFERSIZE 32

#define RXBUFFERSIZE1 RXBUFFERSIZE - 1

#define charMask 0x227FFFFF

extern volatile uint8_t TxBuffer[RXBUFFERSIZE];

void myUART_Init(void);

void Xbee_Init(void);

uint8_t Xbee_get(void);

uint8_t Xbee_available(void);

uint8_t Xbee_hasData(void);

uint8_t Xbee_Read(void);

void SendToXbee(uint8_t len);

extern void _Error_Handler(char *, int);

In myUART.c

#include 'myUART.h'

UART_HandleTypeDef huart7;

DMA_HandleTypeDef hdma_uart7_rx;

DMA_HandleTypeDef hdma_uart7_tx;

__IO ITStatus UartReady = RESET;

volatile uint8_t RxBuffer[RXBUFFERSIZE];

volatile uint8_t TxBuffer[RXBUFFERSIZE];

#define _headPtr ((RXBUFFERSIZE - huart7.hdmarx->Instance->NDTR) & RXBUFFERSIZE1)

static uint32_t _tailPtr;

/* UART7 init function */

void myUART_Init(void)

{

huart7.Instance = UART7;

huart7.Init.BaudRate = 115200;

huart7.Init.WordLength = UART_WORDLENGTH_8B;

huart7.Init.StopBits = UART_STOPBITS_1;

huart7.Init.Parity = UART_PARITY_NONE;

huart7.Init.Mode = UART_MODE_TX_RX;

huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;

huart7.Init.OverSampling = UART_OVERSAMPLING_16;

huart7.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

huart7.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

HAL_UART_DeInit(&huart7);

HAL_UART_Init(&huart7);

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(uartHandle->Instance==UART7)

{

/* Peripheral clock enable */

__HAL_RCC_UART7_CLK_ENABLE();

/* DMA controller clock enable */

__HAL_RCC_DMA1_CLK_ENABLE();

__HAL_RCC_GPIOF_CLK_ENABLE();

GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

GPIO_InitStruct.Alternate = GPIO_AF8_UART7;

HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

/* UART7_IRQn interrupt configuration */

HAL_NVIC_SetPriority(UART7_IRQn, 14, 0);

HAL_NVIC_EnableIRQ(UART7_IRQn);

/* UART7 DMA Init */

/* UART7_RX Init */

//HAL_DMA_DeInit(&hdma_uart7_rx);

hdma_uart7_rx.Instance = DMA1_Stream3;

hdma_uart7_rx.Init.Channel = DMA_CHANNEL_5;

hdma_uart7_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_uart7_rx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_uart7_rx.Init.MemInc = DMA_MINC_ENABLE;

hdma_uart7_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_uart7_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_uart7_rx.Init.Mode = DMA_CIRCULAR;

hdma_uart7_rx.Init.Priority = DMA_PRIORITY_LOW;

hdma_uart7_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

HAL_DMA_DeInit(&hdma_uart7_rx);

HAL_DMA_Init(&hdma_uart7_rx);

__HAL_LINKDMA(uartHandle,hdmarx,hdma_uart7_rx);

/* DMA1_Stream3_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 15, 0);

HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);

/* UART7_TX Init */

hdma_uart7_tx.Instance = DMA1_Stream1;

hdma_uart7_tx.Init.Channel = DMA_CHANNEL_5;

hdma_uart7_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_uart7_tx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_uart7_tx.Init.MemInc = DMA_MINC_ENABLE;

hdma_uart7_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_uart7_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_uart7_tx.Init.Mode = DMA_NORMAL;

hdma_uart7_tx.Init.Priority = DMA_PRIORITY_LOW;

hdma_uart7_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

HAL_DMA_DeInit(&hdma_uart7_tx);

HAL_DMA_Init(&hdma_uart7_tx);

__HAL_LINKDMA(uartHandle,hdmatx,hdma_uart7_tx);

/* DMA1_Stream1_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 15, 1);

HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);

}

}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)

{

if(uartHandle->Instance==UART7)

{

/* Peripheral clock disable */

__HAL_RCC_UART7_CLK_DISABLE();

HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_6);

/* UART7 DMA DeInit */

HAL_DMA_DeInit(uartHandle->hdmarx);

HAL_DMA_DeInit(uartHandle->hdmatx);

/* UART7 interrupt Deinit */

HAL_NVIC_DisableIRQ(UART7_IRQn);

}

}

/* Set transmission flag: trasfer complete*/

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)

{

UartReady = SET;

}

/* Set transmission flag: trasfer complete*/

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)

{

UartReady = SET;

}

void Xbee_Init(void){

__HAL_UART_FLUSH_DRREGISTER(&huart7);

if(HAL_UART_Receive_DMA(&huart7, (uint8_t *)RxBuffer, RXBUFFERSIZE) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

uint8_t Xbee_hasData(void) {

if(_tailPtr == _headPtr) {

return 0;

}

return 1;

}

uint8_t Xbee_Read(void) {

uint8_t c = RxBuffer[_tailPtr++];

_tailPtr &= RXBUFFERSIZE1;

return c;

}

void SendToXbee(uint8_t len){

UartReady = RESET;

HAL_UART_Transmit_DMA(&huart7, (uint8_t*)TxBuffer, len);

while (UartReady != SET)

{

}

}

Any help is appreciated