cancel
Showing results for 
Search instead for 
Did you mean: 

USART with Nucleo L4R5ZI - bare metal/registry programming

Valkan Pavlov
Associate III

Hey folks, I did try the bare metal programming videos on Udemy, and got so facinated, that decided to try on other board. As expected the code from the tutorial is not working on the other board. However I have checked, and re cheked the registry values that I provide, with the documentation of the correct board, and all seems to be OK, In addition to that I added 120 MHz for APB1 bus frequency, but I am still not getting anything on RealTerm.

In Udemy they do not respond to my questions, regarding other boards, so I really hope to get some help here. Thank you!

The device is Nucleo L4R5ZI, here is the code:

#include <stdint.h>
#include <stdio.h>
#include "stm32l4xx.h"
 
#define GPIOAEN 		(1U<<0)
#define UART2EN			(1U<<17)
 
 
#define SYS_FREQ 		120000000
#define APB1_CLK 		SYS_FREQ
 
#define CR1_TE 			(1U<<3)
#define CR1_UE			(1U<<0)
 
#define ISR_TXE 		(1U<<7)
 
 
static uint16_t compute_uart_div(uint32_t PeriphClk, uint32_t Baudrate);
 
static void uart_set_baudrate (USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t Baudrate);
 
static void uart2_write(uint8_t ch);
 
void uart2_tx_init (USART_TypeDef *USARTx);
 
 
int __io_putchar (int ch)
{
	uart2_write(ch);
	return ch;
}
 
int main(){
 
	uart2_tx_init (USART2);
 
	while (1)
	{
		printf ("Hello from STM32L4....\n\r");
	}
 
}
 
 void uart2_tx_init (USART_TypeDef *USARTx)
{
	//*******************Configure the UART pin*******************
	//Enable clock access to GPIOA for PA2 as TX line
	RCC->AHB2ENR |= GPIOAEN;
 
	//Set PA2 mode as alternate function mode
	GPIOA->MODER &=~(1U<<4);
	GPIOA->MODER |=(1U<<5);
 
	//Set the alternate function type to UART
	GPIOA->AFR[0] |=(1U<<8);
	GPIOA->AFR[0] |=(1U<<9);
	GPIOA->AFR[0] |=(1U<<10);
	GPIOA->AFR[0] &=~(1U<<11);
 
	//*******************Configure the UART module*******************
	//Enable clock access to UART2
	RCC->APB1ENR1 |=UART2EN;
 
	//Configure baudrate
	uart_set_baudrate (USARTx, APB1_CLK, 115200);
 
	//Configure transfer direction
	USARTx->CR1 = CR1_TE;
 
	// Enable UART module
	USARTx->CR1 |= CR1_UE;
}
 
static void uart2_write(uint8_t ch)
{
	//Wait for transmit data register to be empty
	while (!(USART2->ISR & ISR_TXE)) {}
 
	//Transmit value
	USART2->TDR = (ch & 0xFF);
 
}
 
 
static void uart_set_baudrate (USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t Baudrate)
{
	USARTx->BRR = compute_uart_div( PeriphClk, Baudrate);
}
 
static uint16_t compute_uart_div(uint32_t PeriphClk, uint32_t Baudrate)
{
	return ((PeriphClk + (Baudrate/2))/Baudrate);
}

18 REPLIES 18

@Valkan Pavlov​ how results?

Dudo

It was definatley part of the issue, but I have not manage to make it work yet. I have posted the new code in the answer to Peter.

Hi Peter,

Thanks for the welcome, and the answer!

It was really the case, that LPUART1 is connected to the virtual COM port. I did try to set it up, and ended up with this:

#include <stdint.h>
#include <stdio.h>
#include "stm32l4xx.h"
 
 
 
#define GPIOGEN 		(1U<<6)
#define LPUART1EN		(1U<<0)
 
#define SYS_FREQ 		4000000 //It is 4MHz!
#define APB1_CLK 		SYS_FREQ
 
#define CR1_TE 			(1U<<3)
#define CR1_UE			(1U<<0)
 
#define ISR_TXE 		(1U<<7)
 
 
 
static uint16_t compute_LPUART_div(uint32_t PeriphClk, uint32_t Baudrate);
 
static void LPUART_set_baudrate (USART_TypeDef *LPUARTx, uint32_t PeriphClk, uint32_t Baudrate);
 
static void LPUART1_write(USART_TypeDef *LPUARTx, uint8_t ch);
 
void uart2_tx_init (USART_TypeDef *LPUARTx);
 
int __io_putchar (int ch)
{
	LPUART1_write(LPUART1, ch);
	return ch;
}
 
 
int main(){
 
	LPUART1_tx_init (LPUART1);
 
	while (1)
	{
		printf ("Hello from STM32L4....\n\r");
	}
 
}
 
 void LPUART1_tx_init (USART_TypeDef *LPUARTx)
{
	//*******************Configure the UART pin*******************
	//Enable clock access to GPIOG for PG7 as TX line
	RCC->AHB2ENR |= GPIOGEN;
 
	//Set PG7 mode as alternate function mode
	GPIOG->MODER &=~(1U<<14);
	GPIOG->MODER |=(1U<<15);
 
	//Set the alternate function type to TX - AF8
	GPIOG->AFR[0] &=~(1U<<28);
	GPIOG->AFR[0] &=~(1U<<29);
	GPIOG->AFR[0] &=~(1U<<30);
	GPIOG->AFR[0] |=(1U<<31);
 
	//*******************Configure the UART module*******************
 
	//Enable clock access to LPUART1
	RCC->APB1ENR2 |= LPUART1EN;
 
	//Configure baudrate ?????
	LPUART_set_baudrate (LPUART1, APB1_CLK, 115200); //?????
 
	//Configure transfer direction
	LPUART1->CR1 = CR1_TE;
 
	// Enable UART module
	LPUART1->CR1 |= CR1_UE;
 
 
}
 
static void LPUART1_write(USART_TypeDef *LPUARTx, uint8_t ch)
{
	//Wait for transmit data register to be empty
	while (!(LPUARTx->ISR & ISR_TXE)) {}
 
	//Transmit value
	LPUARTx->TDR = (ch & 0xFF);
}
 
 
static void LPUART_set_baudrate (USART_TypeDef *LPUARTx, uint32_t PeriphClk, uint32_t Baudrate)
{
	LPUARTx->BRR = compute_LPUART_div( PeriphClk, Baudrate);
}
 
static uint16_t compute_LPUART_div(uint32_t PeriphClk, uint32_t Baudrate)
{
	return ((PeriphClk + (Baudrate/2))/Baudrate);
}

It is not working, my baudrate formula is probably wrong, together with the SYS_FREQ that should be 32.768 MHz? If you have any more valuable advices, including learning resourses it will be greatly appreciated!

Thanks!

You still init USART2, line 37

Dudo

It is amazing how can I omit obvious things. Thank you. I will try again.

nice 🙂 please some answer as the best as we can close topic 🙂 OF course after the test :D

Dudo

It's magic of review code :D

Dudo

Hi, I was able to validate the default system clock speed of 4 MHz, and maybe fix the errors. But still miss something. Maybe the LPUART require more things to work.... back to tutorials, maid be early to start projects on my own. Thank you for the assistance!

Piranha
Chief II

> However I have checked, and re cheked the registry values that I provide

Again someone who defines their own register bit field definitions and uses magic numbers. Use the provided standard CMSIS definitions!