STM32 Nucleo F446RE LED Blink

I am trying to get up and running with stm32cube on a Nucleo F446RE. Long story short, I wanted to use the mbed framework with the board but felt that compiling took too long, as well as bogging down my editor (Vim) while developing. Hopefully, my decision won’t ruin me too much…

Anyways, I am trying to get back up to speed with using the stm32cube framework and am attempting to get the onboard LED blinking

#include "stm32f4xx_hal.h"

#define LED_PIN                     GPIO_PIN_5
#define LED_GPIO_PORT               GPIOA
#define LED_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()

int main(void) {
    HAL_Init();

    LED_GPIO_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Pin     = LED_PIN;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_HIGH;

    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

    while (1) {
        HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
        HAL_Delay(500);
    }
}

The code uploads fine with no issues. The LED, however, doesn’t blink. If I adjust the GPIO port or GPIO_PIN to another port or pin, the LED turns off, which makes sense. I’m guessing I need to set up the system clock? If so, I can’t seem to find any examples of how the default configs are set up via code…

I’m guessing this is entirely an oversight on my part.

Can’t work without a SysTick handler calling into the HAL notifiying it a tick happened…

Is absolutely crucial for this to work.

Thanks for the response @maxgerhardt. I’ve added the handler method, but, the LED isn’t blinking. Do I need to add a call to the method in main?

#include "stm32f4xx_hal.h"

#define LED_PIN                     GPIO_PIN_5
#define LED_GPIO_PORT               GPIOA
#define LED_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()

int main(void) {
    HAL_Init();

    LED_GPIO_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.Pin     = LED_PIN;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_HIGH;

    HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

    while (1) {
        HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
        HAL_Delay(1000);
    }
}

void SysTick_Handler(void) {
    HAL_IncTick();
}

Is this code in a .c or .cpp file?

It is in a .cpp file. Should it be a .c file?

No it can be in a .cpp file but you just have to adhere to the fact that the handler function is referenced in the .S assembly code and thus expects the symbol name SysTick_Handler but when you’re writing the function in .cpp it by default gets a mangled symbol name that include the return type and parameter type. That has to be explicitly disabled by declaring the function to be extern "C". So just write

extern "C" void SysTick_Handler(void) {
    HAL_IncTick();
}

See

Ah, fascinating! Looks like I have some light reading to do!

The extern "c" declaration worked perfectly, as well as changing the file extension from .cpp to .c.

From your perspective is it better to stick with C when using the stm32cube framework?

Depends on your coding style. It’s advantageous to be able to use C++ constructs like classes, overloaded methods et cetara. Really the only time where the “function must be exposed with C-linkage / no name mangling” is when you have to interwork with assembly code, which are mostly interrupt functions, or C function callbacks. So you can just stick to C++ if you think C++ is better for your application. Otherwise stick to C with the in C written STM32Cube HAL framework.