cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F303VC Bare Metal - How to Enable VCP / USART Over USB?

KPres.1
Associate II

I'm trying to follow the reference manual to use USART over USB via VCP (bare metal), but Realterm isn't able to read *any* data. According to the user manual, USART/VCP over USB should be supported, mentioning it's on the PC4,PC5 pins. Here's the code I'm using:

#include <stdio.h>
#include "stm32f303xc.h"
 
/* USART1 is an alternative function of GPIOC */
#define GPIOCEN         (1U << 19)
#define USART1EN        (1U << 14)
 
/* USART1 -> CR1 Control Register */
#define CR1_TE          (1U << 3)
#define CR1_UE          (1U << 0)
 
#define SYS_FREQ        8000000
#define APB2_CLK        SYS_FREQ
 
#define USART_BAUDRATE   9600
 
static void usart_set_baudrate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t BaudRate);
static uint16_t compute_usart_bd(uint32_t PeriphClk, uint32_t BaudRate);
 
void usart1_tx_init(void);
void usart1_write(int ch);
 
int main(void)
{
    usart1_tx_init();
 
    while(1)
    {
        usart1_write('H');
        usart1_write('i');
    }
}
 
void usart1_tx_init(void)
{
    /****** Configure UART GPIO pin ******/
    /* Enable clock access to GPIOC */
    RCC -> AHBENR |= GPIOCEN;
    
    /* Set PC4 mode to alternate function mode */
    GPIOC -> MODER &= ~(1U << 8);
    GPIOC -> MODER |=  (1U << 9);
 
    /* Set PC4 alternate function type to USART_TX  */
    GPIOC -> AFR[0] |=  (1U << 28);
    GPIOC -> AFR[0] |=  (1U << 29);
    GPIOC -> AFR[0] |=  (1U << 30);
    GPIOC -> AFR[0] &= ~(1U << 31);
 
    /****** Configure UART module ******/
    /* Enable clock access to USART1 */
    RCC -> APB2ENR |= USART1EN;
 
    /* Configure baud rate */
    usart_set_baudrate(USART1, APB2_CLK, USART_BAUDRATE);
 
    /* Enable UART module */
    USART1 -> CR1 = CR1_UE;
 
    /* Configure the transfer direction */
    USART1 -> CR1  = CR1_TE;
}
 
void usart1_write(int ch)
{
 
    /* Make sure transmit data register is empty */
    while (!(USART1 -> ISR & ISR_TXE)){}
 
    /* Write to transmit data register */
    USART1 -> TDR = (ch & 0xFF);
}
 
static void usart_set_baudrate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t BaudRate)
{
    USARTx -> BRR = compute_usart_bd(PeriphClk, BaudRate);
}
 
static uint16_t compute_usart_bd(uint32_t PeriphClk, uint32_t BaudRate)
{
    return ((PeriphClk + (BaudRate/2U))/BaudRate);
}

I'd very much appreciate any help or resources I could look at!

1 ACCEPTED SOLUTION

Accepted Solutions

Code is not very efficient, you want the compiler to do the work, not the MCU

Setting AF7 for PC7, not PC4

OR bits onto UART->CR1

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

View solution in original post

7 REPLIES 7

Where's the USB here? What hardware is this?

Style: Why don't you use symbols defined in the CMSIS-mandated device header (stm32f303xc.h)?

JW

gbm
Lead III

Line 61 disables the UART. Lines 45..48 don't do what you expect them to - they set PC7.

Code is not very efficient, you want the compiler to do the work, not the MCU

Setting AF7 for PC7, not PC4

OR bits onto UART->CR1

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

Assuming a NUCLEO or DISCO board

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

> Assuming a NUCLEO or DISCO board

AFAIK there's no 100-pin-target Nucleo. The 'F303 Disco indeed uses 'F303VC, but older variants had the STLink without VCP (ST-LINK/V2 PCB version A or B, ST-LINK/V2-B (+ VCP + MSD) for PCB version C and newer),

If it's the C revision or newer, VCP related jumpers/SBs are to be checked.

And, reading out and checking content of UART and related GPIO registers is always the way to go. Plus observing the pins using oscilloscope/LA, plus the basic blinky to verify basic functionality and/or clocks settings.

JW

It's the STM32F3DISCOVERY, I should have clarified that I'm trying to use the USB ST-LINK/V2-B (and not the USER USB - yet).

Re: style, mainly because I don't know any better. This is my first foray into something other than MicroPython on ESP32s so I'm following a guide for a similar board (but different enough to be a pain). But I will definitely use the symbols moving foward, thanks!

Thank you so much! I had rewritten the code at least 3 times, each time missing the fact I was setting the AF for the wrong pin. Everything seems to be working fine now!

I'm following a beginner's guide for a similar board, as this is my first time working with something other than an ESP32 and MicroPython, so code efficiency probably leaves much to be desired. But I'll get there eventually