¿Por qué mi STM32F4 PLL no parece funcionar?

0

He pasado algunos días sin éxito intentando que mi Nucleo F401RE use el PLL para el reloj de su sistema. Lo he configurado para utilizar el HSE de 8 MHz y la salida de 84 MHz como el reloj del sistema. El código deja de ejecutarse cuando llega a:

// Wait for clock source to change
    while ((RCC_CFGR & (2 << RCC_CFGR_SWS_BIT)) == 0);

Estoy emitiendo el reloj PLL en MCO1 y el HSE en MCO2, y veo un PLL plano (alto) y un HSE de 8MHz. Supongo que SWS nunca indica que el PLL es el reloj del sistema porque el PLL no está configurado correctamente, pero lo hace más allá de la espera de PLLRDY.

Estoy usando el siguiente código (específicamente no estoy usando CMSIS, porque quiero resolver esto manualmente):

#include "stm32f4.h"

#include <stdbool.h>

void led(bool on) {
    GPIOA_ODR = on ? 1 << 5 : 0;
}

void init(void) {
    // Enable GPIOA peripheral clock
    RCC_AHB1ENR = RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOCEN;

    // Set PA5 to output and PA8 to MCO1
    GPIOA_MODER = 0b01 << 10 | 0b10 << 16;

    // Set PC9 MCO2
    GPIOC_MODER = 0b10 << 18;

    // Turn on HSE
    RCC_CR |= RCC_CR_HSEON;
    while ((RCC_CR & RCC_CR_HSERDY) == 0);

    // Set flash wait cycles
    FLASH_ACR = FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_BIT);

    // Configure PLL
    // System clock = 84MHz, PLL48CLK = 48MHz
    RCC_PLLCFGR = (RCC_PLLCFGR & RCC_PLLCFGR_RESERVED_MASK)
        | RCC_PLLCFGR_PLLSRC // Set HSE as PLL source
        | (4 << RCC_PLLCFGR_PLLM_BIT) // M = 4
        | (168 << RCC_PLLCFGR_PLLN_BIT) // N = 168
        | (1 << RCC_PLLCFGR_PLLP_BIT) // P = 4
        | (7 << RCC_PLLCFGR_PLLQ_BIT) // Q = 7
    ;

    // Turn on PLL
    RCC_CR |= RCC_CR_PLLON;
    while ((RCC_CR & RCC_CR_PLLRDY) == 0);

    RCC_CFGR = 
        (1 << RCC_CFGR_SW_BIT) // Use PLL as clock source
        | (0b11 << 21) // Output PLL on MCO1
        | (0b10 << 30) // Output HSE on MCO2
    ;

    // LED lights if set here

    // Wait for clock source to change
    while ((RCC_CFGR & (2 << RCC_CFGR_SWS_BIT)) == 0);

    // LED doesn't light here
    led(true);

    for (;;);
}

con estos encabezados:

#ifndef STM32F4_H
#define STM32F4_H

#include <stdint.h>

#define REGISTER(addr) (*(volatile uint32_t *)(addr))

#define GPIOA_BASE 0x40020000
#define GPIOA_MODER REGISTER(GPIOA_BASE + 0x00)
#define GPIOA_OTYPER REGISTER(GPIOA_BASE + 0x04)
#define GPIOA_PUPDR REGISTER(GPIOA_BASE + 0x0c)
#define GPIOA_ODR REGISTER(GPIOA_BASE + 0x14)

#define GPIOC_BASE 0x40020800
#define GPIOC_MODER REGISTER(GPIOC_BASE + 0x00)

#define RCC_BASE 0x40023800

#define RCC_CR REGISTER(RCC_BASE + 0x00)
#define RCC_CR_HSEON (1 << 16)
#define RCC_CR_HSERDY (1 << 17)
#define RCC_CR_PLLON (1 << 24)
#define RCC_CR_PLLRDY (1 << 25)

#define RCC_PLLCFGR REGISTER(RCC_BASE + 0x04)
#define RCC_PLLCFGR_RESERVED_MASK 0b11110000101111001000000000000000
#define RCC_PLLCFGR_PLLM_BIT 0
#define RCC_PLLCFGR_PLLN_BIT 6
#define RCC_PLLCFGR_PLLP_BIT 16
#define RCC_PLLCFGR_PLLSRC (1 << 22)
#define RCC_PLLCFGR_PLLQ_BIT 24

#define RCC_CFGR REGISTER(RCC_BASE + 0x08)
#define RCC_CFGR_SW_BIT 0
#define RCC_CFGR_SWS_BIT 2

#define RCC_AHB1ENR REGISTER(RCC_BASE + 0x30)
#define RCC_AHB1ENR_GPIOAEN (1 << 0)
#define RCC_AHB1ENR_GPIOCEN (1 << 2)

#define FLASH_BASE 0x40023C00
#define FLASH_ACR REGISTER(FLASH_BASE + 0x00)
#define FLASH_ACR_LATENCY_BIT 0
#define FLASH_ACR_PRFTEN (1 << 8)

#define NVIC_ISER0 0xE000E100

#define SYST_CSR REGISTER(0xE000E010)
#define SYST_CSR_COUNTFLAG (1 << 16)

#define SYST_RVR REGISTER(0xE000E014)
#define SYST_CVR REGISTER(0xE000E018)

#endif
    
pregunta Dan Ellis

0 respuestas

Lea otras preguntas en las etiquetas