STM32F4 USART no configurado correctamente

Estoy tratando de configurar manualmente* un USART en un Nucleo F401RE para transmitir a través del puerto COM virtual USB, lo que significa usar USART2 en PA2 (TX) y PA3 (RX). No solo no recibo ningún carácter, sino que el pin TX nunca está alto, lo que creo que debería estar cuando está inactivo.

Esto es lo que he hecho:

PLL funciona a 84 MHz (confirmado mediante MCO) y el preescalador APB1 está configurado en /2:

RCC_CFGR = 
    (2 << RCC_CFGR_SW_BIT) // Use PLL as clock source
    | (0b100 << RCC_CFGR_PPRE1_BIT) // Prescale APB1 clock /2
;

El reloj periférico GPIOA está habilitado:

// Enable GPIOA peripheral clock
RCC_AHB1ENR = RCC_AHB1ENR_GPIOAEN;

Luego la configuración de USART:

GPIOA_MODER |= 0b1010 << 4; // PA2, PA3 to AF
GPIOA_OSPEEDR |= 0b1111 << 4; // PA2, PA3 to high speed
GPIOA_AFRL |= (7 << 8) | (7 << 12); // Set PA2, PA3 to AF7 (USART2)
RCC_APB1ENR |= RCC_APB1ENR_USART2EN; // Enable peripheral clock for USART2

// Baud rate 115k2 with SYSCLK 84MHz (BRR = 45.5625)
USART2_BRR = (45 << 4) | 9;

USART2_CR1 = USART_CR1_UE | USART_CR1_TE;

Creo que en este punto, TX debería ser alto, pero no lo es. Envío con:

while ((USART2_SR & USART_SR_TXE) == 0);
USART2_DR = c;

Encender el LED dentro de whilemuestra que el búfer de transmisión está inicialmente lleno. Al encenderlo después de las whiledemostraciones que se vacía con éxito. Usar TCen lugar de TXEmuestra se considera transmitido con éxito.

¿Qué me he perdido?

Todo el código está aquí: https://github.com/danellis/zeptos/tree/usart-fail


* Por favor, no trate de persuadirme para que use CMSIS o mbed; es un ejercicio de aprendizaje.

nadie leerá los números mágicos.
Así que suponga que son correctos.
Por cierto, está configurando los registros de una manera potencialmente peligrosa. Debe borrar los valores de bit existentes antes de aplicar la operación OR. Por ejemplo, agregue GPIOA_MODER &= ~(0xF << 4); para ese registro. Esto ahorrará a sus colegas (y a usted mismo en el futuro) muchas horas de depuración.
@Jon Eventualmente, sí. Tengo un archivo YAML de descripciones de registro para generar las macros apropiadas para cualquier campo de más de un bit. Por ahora, tienen en cuenta los valores de reinicio.

Respuestas (1)

Resultó que el código estaba bien y que todos eran problemas de hardware. En primer lugar, los pines USART2 TX/RX en el conector de esa placa están, por diseño, no conectados a nada. Los pines MCU solo están conectados al ST-Link. (Hay puentes de soldadura para cambiar esta configuración). Por eso no obtuve nada en el alcance.

En cuanto a por qué no obtuve ningún dato en el puerto USB, creo que el ST-Link no era compatible con USB 3.0. Cuando actualicé su firmware, de repente vi mis datos.