I have been prototyping my project with the STM32F103 "Bluepill" and for the final product I want to move to the STM32F042F6 which has a smaller TSSOP-20 footprint. I need to use UART in my communications with the device so I tried to create a simple UART transmit program to check that the UART peripheral was working correctly. Here is my code.
#include "stm32f0xx.h"
#include "stm32f0xx_hal.h"
#include "stm32f0xx_hal_conf.h"
void Startup_Sequence(void);
void Error_Handler(void);
void SystemClock_Config(void);
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle);
UART_HandleTypeDef UartHandle;
__IO ITStatus UartReady = RESET;
int main(void)
{
HAL_Init();
//SystemInit();
SystemClock_Config();
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
// Setup LED Pin
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Setup UART Tx Pin
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Setup UART Rx pin
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//Setup UART Instance
UartHandle.Instance = USART1;
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
//Error handling
if(HAL_UART_Init(&UartHandle) != HAL_OK) {
Error_Handler();
}
Startup_Sequence();
HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USART1_IRQn);
char hello[6] = "hello\n";
while(1) {
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t *)hello, 6) != HAL_OK) {
Error_Handler();
}
}
}
void Startup_Sequence(void) {
int i;
for (i=1; i<50;i++) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
HAL_Delay((1.0/i) * 1000);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}
void Error_Handler(void) {
while(1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
HAL_Delay(1000);
}
}
/**
* Associates the interrupt handler with the UartHandle
*/
void USART1_IRQHandler(void) {
HAL_UART_IRQHandler(&UartHandle);
}
/**
* This function is called when transmitting
* @param UartHandle [Pointer to UartHandle]
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle) {
UartReady = SET;
}
/**
* This function is called when receiving
* @param UartHandle [Pointer to UartHandle]
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {
UartReady = SET;
}
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType =
RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) !=
HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
The UART peripheral initialises correctly, because the Error Handler is not called until after the Startup_Sequence() has completed. So why is the ErrorHandler called when I try to transmit? I have tried to send using the blocking mode, but it just timeouts every time.
EDIT: I have tracked the error down to the initialisation function. Here is the GDB Log https://hastebin.com/xopohaniyu.coffeescript but I can't find anywhere where HAL_OK is not returned.
Is there something wrong my setup of the UART peripheral? Or is there a problem with the System clock? Please advise.
Best Answer
GPIO setup is somewhat more
complicatedflexible on the F0. Here you should also setGPIO_InitStruct.Alternate = GPIO_AF1_USART1
, otherwise it will get some random value, because it is an unitialized automatic variable. Enable the warnings in the compiler, and pay attention to them, they are there for a reason.HAL_UART_Transmit_IT()
is called again before the previous transmit has finished. You should wait until theUartReady
flag is set, and reset it before repeating.