Tuesday, January 15, 2019

STM32L0 : Changing Clock Frequency

STM32L0 : Changing Clock Frequency

Changing the clock frequency is something I usually never do because the startup file provided by Keil sets the STM32F1 to 72MHz by default, which has always been fine with me. However as late I have been testing out TrueStudio as an IDE. At the same time I managed to break my last St-Link so I have been using my Nucleo board with its on-board ST-Link to play around with TrueStudio. I will give my thoughts on TrueStudio on a later post.
By default the Nucleo pictured here runs on its internal RC oscillator @ 2MHz, This series of MCU by ST targets low power applications so this explains their default setting. To change the frequency requires setting a few bits in a few registers and checking a few flags, imagine that. However, to really send this bad boy running requires some soldering and desoldering of solder bridges, I do not have any other Nucleo boards so I do not know if this is a common practice with them, but the way this specific board has been manufactured it is. The soldering required is straight forward so fear not.
The hardware modification is necessary because there is no external crystal or oscillator  connected to the appropriate pin A0 on the microcontroller, in fact I believe this little guy only accepts an external clock on that single A0 pin, and not a conventional crystal. (I am not talking about the 32KHz clock for the RTC, I am only talking about main System Clock)So you could use something like a MEMS oscillator. But in this case the board was manufactured in such a way that the ST-Link that is on-board shares its clock.
This is done by enabling the Master Clock Output (MCO) on the ST-Link microcontroller which is an STM32F1. That master clock output is then fed to the A0 clock pin of the STM32L031. To make that connection we have to remove some solder bridges and create one. Well the bridges are already there we just must provide the solder.


The hardware part:


Here is a link the manual for the specific board I am using. On page 33 you will see the following schematic of the MCU and notice the SB17 (Solder bridge) which connects the MSO (MASTER CLOCK OUT) to the mcu A0. 




Another important part of this manual is page 19 that shows what solder bridges need to be on or off to get the desired clock. Where "ON" means that we must close the gap in the solder bridge and thus make a connection, and "OFF" means we remove any solder/jumper/0-Ohm resistor making the connection and thus break the connection. I have provided the table on page 19 here for your viewing pleasure.



Below are images taken from pages 11 and 12 of the manual showing the location of the specified
solder bridges. Click to enlarge.





In a nutshell you are going to desolder bridges 4 5 6 7 and 8. Meaning that if there is a 0 ohm resistor bridging the gap you must remove it. If there is solder alone bridging the gap you must remove it. Then on the other side of the board you will find solder bridge number 17 but for this one you must bridge the gap, adding enough solder to complete the connection.


The software part:

 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
void setClockTo32Mhz(void)
{
 //adjust flash latency
 REG_VAL = FLASH->ACR ;
 FLASH->ACR |= FLASH_ACR_LATENCY ;
 while( (FLASH->ACR & FLASH_ACR_LATENCY) == 0 ) ; //wait for latency set flag

 //set voltage scaling to range 1
 PWR->CR |= PWR_CR_VOS_0 ;
 PWR->CR &= ~(PWR_CR_VOS_1);
 while( ((PWR->CSR) & (PWR_CSR_VOSF)) == 1) ; //wait for voltage to settle

 //turn on HSE external, HSE bypass and security
 RCC->CR |= RCC_CR_CSSHSEON | RCC_CR_HSEBYP |  RCC_CR_HSEON ;
 while( ((RCC->CR) & RCC_CR_HSERDY) == 0) ; //wait for the HSE to be ready

 //reset and configure pll mull and div settings, and PLL source
 RCC->CFGR = (  (RCC->CFGR & ~(RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL)) | RCC_CFGR_PLLDIV2 | RCC_CFGR_PLLMUL8 | RCC_CFGR_PLLSRC_HSE ) ;
 while((RCC->CR & RCC_CR_PLLRDY )== 1) ;

 //turn on PLL , wait for ready
 RCC->CR |= RCC_CR_PLLON;
 while(  ((RCC->CR) & RCC_CR_PLLRDY) == 0  ) ; // wait for pll to ready

 //set PLL as system clock
 RCC->CFGR |= RCC_CFGR_SW_PLL;
 while(  ((RCC->CFGR)&(RCC_CFGR_SWS_PLL)) != RCC_CFGR_SWS_PLL );
}


It is very important that after any modification to the system clock or system bus clocks the function SystemCoreClockUpdate is called. According to the CMSIS header file where this function is located:

Each time the core clock (HCLK) changes, this function must be called to update the SystemCoreClock variable value. Otherwise any configuration based on this value will be incorrect .

One of those configurations being my favorite SystickConfig function. As you can see below only after updating my clock and calling the SystemCoreClockUpdate function do I call my SysTickConfig function. Otherwise the systick will be configured using the default 2MHz value.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int main(void)
{ 
 setClockTo32Mhz();
 SystemCoreClockUpdate();
 
 SysTick_Config(SystemCoreClock/1000);
 
  while (1)
  {

  }

  return 0;
}

Post a Comment

Whatsapp Button works on Mobile Device only

Start typing and press Enter to search