cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with STM32C011 USART--hanging while waiting for transmission complete

cosmicchasm
Associate II

Hey everybody,

I was wondering if someone could help me correct my firmware that I've written.

I created a custom board using the STM32C011F4P6 MCU. I put an FTDI UART-to-USB converter on the board to be able to view outgoing messages from the custom board on my laptop. 

While writing the firmware needed to demonstrate this functionality of the board, I referenced the C011 reference manual. There, STM describes the following steps to take when transmitting a character via USART, on page 752. I have tried to follow their advice to the best of my ability, but I notice that my board hangs while waiting for the transmission of a character to complete.

My testing code (in my main.c) is shown below:

int main(void)
{
	char msg[] = "d";

	// initialize debug LED
	user_led_init();

	// initialize the usart
	usart_init();

	while (1) {
		// transmit string of characters (one character here)
		usart_write_chars(msg, strlen(msg));
		toggle_led();
		delay_ms(500);
	}

	return 0;
}

Here are the definitions of my usart_init and usart_write_chars functions:

// Author: Aidan Stanford
/* Writing a quick polling UART driver */
/* The main goal of this driver is to interface the STM32C011
 * processor with the FTDI USB-to-UART converter on the breakout 
 * board.
 * It is very bare bones. No interrupts or DMA stuff yet!
 */

// TODO: Organize header files better
#include <stdint.h>
#include "stm32c0xx.h"
#include "uart.h"
#include "main.h"

// This function modifies USART2->BRR
void usart_config_br(int baud)
{
	// Do math according to the kernel clock source used
	uint32_t div = (USART_APB_CLK / (USART_IND_PSC<<1) / baud);

	// Set the BSRR register with the result from above
	if (USART2->CR1 & (1U<<15)) // oversampling by 8
		USART2->BRR = ((div & 0XFFF0) | ((div & 0XF) >> 1)) & ~(0X8);
	else
		USART2->BRR = div;
}

void usart_init(void)
{
	/* Configure appropriate GPIOA pins */
	// Enable GPIOA clocks!
	RCC->IOPENR |= (RCC_GPIOA_CEN);

	// Set speed to high
	GPIOA->OSPEEDR |= GPIO_PA4_HS | GPIO_PA5_HS;

	// Set pins PA5 and PA4 to AF mode and define their functions
	GPIOA->MODER &= ~GPIOA_UART_MSK;
	GPIOA->MODER |= GPIO_PA4_AF | GPIO_PA5_AF;  
	GPIOA->AFR[0] |= (GPIOA_USART2_AF<<16) | (GPIOA_USART2_AF<<20);
	

	// Enable APB clock for USART2
	RCC->APBENR1 |= RCC_USART2_CEN;

	// Configure usart_ker_ck prescaler of 5 (ends up being 10)
	USART2->PRESC |= USART_IND_PSC;

	// configure baud rate
	usart_config_br(9600);
	
	// Enable the USART peripheral
	USART2->CR1 |= USART_EN;
}

// Polling
void usart_read_chars(char *buf, int size)
{
	
}

void usart_write_chars(char *buf, int size)
{
	int c = 0;

	USART2->CR1 |= USART_TXE;

	while (c < size) {
		USART2->TDR = ((int)buf[c]) & 0XFF;
		while (!(USART2->ISR & USART_TXE)) {}
		++c;
	}
	/* This is where I hang */
	while ((USART2->ISR & (1U<<6))) {}
}

Any chance someone has developed with this MCU before and can give me a reality/sanity check on my code?

Thanks so much!

 

1 REPLY 1

Perhaps you could use the debugger, step the code, and check you've used the right bits.

Stick a scope on the pins, check the signals.

Perhaps just loop with the LED toggling, confirm that works.

Confirm board level functionality with HAL code.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..