2021-02-11 05:02 AM
I am working on STM32H753 microcontroller. I want to receive string using UART interrupt and send the same string back on UART. The IDE is keil uvision 5. The problem I am facing is that when I first program the MCU UART is working fine and I am receiving back the string but after completely switching off the supply and restarting it UART is not working properly and I am not receiving the data I sent. I generated my code using stm32cube.
int main(void)
{
device_init();
HAL_Delay(100);
HAL_UART_Receive_IT(&huart1,recbuf,80);
/* USER CODE BEGIN WHILE */
while (1)
{
if(rec_data == 1)
{
rec_data = 0;
//Clean and Invalidate data cache
//SCB_CleanInvalidateDCache();
HAL_UART_Transmit_IT(&huart1,recbuf,80);
}
}
/* USER CODE END 3 */
}
#include "usart.h"
#include "gpio.h"
#include "config.h"
#include <string.h>
#include "timer.h"
uint8_t recbuf[100],trnsbuf[100];
unsigned char rec_data;
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 19200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.Prescaler = UART_PRESCALER_DIV4;//UART_PRESCALER_DIV256;//UART_PRESCALER_DIV1;
huart1.Init.FIFOMode = UART_FIFOMODE_DISABLE;
huart1.Init.TXFIFOThreshold = UART_TXFIFO_THRESHOLD_1_8;
huart1.Init.RXFIFOThreshold = UART_RXFIFO_THRESHOLD_1_8;
// huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT;
huart1.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
huart1.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;
rec_data = 0;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
// HAL_UART_Receive_IT(&huart1,recbuf,80);
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;//GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
memset(recbuf,0,sizeof(recbuf));
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//0
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
rec_data=1;
}
// Transmit buffer complete call routine
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
transmit_running = 0;
HAL_UART_Receive_IT(&huart1,recbuf,100);
}
/**
* @brief Receive an amount of data in interrupt mode.
* @note Function is called under interruption only, once
* interruptions have been enabled by HAL_UART_Receive_IT()
* @param huart: UART handle.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint16_t uhMask = huart->Mask;
uint16_t uhdata;
/* Check that a Rx process is ongoing */
if(huart->RxState == HAL_UART_STATE_BUSY_RX)
{
//SCB_DisableICache(); // Disable Instruction-cache at beginning of function in case of success! AKASH EDIT
uhdata = (uint16_t) READ_REG(huart->Instance->RDR);
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
tmp = (uint16_t*) huart->pRxBuffPtr ;
*tmp = (uint16_t)(uhdata & uhMask);
huart->pRxBuffPtr +=2;
}
else
{
*huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask);
if(uhdata == '\0')
huart->RxXferCount = 1;
}
if(--huart->RxXferCount == 0U)
{
//HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_9);
/* Disable the UART Parity Error Interrupt and RXNE interrupt*/
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Rx process is completed, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
HAL_UART_RxCpltCallback(huart);
//SCB_EnableICache(); // Disable Instruction-cache at beginning of function in case of success! AKASH EDIT
return HAL_OK;
}
return HAL_OK;
}
else
{
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
return HAL_BUSY;
}
}
/**
* @brief Send an amount of data in interrupt mode.
* @note Function is called under interruption only, once
* interruptions have been enabled by HAL_UART_Transmit_IT().
* @param huart: UART handle.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint16_t uhdata;
/* Check that a Tx process is ongoing */
if (huart->gState == HAL_UART_STATE_BUSY_TX)
{
if(huart->TxXferCount == 0U)
{
/* Disable the TX FIFO threshold interrupt (if FIFO mode is enabled) or
Transmit Data Register Empty interrupt (if FIFO mode is Disabled).
*/
if (READ_BIT(huart->Instance->CR1, USART_CR1_FIFOEN) != RESET)
{
CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);
}
else
{
CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
}
/* Enable the UART Transmit Complete Interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
return HAL_OK;
}
else
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
tmp = (uint16_t*) huart->pTxBuffPtr;
huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU);
huart->pTxBuffPtr += 2U;
}
else
{
uhdata = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFF);
huart->Instance->TDR = uhdata;
if(uhdata == '\0')
huart->TxXferCount = 1;
// transmit_running = 1;
}
huart->TxXferCount--;
return HAL_OK;
}
}
else
{
return HAL_BUSY;
}
}
2021-02-11 05:34 AM
Blind use of SCB_CleanInvalidateDCache(); will almost always fault the MCU
Buffer needs to hit full capacity before the callback will trigger, you use the same active buffer.
Inconsistent use of 80 / 100 lengths.
rec_data should be volatile.
Ping-pongs between receive and transmit, watch for overrun/sync issues.
Ignoring errors.
Not clear why hard reset would change things, not initializing clock, assuming HSI 64 MHz
2021-02-12 11:10 PM
Hello,
>>Buffer needs to hit full capacity before the callback will trigger, you use the same active buffer. - I am only receiving data till '\0' (NULL) is received. Therefore callback will be triggered once NULL is received, which is working as expected after programming using KEIL IDE. But after switching off the supply and restarting the device the receive interrupt is not working properly.
>>Inconsistent use of 80 / 100 lengths. rec_data should be volatile. - I changed both the values to 80 and made rec_data as volatile ,but it also did not work.
Please find the attached clock configuration.
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
HAL_Delay(1000);
__HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSI);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
//Error_Handler();
}
HAL_Delay(1000);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
//Error_Handler();
}
HAL_Delay(1000);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_SPI2|RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_SPI4|RCC_PERIPHCLK_USART1;
PeriphClkInitStruct.PLL2.PLL2M = 32;
PeriphClkInitStruct.PLL2.PLL2N = 129;
PeriphClkInitStruct.PLL2.PLL2P = 2;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_1;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;
PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_D2PCLK1;
PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C123CLKSOURCE_D2PCLK1;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_PLL2
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
//Error_Handler();
}
HAL_Delay(1000);
}
void device_init(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
HAL_Delay(1000);
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_Delay(50);
}