cancel
Showing results for 
Search instead for 
Did you mean: 

UART not transmitting in baremetal or cubeide

seb5767
Associate

From my understanding im doing everything right im using a stm32f446re. I've tried using cube ide where all the peripherals are loaded for me and it still doesn't seem to transmit i cannot see anything in the Putty or even the stm32 console. someone please help me understand

#include "Registers.h"

#define USART2_SR  *(volatile uint32_t *) (USART2_BASE + 0x00U)
//Data Register (The mailbox slot where you load characters)
#define USART2_DR  *(volatile uint32_t *) (USART2_BASE + 0x04U)
//Baud Rate Register (Controls transmission speed)
#define USART2_BRR *(volatile uint32_t *) (USART2_BASE + 0x08U)
//Control Register 1 (The main power and pin enable dashboard
#define USART2_CR1 *(volatile uint32_t *) (USART2_BASE + 0x0CU)


void init_uart()
{
	RCC_APB1ENR |= (1U<<17);
	GPIOA_MODER &= ~(3 << 2*2);
	GPIOA_MODER |= (2U << 2*2);
	GPIOA_AFRL &= ~(0xF<<2*4);
	GPIOA_AFRL |= (7<<2*4);
	USART2_BRR = 0x08B;
	USART2_CR1 |= (1U<<13);
	USART2_CR1 |= (1U<<3);
}

void uart_send_byte(uint8_t data)
{
	// Wait until the Transmit Data Register Empty (TXE) flag is set
	    // TXE is Bit 7 in the Status Register (USART2_SR)
	    while (!(USART2_SR & (1U << 7)))
	    {
	        // Do nothing until the hardware is ready for the next byte
	    }

	    // Stuff the byte into the mailbox slot
	    USART2_DR = data;
}

 

9 REPLIES 9
seb5767
Associate

Post edited by ST moderator especially for the code sharing. In next time please use </> button to share your code.

+ Threads merged for the same question / issue.

These are my registers addresses for stm32446re i have checked these with the datasheet so im pretty sure their correct

#define GPIOA_BASE 0x40020000U
#define RCC_BASE 0x40023800U // this is the power block
#define USART2_BASE 0x40004400U
// This macro handles the pointer casting and the 0x30 offset automatically
#define RCC_APB1ENR *(volatile uint32_t *) (RCC_BASE + 0x40U)
#define RCC_AHB1ENR *(volatile uint32_t *)(RCC_BASE + 0x30U)

//Turns internal Pull-up or Pull-down resistors on/off
#define GPIOA_PUPDR *(volatile uint32_t *)(GPIOA_BASE + 0x0CU)
//Input Data Register (Reads voltage coming into pins)
#define GPIOA_IDR *(volatile uint32_t *) (GPIOA_BASE + 0x10U)
//Sets pin modes (Input, Output, Alternate Function)
#define GPIOA_MODER *(volatile uint32_t *) (GPIOA_BASE + 0x00U)
//Output Data Register (Sends voltage out to pins)
#define GPIOA_ODR *(volatile uint32_t *) (GPIOA_BASE + 0x14U)
//Alternate Function Low (Routes internal engines to Pins 0–7
#define GPIOA_AFRL *(volatile uint32_t *) (GPIOA_BASE + 0x20U)
//Alternate Function High (Routes internal engines to Pins 8–15)
#define GPIOA_AFRH *(volatile uint32_t *) (GPIOA_BASE + 0x24U)
#define GPIOA_OTYPER *(volatile uint32_t *) (GPIOA_BASE + 0x04U)
#define GPIOA_OSPEEDR *(volatile uint32_t *) (GPIOA_BASE +0x08)
//Uart offsets

//Status Register (Checks if the hardware is busy or empty)
#define USART2_SR *(volatile uint32_t *) (USART2_BASE + 0x00U)
//Data Register (The mailbox slot where you load characters)
#define USART2_DR *(volatile uint32_t *) (USART2_BASE + 0x04U)
//Baud Rate Register (Controls transmission speed)
#define USART2_BRR *(volatile uint32_t *) (USART2_BASE + 0x08U)
//Control Register 1 (The main power and pin enable dashboard
#define USART2_CR1 *(volatile uint32_t *) (USART2_BASE + 0x0CU)
//Control Register 2 (Advanced layout options, like stop bits)
#define USART2_CR2 *(volatile uint32_t *) (USART2_BASE + 0x10U)
//Control Register 3 (Advanced system features, like DMA)
#define USART2_CR3 *(volatile uint32_t *) (USART2_BASE + 0x14U)


* UART.C

*

* Created on: 3/06/2026

* Author: libak

*/

#include "register.h"

void uart_write(int ch)

{

while (!(USART2_SR & (1U << 7)));

USART2_DR = (uint8_t)ch;

}



void uart_write_string(char *str)

{

while (*str)

{

uart_write(*str++);

}

}



int uart_read(void)

{

while (!(USART2_SR & (1U << 5)));

return (int)(USART2_DR & 0xFF);

}

 

Sorry, but the code presented is hardly readable, for two reasons.
First the format - there is an "Insert/Edit code sample" option of the forum editor, use it :

Ozone_0-1780466667277.png


Second, you almost exclusively use "magic numbers".
I'm not willing to wade through the reference manual just to check your code.
There are device header files with definitions of speaking names and macros, it doesn't hurt to use those.
And you immediately understand the intention of you own code even months or years later ...

> my TX pin doesnt seem to work when using UART

Have you checked the schematics, that no other circuitry is connected to this pin ?

Use a debugger and the register view to check that all your settings actually take effect.

Have you checked that RS232 input is visible on the Rx pin, e.g. with a scope ?

i have updated the post please have a look at my most recent post!!

> have updated the post ...

That's not how it's supposed to work.

Editing posts (beyond perhaps a small typo) makes the whole thread incoherent and almost impossible to follow, not only for others. Make a new post.

And what about the "code sample formatting" option ?

And, as I wrote before :
> Have you checked the schematics, that no other circuitry is connected to this pin ?
> Use a debugger and the register view to check that all your settings actually take effect.
> Have you checked that RS232 input is visible on the Rx pin, e.g. with a scope ?

Have you tried any of that ?


And, I don't see any code enabling the UART and the associated GPIO, and code configuring both.

Andrew Neil
Super User

Welcome to the forum

Please see How to write your question to maximize your chances to find a solution for best results.

 

In particular, you haven't told us what board you're using, or how you're connecting it to your PuTTY.

 

If you're trying to use the ST-Link VCP (Virtual COM Port) on an ST board (eg, Nucleo), the commonest problem is not using the correct pins - you must use the pins which are physically connected to the ST-Link's VCP.

See the board's User Manual for details.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@seb5767 wrote:

i have updated the post


As @Ozone said, that's unhelpful!

Going forward, please add further details and/or corrections in a reply.

 

You still haven't said what board you are using.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@seb5767 wrote:

These are my registers addresses for stm32446re i have checked these with the datasheet so im pretty sure their correct


As @Ozone said, ST provide headers that you can use - there no need to re-invent the wheel, and risk introducing errors.

 

The ST headers also define meaningful names for the bits - but you are still using "magic numbers":

while (!(USART2_SR & (1U << 5)));

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
waclawek.jan
Super User

What hardware do you use, a "known good" board like Nucleo, or your own design?

Blinking a LED works?

Did you observe the output using oscilloscope/logic analyzer?

JW

@seb5767 ,

Use HAL before using Baremetal for two reasons:

1- To validate your hardware and discard any PCB issues related reasons. 

2- Inspire from what it was implemented in the HAL to implement it the bare metal way.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.