Startup Without Peripheral Libraries – STM32

Startup without peripheral libraries series

A default bit of basic startup code is created when you start a project in Atollic TrueSTUDIO.  For my project, the code is called startup_stm32f446xx.s.  This code sets up the initial vector table, the program counter, the stack pointer, and branches to the main function.  I also include the standard device header files that ST provides and use the definitions in the files for register configuration.  These are well documented in the headers and the names match the datasheet.

This configuration uses the 16MHz internal oscillator and PLL to run the system clock at 180MHz.  I then set up the SysTick timer for a 1ms interrupt.

The rest of the startup code is pretty straightforward:

  1. Enable the FPU
  2. Set up flash caching with the correct wait states for the clock speed
  3. Set up the clock and switch to it
  4. Enable any peripheral clocks
  5. Configure any peripherals – in this case I configure SysTick.  The interrupt callback function is defined in the startup code and is appropriately named SysTick_Handler.
  6. Call the sysInit from the main function before the main loop.
#include "stm32f4xx.h"


void sysInit (void)
{
   // enable fpu
   SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));

   // Set up flash caching
   FLASH->ACR = 0x705; // 5 wait state latency (150-180MHz), prefetch enable, instruction cache enable, data cache enable

   // Set up clock - using 16MHz internal clock
   RCC->CR |= RCC_CR_HSION;
   RCC->PLLCFGR = 0x12002D08; // 180MHz
   RCC->CR |= RCC_CR_PLLON;
   // wait for the PLL to be ready
   while (!(RCC_CR_PLLRDY & RCC->CR));

   // switch clock to the PLL, set up dividers
   RCC->CFGR = 0x9402; // 180MHz

   // wait for the clock to be switched
   while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);

   RCC->AHB1ENR |= 0xFF; // enable GPIO clocks

   // Configure systick
   // Lower systick interrupt priority to lowest level
   NVIC_SetPriority(SysTick_IRQn, 0xf);

   // Set interrupt frequency to 1000 Hz
   SysTick->LOAD = (180000) - 1;

   SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
   SysTick_CTRL_ENABLE_Msk |
   SysTick_CTRL_TICKINT_Msk;
}