Witnes
Witnes

Reputation: 317

STM32 UART not transmitting data

I'm using B-L4S5I-IOT01A board and I'm not able to make UART working properly. It's working fine when using HAL, but when I'm trying to operate directly on registers there is no data transferred to my PC (at least I can't see in terminal).

#include "stm32l4r5xx.h"

#define SYS_FREQ 8000000
#define UART_BAUDRATE 115200
#define TXE 1U << 7

void write_uart(int value) {
  while (!(USART1->ISR & TXE)) {}
  USART1->TDR = (value & 0xFF);
}

int main() 
{
  RCC->AHB2ENR |= 1U << 1;
  RCC->AHB2ENR |= 1U << 2;
  
  // PIN UART TX
  RCC->AHB2ENR |= 1U << 0;

  GPIOA->MODER &= ~(1U << 18);
  GPIOA->MODER |= 1U << 19;
  
  GPIOA->AFR[1] |= 1U << 4;
  GPIOA->AFR[1] |= 1U << 5;
  GPIOA->AFR[1] |= 1U << 6;
  GPIOA->AFR[1] &= ~(1U << 7);

  // UART
  RCC->APB1ENR1 |= 1U << 17;
  RCC->APB2ENR |= 1U << 14;

  USART1->CR1 &= ~(1U << 15);
  USART1->BRR = (SYS_FREQ / UART_BAUDRATE);

  USART1->CR1 |= 1U << 0;
  USART1->CR1 |= 1U << 3;

  while (1)
  {
    write_uart('Y');
  }
}

Upvotes: 0

Views: 456

Answers (1)

0___________
0___________

Reputation: 67855

  1. Do not use magic numbers. Use human-readable definitions from the STM CMSIS headers. I am not going to decode bit numbers as it makes no sense and it is very easy to make a stupid mistake.
  2. Read the Reference Manual. After enabling a peripheral clock you need to make sure that that it has propagated through the bus. You can read back, execute the barrier instruction or add a small delay. 4.TXE - you got a warning there - read it and correct.
GPIOB->MODER |= GPIO_MODER_MODE6_1;

It is no-op in your uC. It is by default in analog mode and has to be reset before setting.

GPIOB->MODER &= ~GPIO_MODER_MODE6_MSK;
GPIOB->MODER |= GPIO_MODER_MODE6_1;

You also do not need a long delay (3 clocks are needed). Readback is the best option as operations on the bus are strongly ordered.

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
(void)RCC->AHB2ENR;

Upvotes: 2

Related Questions