Getting Started with the ARM GCC Compiler on Windows for the STM32F4DISCOVERY Board

In late 2012, I wrote a five-part series of tutorials on getting started with the ARM GCC Compiler on Windows for the STM32F0Discovery board. You can review part one, part two, part three, part four, and part five.

Today I want to do the same thing but show you how to get up and running with the STM32F4DISCOVERY board. The STM32F4 parts are more capable than the STM32F0 parts. In particular, the STM32F4 series has a Cortex-M4 processor with hardware floating point unit, is faster, and has more memory than the F0 parts. The chip on the STM32F4DISCOVERY kit has 1MB FLASH and 192K of RAM. These are very generous amounts of memory for a microcontroller!

Here's the ST feature list for the STM32F4DISCOVERY board:

The STM32F4DISCOVERY board

The STM32F4DISCOVERY board

Key Features

  • STM32F407VGT6 microcontroller featuring 32-bit ARM Cortex-M4F core, 1 MB Flash, 192 KB RAM in an LQFP100 package
  • On-board ST-LINK/V2 with selection mode switch to use the kit as a standalone ST-LINK/V2 (with SWD connector for programming and debugging)
  • Board power supply: through USB bus or from an external 5 V supply voltage
  • External application power supply: 3 V and 5 V
  • LIS302DL or LIS3DSH ST MEMS 3-axis accelerometer
  • MP45DT02, ST MEMS audio sensor, omni-directional digital microphone
  • CS43L22, audio DAC with integrated class D speaker driver
  • Eight LEDs:
  • LD1 (red/green) for USB communication
  • LD2 (red) for 3.3 V power on
  • Four user LEDs, LD3 (orange), LD4 (green), LD5 (red) and LD6 (blue)
  • 2 USB OTG LEDs LD7 (green) VBus and LD8 (red) over-current
  • Two push buttons (user and reset)
  • USB OTG FS with micro-AB connector
  • Extension header for all LQFP100 I/Os for quick connection to prototyping board and easy probig

Here's a consolidated list of steps to get up and running. Please see my earlier tutorial series for a full explanation of each step and what it does.

    1. Install ARM GCC from this website. Be sure to check "Add path to environment variable" on the last page of the wizard. (Reference)
    2. Install the GCC MAKE utilty from this link. Download the "Complete package, except sources" file. Accept defaults in the setup wizard. (Reference)
    3. Download and install the GNU utilities package for Windows. When finished, add the path to the folder containing the binaries to your system path. This installs the "rm" command so that the "Clean Project" option will work.
    4. Create a Development folder and a Workspace folder. Choose paths with no spaces in them. (Reference)
    5. Install Eclipse on your machine (Reference)
    6. Install CDT, Cross-Compiler support, and GCC Hardware Debugging support within Eclipse. Install the ST-LINK utility. (Reference, Reference)
    7. Within your workspace folder, create two subfolders named 'Libraries' and 'Projects.' (This is a different folder structure than I used in the STM32F0 tutorial series.)
    8. Download the STM32F4 DSP and standard peripherals library from ST's website. Extract the files into the Libraries folder.
    9. Launch Eclipse and open your workspace folder when prompted to open a workspace.
    10. Create a new project. (File... New... Project)
    11. Select the C Project wizard in the C/C++ node of the treeview control
    12. Name the new project "STM32F4_TemplateProject" and override the default path to put the new project inside the Projects folder. Ensure the Cross GCC toolchain is selected.
    13. Enter the cross compiler prefix "arm-none-eabi" and the path
    14. Within the IDE, create a src and an inc folder. Inside the src folder, create a Startup folder. (Again, this is a different file structure than I used in my STM32F0 tutorial. Do what works for you.)
    15. The sample program that ships with the STM32F4DISCOVERY kit uses the USB port to emulate a mouse. That's a bit ambitious for our first 'hello, world' program. Instead of building the demo program from ST, we're going to build a program that turns on the green LED when it runs, and turns on the blue LED whenever the USER button is pressed. To do this, we're going to have to copy some of the sample files into our project directory and then edit them. The files we need are in the STM32F4xx_StdPeriph_Lib_V1.3.0\Project\STM32F4xx_StdPeriph_Templates folder. Copy main.c, stm32f4xx_it.c, and system_stm32f4xx.c to our project's src folder. Copy main.h, stm32f4xx_it.h, and sym32f4xx_conf.h to the inc folder. From the STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Project\STM32F4xx_StdPeriph_Templates\TrueSTUDIO\STM32F40_41xxx folder, copy STM32F407IG_FLASH.ld to the root of the Project folder. From the STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\TrueSTUDIO folder, copy startup_stm32f401xx.s to the src/startup folder in your project. Rename the file from having a .s (lowercase) extension to a .S (uppercase) extension.
    16. In the Eclipse IDE, select the root of the project tree and refresh so that the IDE sees all of the changes we made to the filesystem.
    17. Right-click the src folder and select New Folder. Click the advanced button and select linked folder. Name the folder StdPeriph and use the location WORKSPACE_LOC\Libraries\STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Libraries\STM32F4xx_StdPeriph_Driver\src. (Reference)
    18. In the project properties, C/C++ General, Paths and Symbols node, click on the Includes tab, click GNU C and ensure All Configurations is selected. Add the following include paths:
      • ${ProjDirPath}/inc
      • ${WorkspaceDirPath}/Libraries/STM32F4xx_DSP_StdPeriph_Lib_V1.3.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include
      • ${WorkspaceDirPath}/Libraries/STM32F4xx_DSP_StdPeriph_Lib_V1.3.0/Libraries/CMSIS/Include
      • ${WorkspaceDirPath}/Libraries/STM32F4xx_DSP_StdPeriph_Lib_V1.3.0/Libraries/STM32F4xx_StdPeriph_Driver/inc
    19. In the project properites, C/C++ Build, Settings node, click on Cross GCC Compiler, Symbols. Ensure All Configurations is selected. Add the following two symbols:
      • STM32F40_41xxx
      • USE_STDPERIPH_DRIVER
    20. Add the following build flags under project properties, C/C++ Build, Settings, Cross GCC Compiler, Miscellaneous. Ensure All Configurations is selected.
      • -c -fmessage-length=0 (should already be there)
      • -mthumb
      • -mcpu=cortex-m4
      • -mfloat-abi=hard
      • -mfpu=fpv4-sp-d16
      • -fdata-sections
      • -ffunction-sections
    21. Add the following linker flags under project properties, C/C++ Build, Settings, Crogg GCC Linker, Misellaneous. Ensure All Configurations is selected.
      • -Wl,--gc-sections
      • -T"..\STM32F407IG_FLASH.ld"
      • "Wl,-Map=${BuildArtifactFileBaseName}.map"
      • -mthumb
      • -mcpu=cortex-m4
      • -mfloat-abi=hard
      • -mfpu=fpv4-sp-d16
    22. In project settings, C/C++ Build, Settings node, Build Artifact tab, set the Artifact extension to "elf"
    23. In project settings, C/C++ Build node, Builder Settings tab, uncheck "Use default build command" and enter the command "C:\Progra~1\GnuWin32\bin\make.exe"
    24. In the project explorer window, expand the src folder, then the StdPeriph folder. Right-click on the stm32f4xx_fmc.c file and select "Resource Configurations... exclude from build." Click Select All and click OK.
    25. Add the following #defines to your main.h file:
1
2
3
4
5
6
7
8
9
10
11
#define GREEN_LED_PORT GPIOD
#define GREEN_LED_PIN GPIO_Pin_12
#define BLUE_LED_PORT GPIOD
#define BLUE_LED_PIN GPIO_Pin_15
#define USER_BUTTON_PORT GPIOA
#define USER_BUTTON_PIN GPIO_Pin_0
#define BLUE_LED_PERIPH_CLOCK RCC_AHB1Periph_GPIOD
#define GREEN_LED_PERIPH_CLOCK RCC_AHB1Periph_GPIOD
#define USER_BUTTON_PERIPH_CLOCK RCC_AHB1Periph_GPIOA

#define USER_BUTTON_IS_PRESSED (USER_BUTTON_PORT->IDR & USER_BUTTON_PIN)
    1. Add the following code to main():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//enable clocking to the GPIO ports
RCC_AHB1PeriphClockCmd(GREEN_LED_PERIPH_CLOCK, ENABLE);
RCC_AHB1PeriphClockCmd(BLUE_LED_PERIPH_CLOCK, ENABLE);
RCC_AHB1PeriphClockCmd(USER_BUTTON_PERIPH_CLOCK, ENABLE);

//Set up the pins for the LEDs and User Button
GPIO_InitTypeDef gpioInit;
gpioInit.GPIO_Mode = GPIO_Mode_OUT;
gpioInit.GPIO_OType = GPIO_OType_PP;
gpioInit.GPIO_Pin = GREEN_LED_PIN;
gpioInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpioInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GREEN_LED_PORT, &gpioInit);

gpioInit.GPIO_Pin = BLUE_LED_PIN;
GPIO_Init(BLUE_LED_PORT, &gpioInit);

gpioInit.GPIO_Mode = GPIO_Mode_IN;
gpioInit.GPIO_Pin = USER_BUTTON_PIN;
GPIO_Init(USER_BUTTON_PORT, &gpioInit);

//Turn on the green LED
GREEN_LED_PORT->BSRRL |= GREEN_LED_PIN;

//Turn off the blue LED
BLUE_LED_PORT->BSRRL |= BLUE_LED_PIN;

/* Infinite loop */
while (1)
{
   if (USER_BUTTON_IS_PRESSED)
   {
    BLUE_LED_PORT->BSRRH |= BLUE_LED_PIN;
   }
   else
   {
    BLUE_LED_PORT->BSRRL |= BLUE_LED_PIN;
   }
}

Build your project and debug it using the steps in the previous tutorial.

Let me know how things work for you!

Edit 2/9/2014:

The Standard Peripheral Library is configured for a demo board with a 25MHz crystal. The STM32F4DISCOVERY has an 8MHz crystal onboard. As a result, computations regarding clock frequency may not be accurate if you build with this file. To fix this, change the value of HSE_VALUE in stm32f4xx_conf.h from its current value of 25,000,000 to a value of 8,000,000. You may also wish to download ST's Clock Configuration tool (which is actually an Excel spreadsheet) and build a new system_stm32f4xx.c file with a set of known-good clock values.