stm32 Getting started with stm32 First time setup with blink LED example using SW4STM32 and HAL library

Help us to keep this website almost Ad Free! It takes only 10 seconds of your time:
> Step 1: Go view our video on YouTube: EF Core Bulk Extensions
> Step 2: And Like the video. BONUS: You can also share it!


(Note: There are many IDE, toolchain and library which are ready-to-use with STM32. The following setup requires minimal effort to get it work, but it is only one of the many. Feel free to explore others, it is not the purpose of this example to force anyone to use the tools that will be used here.)

IDE installation

System Workbench for STM32: free IDE on Windows, Linux and OS X. It has been built by AC6 and available for download after registration from the OpenSTM32 Community's website.

The IDE itself is based on Eclipse, but comes with some extras for STM32 development like:

  • Ac6 STM32 MCU GCC toolchain
  • OpenOCD and GDB (arm-none-eabi-gdb) with automatically generated debug configurations depending on the target board
  • Built-in options to program or erase chip

To start with STM32 before creating your own board, it is recommended to experiment with a Discovery, a Nucleo or an Eval board, which come with an on-board SWD (Serial Wire Debug) programmer/debugger called ST-Link.

Creating a project

This example will use an STM32F4 Discovery kit, which features an STM32F407VG microcontroller. (Any other board can be used as well.)

  1. Open SW4STM32 and create a new C project: File → New → C Project

  2. Give it a name like "STM32F4_Discovery-Blinky" and from the Project Type list choose the Executable/Ac6 STM32 MCU Project. By default the only available toolchain is Ac6 STM32 MCU GCC. Click Next.

    enter image description here

  3. Next step is Debug/Release settings, can be skipped now by clicking Next.

  4. Board selection. Existing boards can be selected as in this example the STM32F4 Discovery or new custom boards can be added.

    enter image description here

  5. Next step is Project Firmware configuration. Choose between No firmware, Standard Peripheral Library (SPL) or Hardware Abstraction Layer (HAL). It is questioned which one is more suitable for development, but this question is out of scope in this example. This example will use the HAL library as it is the currently supported by ST Microelectronics. Additional available software tool for HAL is STM32CubeMX, which is an initialization code generator. Also several example applications are available by the STM32CubeFx or STM32CubeLx software packages. Download the target firmware if it's missing and it is recommended select the "Add low level drivers in the project" and the "As sources in the application" options. Finally, click Finish.

    enter image description here

Blink LED application

As this project has been created with an STM32F4 Discovery, there are already several ready-to-use functions under the /STM32F4_Discovery-Blinky/Utilities/STM32F4-Discovery/ project folder which can be used to interface the Discovery kit's peripherals (accelerometer, audio, LEDs, push button). In this example the void BSP_LED_Init(Led_TypeDef Led) and the void BSP_LED_Toggle(Led_TypeDef Led) functions will be used from the stm32f4_discovery.c file to blink the green LED, which is LED4. To decide which LED is which use the schematics of the Discovery kit.

enter image description here

The actual pin and port names are already hidden by some #define and enum, use Ctrl + Click to track them.

  1. Inside the main, call the HAL_Init() function which resets all peripherals, initializes the Flash interface and the Systick. (Systick will be used to generate delay for the blinking.)
  2. The system clock have to be configured. It can be done by using the STM32CubeMX clock configuration feature or by the reference manual. In this example the system clock is fed by the internal PLL (Phase Locked Loop), which is sourced by an external 8 MHz crystal oscillator (HSE). Prescalers have been set to achieve the maximum available frequency, which is 168 MHz in case of the F4 Discovery.
  3. Initialization of the peripherals, in this case a GPIO pin.
  4. Inside an endless loop, call the LED toggling and the HAL_Delay() function. HAL_Delay() uses the Systick and generates a delay in miliseconds.

The whole code is the following:

#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
void SystemClock_Config(void);

int main(void)
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

    /* Configure the system clock */

    /* Initialize one of the LED GPIO pin */

        HAL_Delay(1000);       // in miliseconds

 * @brief  System Clock Configuration
 *         The system Clock is configured as follow :
 *            System Clock source            = PLL (HSE)
 *            SYSCLK(Hz)                     = 168000000
 *            HCLK(Hz)                       = 168000000
 *            AHB Prescaler                  = 1
 *            APB1 Prescaler                 = 4
 *            APB2 Prescaler                 = 2
 *            HSE Frequency(Hz)              = HSE_VALUE
 *            PLL_M                          = (HSE_VALUE/1000000u)
 *            PLL_N                          = 336
 *            PLL_P                          = 2
 *            PLL_Q                          = 7
 *            VDD(V)                         = 3.3
 *            Main regulator output voltage  = Scale1 mode
 *            Flash Latency(WS)              = 5
 * @param  None
 * @retval None
void SystemClock_Config(void)
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  // Enable Power Control clock

  // The voltage scaling allows optimizing the power consumption when the
  // device is clocked below the maximum system frequency, to update the
  // voltage scaling value regarding system frequency refer to product
  // datasheet.

  // Enable HSE Oscillator and activate PLL with HSE as source
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

  // This assumes the HSE_VALUE is a multiple of 1MHz. If this is not
  // your case, you have to recompute these PLL constants.
  RCC_OscInitStruct.PLL.PLLM = (HSE_VALUE/1000000u);
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLQ = 7;

  // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
  // clocks dividers
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

Build with the hammer enter image description here, and download the application by right clicking on the project folder and selecting the Target → Program chip... option.

Another way to download is with using debug. To do so click on the arrow beside the bug icon enter image description here in the toolbar and open Debug Configuration... menu. Creat a new Ac6 STM32 Debugging configuration and if the C/C++ Application field is empty, fill in the following:


Other debug parameters such as the OpenOCD configuration file and the used Telnet and GDB ports are automatically generated and filled in by the framework. Finally, click the Debug button.

Got any stm32 Question?