Skip to main content

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;
}

Comments

Popular posts from this blog

Interface a Rotary Encoder the right way.

So whilst reading my favorite odyssey found here I stumbled onto something I never spotted before. It turns out that the general purpose timers support hardware interfacing with an incremental encoder. This means no more interrupts and no need to increment whatever variable you had. Now all you have to do is get the value from the Count register in the timer. Did I also mention it takes care of figuring out which direction you are turning it? Amazing! Lets talk about it.






Encoder Interface Mode Verbatim from the reference manual of the STM32F103 page 392 or Section 15.3.12  "Encoder interface mode acts simply as an external clock with direction selection. This 
means that the counter just counts continuously between 0 and the auto-reload value in the 
TIMx_ARR register (0 to ARR or ARR down to 0 depending on the direction). So the user 
must configure TIMx_ARR before starting. In the same way, the capture, compare, 
prescaler, trigger output features continue to work as normal."
W…

STM32L0/F0/F3 I2C : Part 3 RX TX via DMA

Most modern microcontroller come with a peripheral called DMA which allows for an even more hands-off approach. The Direct Memory Access controller will get a tutorial of it's own in the future. However, it is so simple to use that I can easily explain the required bits in this tutorial without feeling like I will overwhelm the reader. In this iteration of the I2C series I will cover how to TX and RX date on the peripheral in conjunction with the DMA controller. 

First let me briefly explain in a high level what the DMA controller does. It allows you to transfer data in 3 ways: Peripheral to memoryMemory to peripheralMemory to memory. What does this mean? For example, when you receive data on I2C in your RXDR register, you can have the DMA controller move that data received into an array. At the end of the day your variables are just memory locations, so if you have declared an array it has an address associated with it, this is address is what the DMA considers  "Memory"…

STM32 I2C Does it suck?

Recently I have been annoyed with  bugs in the I2C implementation in ST's F1/L1/F40/F2 series, and  any microcontroller made by ST before 2012. There appears to be, what I can only describe as, a race condition when attempting to receive data in I2C interrupt(low priority)  or polling mode.





Just to be clear a race condition is defined as , verbatim from wiki: "the behavior of an electronics, software, or other system where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events. It becomes a bug when one or more of the possible behaviors is undesirable."
I was humming along trying to make my YouTube tutorials when I arrived to the I2C protocol implementation. I have used I2C with the F1 series plenty of times, however I have never had the need to receive data from a slave. However for the sake of completeness I decided to implement an RXing routine in I2C for my tutorial. Only to find statements like this in the referen…