In an effort to minimise the amount of space taken up on my micromouse board, I wanted to use the internal oscillator (HSI) built in to the STM32F4 device I am using. As ever, working out how to set that up in code is not obvious. However, ST do have a spreadsheet tool that can generate the appropriate source code for you.

The spreadsheet is associated with the ST application note AN3988: Clock configuration tool for STM32F40x/41x microcontrollers. You can find a link to the App Note here ( in the Design Support tab. The spreadsheet itself is linked at the bottom of the page under the section called Configuration Utilities.

Unfortunately, the spreadsheet runs only in Excel on Windows and requires that you turn off all the security to make it work. Instructions for doing this are in the App Note. Things would be hugely more pleasing if either Excel didn’t let your spreadsheets wreak havoc without disabling useful stuff or ST made a platform independent tool that didn’t ask you to do stupid things – or both, ideally.

What the spreadsheet does is allow you to select an operating frequency and some other parameters like the requirement for a 48MHz clock for USB. When you click the Run button, you are asked whether to use the internal or external oscillator. If it is to be the external oscillator, you must have filled that in first.

After running,  the various clock speeds are shown so that you can check that they meet your expectations. If you are happy, click the Generate button and the spreadsheet will create a system_stm32f4xx.c file that you can copy into your project to replace the one you had from the project template or peripheral library examples or whatever. Be aware though that the spreadsheet cheerfully overwrites any existing generated file to save a copy before generating another one if you need to.

I was curious to see the exact difference in setup between using the internal oscillator (16MHz on the STM32F4 parts) and an external 16MHz crystal so I generated two config files and compared them with a diff tool.

It turns out that, if the external crystal frequency is the same as the internal oscillator frequency, there are only two differences in the code – other than some changes in the explanatory comments.

The first reflects the fact that, after power up, the HSI oscillator is on by default whereas, to use the external oscillator, you need to turn it on and wait for it to be ready. So, in the function SetSysClock(), when you use the external clock, you get this block of code:

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  /* Enable HSE */
  RCC->CR |= ((uint32_t) RCC_CR_HSEON);

  /* Wait till HSE is ready and if Time out is reached exit */
  do {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
  } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
    HSEStatus = (uint32_t) 0x01;
  } else {
    HSEStatus = (uint32_t) 0x00;

Then the rest of the setup gets wrapped up in an if statement that carries on if the HSE starts up but just sits and does nothing if it does not.

The other difference is to tell the Phase Locked Loop where to get its clock source from

/* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) |
            (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

When using the internal oscillator, RCC_PLLCFGR_PLLSRC_HSE, is replaced by RCC_PLLCFGR_PLLSRC_HSI.

All in all, it turns out not to be so hard. The internal clock should be plenty accurate enough for my purposes – especially as I don’t intend using USB. Some time, I must work out how to slow the clock right down on the fly as a power saving measure. Some time.

This Post Has One Comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.