Tag: STM32F4

FreeRTOS Simple Tasks

Keywords: Embedded systems, ARM, FreeRTOS, Tasks, STM32F4 Code Link: Tutorial Source Code Github – Keil In this tutorial we will demonstrate how to create a FreeRTOS Task. Tasks are main building blocks of any Application that wants to use a real-time OS. A task is […]

Integrating FreeRTOS and STM HAL Libraries

Keywords: Embedded systems, ARM, FreeRTOS, Tick Timer, HAL Libraries, STM32F4 Code Link: Tutorial Source Code Github – Keil By the time i was writing FreeRTOS tutorials, I thought of making FreeRTOS tutorial (on STM32F4 Platform) by integrating FreeRTOS with Standard Peripheral Libraries provided by ST […]

Changing FreeRTOS Tick Timer – Systick Timer

Keywords: Embedded systems, ARM, FreeRTOS, Tick Timer,STM32F4

Code Link: Tutorial Source Code Github – Keil

This is the only freeRTOS tutorial in series containing bare-metal code. All subsequent tutorials are based on STM32 HAL libraries. The background reason behind this tutorial is that both HAL libraries and FreeRTOS use ARM Systick timer as a default timer (on ARM Cortex-M platform) for delays (in case of HAL libraries) and tick timer operations (in case of freertos). The conflict arises when HAL and freeRTOS don’t agree on same interrupt frequency (ticks per second). This tutorial is based on ARM cortex-M4F profile with port used for Keil compiler (RVDS).

Before going into actual implementation, let’s briefly discuss how freeRTOS implements tick timer and corresponding timer handler.

The FreeRTOS main kernel module is port.c which provides access to actual underlying hardware. port.c contains all the hardware dependent implementation. FreeRTOS uses void vPortSetupTimerInterrupt(void) function to setup and configure a tick timer which is used as reference clock for freeRTOS kernel to schedule tasks. For ARM cortex-m based Microcontrollers, the default tick timer used by freeRTOS kernel is called Systick Timer. The Systick timer is an oncore timer provided by ARM to facilitate OS functionality on Cortex-M profile cores.

Note: In some port.c files, the function is renamed to void prvSetupTimerInterrupt(void). For example the ARM_CM4_MPU port is using this function for implementing tick timer. According to FreeRTOS forum, there is no specific reason behind this illogical renaming. Anyhow in any case the point is to point out the main function that actually implement the timer.

If we go down into port.c file, we will see vPortSetupTimerInterrupt is defined similar in one the following ways.

Case-1:

#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0

   void vPortSetupTimerInterrupt( void )
   { 
     ..... 
   }

#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */

Case-2:

__weak void vPortSetupTimerInterrupt( void ) 
    { 
	  .....
    }

In the first case configOVERRIDE_DEFAULT_TICK_CONFIGURATION macro is used to add / remove the vPortSetupTimerInterrupt function from compilation. if the macro is set to any value other than 0, the function will be excluded from compilation and the compiler will throw an error if another implementation of vPortSetupTimerInterrupt function is not provided in the entire source code. This means (in the first case), if we want to give freeRTOS scheduler our own implementation of timer, we must have to set configOVERRIDE_DEFAULT_TICK_CONFIGURATION to some value other than 0 usually 1 in FreeRTOSConfig.h file.

In the second case the __weak keyword suggests that this function implementation is linked weakly to other module and if another implementation of the function is found, the function definition will be replaced by the new one thus skipping the implementation defined with __weak keyword. In second case all we have to do is to only provide a function that only configure our desired timer functionality.

NOTE: It is highly recommended NOT to edit port.c file. Use configOVERRIDE_DEFAULT_TICK_CONFIGURATION macro to remove the implementation from compilation. Also vPortSetupTimerInterrupt must not be defined or declared with internal linkage i.e. with static keyword. Its linkage must be kept global unless and until you have decided to make changes to the original port.c file or in cases where both the __weak and configOVERRIDE_DEFAULT_TICK_CONFIGURATION are missing like ARM_CM4_MPU port.c file.

The second thing to clarify is how to inform freeRTOS kernel about a tick/ time expiry / timer interrupt to reschedule/run tasks in queue. The freeRTOS uses the xPortSysTickHandler() function for this purpose. Actually in ARM cortex-M ports it’s not even a function, it’s a macro which is actually replaced by SysTick_Handler() function. SysTick_Hanler() is the default ISR for Systick timer, declared in Microcontroller startup(e.g. startup_stm32f407xx.s) file.

FreeRTOS configuration file (FreeRTOSConfig.h) uses the following marco to replace every found xPortSysTickHandler keyword with SysTick_Handler at preprocessor (first stage of compilation) time.

#define xPortSysTickHandler SysTick_Handler

This line must be comment out in FreeRTOSConfig.h file while configuring another timer to be used as a tick timer.

The final thing you must consider while changing timer is that the interrupt rate/tick rate of new timer must be same as defined by configTICK_RATE_HZ in FreeRTOSConfig.h file.

That’s all you need to know in order to change default Systick timer used by FreeRTOS kernel as tick timer. Let’s get into implementation.

Steps:

1. The first step is to create new project using Keil MDK v5. The following tutorial illustrates creating new project with Keil MDK-v5.

2. The next step is to define a function with name vPortSetupTimerInterrupt() with global visibility (default in C) in any of your C file. For convenience we will define it into main.c file. Just to keep things simple.

For illustration purpose we will use STM32f4-discovery Timer-2 as a replacement of tick timer. As the tick rate is 1000 as defined by configTICK_RATE_HZ MACRO, so the general-purpose timer i.e. timer-2 is configured to generate interrupt every 1ms i.e. frequency 1000.

Note: If you don’t know how to configure STM timers refer to the following tutorial for detail timers configuration.


/*********************************************
    
    From FreeRTOSConfig.h
    configTICK_RATE_HZ = 1000
    So Timer-2 needs to be configured to
    generate 1msec delay that matches
    configTICK_RATE_HZ rate.
 *********************************************/

 void vPortSetupTimerInterrupt (void) {
        
    /*****************************************
        Timers Configuration
     *****************************************/
    
    /* 
        From STM32F407 datasheet, Timer2 is clocked from
        APB1 bus (42Mhz max). In default configuration
        Timer-2 is receiving 16Mhz (HSI) bus clock.
    */
    
    /* Enable clock to Timer-2 on AHB-1 Bus */
    __setbit(RCC->APB1ENR, 0U);

    /*
        Divide the timer-2 input frequency (16Mhz)
        by a factor of 1000 (16,000,000/1,000 = 16,000 = 16Khz) 
    */
    TIM2->PSC = 1000;
    
    #if (UP_COUNTER)
     /* Up-Counter mode*/
     __clearbit(TIM2->CR1, 4U);
    #else
     /* Down Counter*/
     __clearbit(TIM2->CR1, 4U);
    #endif

    /*
        As configTICK_RATE_HZ = 1000, so tick timer
        need to generate interrupt at the rate of 1000/sec (1msec delay).
        As the input frequency is 16khz so the total
        counts required for 1msec delay:
        
        total counts = 1msec * f
                     =  0.001 * 16,000
                     = 16
    */
    TIM2->ARR = 16;

    /*
        Enable timer-2 Update interrupt to
        generate interrupt on counter overflow/underflow
    */
    __setbit(TIM2->DIER, 0U);

    /*
        Timer-2 interrupt is received on IRQ-6 on NVIC
        so enable IRQ-6 on NVIC for interrupt detection
    */
     NVIC_EnableIRQ(TIM2_IRQn);
     
     /* Start Timer-2 */
     __setbit(TIM2->CR1, 0U);
}

3. Set the priority of tick timer (timer-2 in this case) to lowest priority available. In case of STM32f4xx, the lowest priority available is 15. See the following tutorial for better understanding of ARM Interrupt priorities.

NVIC_SetPriorityGrouping(0U);
    
/* Tick timer should have least priority */
NVIC_SetPriority(TIM2_IRQn,0xff);	

4. Next, go to port.c file and locate the vPortSetupTimerInterrupt function. If it is defined like shown in Case-1 mentioned above, set configOVERRIDE_DEFAULT_TICK_CONFIGURATION to 1 if already set to 0 or simple add the following code to your FreeRTOSConfig.h file.

#define   configOVERRIDE_DEFAULT_TICK_CONFIGURATION     1

Otherwise if the it is define with __weak keyword, like in Case-2, then just skip this step.

5. Next comment out the following line in FreeRTOSConfig.h file

//#define xPortSysTickHandler SysTick_Handler

6. Implement the timer ISR to be called on every timer interrupt. In our case as we are using Timer-2 so the default timer ISR in Keil is TIM2_IRQHandler. The ISR should do two things. First it should clear the interrupt flag so that next interrupt is generated. This is the first step that must be done in timer ISR to reduce ticks latency. Next is to call xPortSysTickHandler() function in timer ISR to inform scheduler for a timer tick.

void TIM2_IRQHandler (void) {
    
    /* clear timer interrupt */
    __clearbit(TIM2->SR, 0U);
    
    /* call the FreeRTOS kernel for a tick update*/
    xPortSysTickHandler();
}

7. Add the extern void xPortSysTickHandler(void), declaration to your ISR file to avoid implicit declaration compiler warning.

8. This is the most undesirable step (in my opinion) in FreeRTOS tick timer configuration as this requires editing to port.c file. I wonder why Real Time Engineering Group didn’t make a way around it. This step is all about setting default tick timer i.e. Systick Timer priority. Though this step can be omitted as we don’t use Systick as tick timer any more still let’s exclude its priority configuration from source code so that any other library etc. that uses Systick can get expected behavior. It would be much better the code be excluded from compilation using the same macro as used to disable vPortSetupTimerInterrupt i.e. configOVERRIDE_DEFAULT_TICK_CONFIGURATION.

Anyhow, the last step is to comment out the line in port.c file that assigns priority (lowest priority) to Systick Timer. The Following code shows the commented out line. The better approach will be reassign default/desirable priority to Systick in user code, once the FreeRTOS scheduler is called/started.

/* Make PendSV and SysTick the lowest priority interrupts. */
//portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI

That’s it… Congratulation, you have successfully changed the FreeRTOS kernel default timer.

Note: For demonstration purpose we have implemented two tasks that blinks LEDs for demonstration purpose. The complete code can be found in the given github link at the start of the tutorial. The supporting tutorials for configuring STM GPIOs and FreeRTOS tasks creation can be found in the following links.

Video Demonstration:

References:

[1] – Reference manual-RM0090

[1] – FreeRTOS official website

An overview of FreeRTOS Kernel Priorities on ARM Cortex-M Platform

Keywords: Embedded systems, ARM, FreeRTOS, Kernel, STM32F4 When i first started playing with FreeRTOS, one of the main confusion I had was about FreeRTOS Tasks Priority i.e. FreeRTOS Kernel Priorities, and the underlying hardware/Processor Core Interrupt Priorities. In this tutorial we will go one step […]

An Inside view of FreeRTOS Scheduler – ARM Cortex-M Platform

Keywords: Embedded systems, ARM, FreeRTOS, STM32F4, Scheduler Scheduler is the part of Operating System kernel used to schedule various tasks to run simultaneously (feels simultaneously) on a Processor Core thus achieving multitasking phenomena. A single processor core can process only one task at a time. Most […]

Introduction to STM32 Timers

Keywords: Embedded systems, ARM, STM32F4, Timers, Counter

In the world of embedded systems the most important parameter is time. It’s the time that qualifies a systems from simple blinky led to complex inter-systems communication. Its time which defines how fast/slow a job can be done on target processor. Obviously what’s the purpose of time if you can’t count it? This where timers comes into action. Timers provide the facility to measure time relatively from one reference point to another. This relative time measure enables us to generate an event or a specific time interval (like signal) or conversely measure an event time. This makes timers one of the crucial part of Embedded Systems.

The basic idea behind timers is that its logic is provided with some clock and upon each clock it increments/ decrements a counter register value. At the end the counted number of cycles is multiplied with input clock Time period to get the total time elapsed.

Total Time: Counter Value * 1/Frequency

Figure-1: Timer General Operation

A term that usually confuses newbies is the difference between a Timer and a Counter. As a matter of fact there is no such thing as Timers…!!! We only have counters in embedded systems. The source of confusion is that both these terms are NOT so often used INTERFACHANGABLY. The basic functions of both is to count time based events. A minor difference that is usually considered to differentiate timers and counters is frequency source. While in case of timers the input events (clock pulses) have same frequency i.e. clock to timers is fixed; and when the timer is feed from some external events which may or may not of fixed time intervals, the timer is known be as Counter (Counting events). But the basic idea behind both of them is same – They just count events. That’s it.

STM32 Timers:

Based on features/functionalities STM32 Microcontrollers Timers are categorized in 3 main types.

  1. Basic Timers
  2. General Purpose Timers
  3. Advanced Timers

Almost all STM32Fxxx devices come with General purpose timers and Advanced timers with optional availability of Basic Timers which is covered by ARM Systick timer itself.

Basic Timers:

As the name suggests, its a timer with basic functionality of counting and works independently of any I/O interaction. Its just connected to some on-chip frequency source and simply counts time. This type of timer can’t capture external events or produce output signals like PWM etc.

General-Purpose Timers:

This type of timers are available on almost every STM32Fxxx device. These timers are like the Basic timers with one exception that they can also perform I/O operation/interaction like generating PWM on a pin or capturing an event from external source for comparison purpose.

Advanced timers:

These type of timers inherent all the features of General-Purpose timers with add-ons of few advance features that generate SPECIAL signals for some time critical devices like Power Electronics, Motor Control etc.

There is another special purpose timer usually available on embedded SOCs known as watchdog timer. This is a special purpose timer which prevents processor from getting stuck at a single point in software for more than a specified allowed time. The watchdog timer is kicked (reset) in various points in software flow. If software gets stuck in some infinite loop and watchdog timer gets fired (counted to specified value), the watchdog will reset the processor similar to Power ON Reset.

Figure-2: STM32 Timers Types

Example: The STM32F405xx and STM32F407xx devices include two advanced-control timers, eight general-purpose timers, two basic timers and two watchdog timers.

The following table summarize their features.

Table-1: STM32F4xx Timers

STM32 Timer Internals:

Let’s discuss briefly what’s going on under the surface. In this section we will try to dig down a little more into working anatomy of STM32 Timers. I will try to keep things as simple as possible, for more in-depth information, refer to respective SoC datasheet.

Shadow and Preload Register:

In STM32 Timers, certain registers have their duplicate/alias registers. The actual registers are called Preload registers and the duplicate/alias ones are called shadow registers. The shadow registers are not accessible/visible to software while the actual registers can be programmed by software. The point of duplication is to copy and lock the value from actual register to shadow register and then comparison is made with the shadow registers to prevent undesirable results. In other words the Preload registers are used by Software and Shadow registers are used by Hardware.

Following are the registers in STM32 microcontrollers that have their duplicate registers.

  • Pre-scaler Register (TIMx_PSC)
  • Auto-reload Register (TIMx_ARR)
  • Repetition Counter Register (TIMx_RCR)

STM32 Timer Events:

Update Event (UEV): This event causes the shadow registers values to be updated from preload registers (ARR, PSC, CCRx) for possible new values. This event is fired whenever the Counter register overflows/underflows or when the UG bit is set manually by software in TIMx_EGR register.

STM32 Timers implementations consists of the following main blocks.

  1. The clock-subsystem
  2. Time-base Unit (The Timer Kernel)
  3. Input Stage and Signal Conditioning
  4. Output Stage

1. Time-Base Unit (The Timer Kernel):

This is the hearth of STM32 Timers. As a matter of fact this is the actual Timer. It is the base logic where all the counting occurs. The Time-Base Unit basically consists of the following main registers.

  1. Auto-Reload Register: This contains the actual value with which the Timer counted value is compared. There are actually two auto-reload registers. The one that is accessible to software and the one that is shadow of this register. The shadow register is not accessible to software and the value from actual auto-reload register is shifted to shadow register for comparison.
  2. Prescaler Register: This register is used to cut-down/divide the input clock frequency to timer by a constant factor. For example if 100Mhz is the input clock to Timers logic before prescaler and the prescaler register is loaded with 1 (actual divider: prescaler register value + 1) then the frequency that will appear at timer input will be 50Mhz.
  3. Counter Register: This is the actual register that contains the value counted by the timer at any given time.
  4. Repetition Register: This register is used to configure STM32 timers not to generate interrupt/event every time the counter register counts to auto reload shadow-register. The event is generated only when a number (REP register value) of count cycles are completed.
  5. Capture/compare Registers: As the name suggests these register captures input from input channels for comparison and/or produce output after comparison on output channels.
Figure-3: STM32F4xx Timers Time Base

2. The clock-subsystem:

The clock subsystem also known as clock and trigger controller is main clock providing unit that multiplex multiple selectable clock sources on single Timer input line. Following are the main clock sources that feed clock and trigger controller.

  1. Internal Clock: This is the clock source that is feed from RCC STM32 Unit. This clock source comes from main system clock of STM32 MCU Figure-4(1).
  2. ITRx: These are input lines that can be connected to the output of other on-chip timers in master/slave architecture. In this configuration, one timer, called Master, provides clock and other control signals while the receiving timer, called Slave, actually perform the counting operation Figure-4(2).
  3. TIMx_ETR: This line connects timers with external PIN to count external events like counting external pulses Figure-4(3).
  4. TIxFPx: These lines also connect timer to external clock source like TIMx_ETR with the only exception that the input clock from the external pins are first passed through some intermediate logic (discussed later) for edge detection/digital filtration to remove spurious events Figure-4(4).
Figure-4: STM32F4xx Timers clock Sources

3. Input Stage and Signal Conditioning:

The input stage and signal conditioning provide the facility intermediate process like digital filtering etc. before the signal is feed to timer.

Figure-4: STM32F4xx Timers Input Stage

4. Output Compare:

The output stage is used to generate some timing signals like PWM etc. for off-chip peripherals.

Figure-5: STM32F4xx Timers Output Compare

The whole STM32 timers units are interconnected as follow:

Figure-6: STM32F4xx Timers Logic

References:

[1] – Reference manual-RM0090

STM32F4xx GPIO`s (as Input)

Keywords: Embedded systems, ARM, STM32F4, GPIOs, Multiplexed Pins Code Link: Source Code Github Keil- Bare-Metal Code Link: Source Code Github Keil- HAL Libraries GPIOs (General Purpose Input Output) enable a processor to interact with outside world. GPIOs are the most common way of interacting processor […]

STM32F4xx GPIO`s (as Output)

Keywords: Embedded systems, ARM, STM32F4, GPIOs, Multiplexed Pins Code Link: Source Code Github Keil- Bare-Metal Code Link: Source Code Github Keil- HAL Libraries GPIOs (General Purpose Input Output) enable a processor to interact with outside world. GPIOs are the most common way of interacting processor […]

STM32F4xx GPIOs Alternate Function

Keywords: Embedded systems, STM32F4, GPIOs, Multiplexed Pins

The number of transistors per square inch will double approximately every 18 months. (revised)

“Moore’s Law”

As per the above Moore’s Law, doubling the number of transistors per square inch mean more and more functionalities can be added to integrated chips per square inch. This means that without increasing the SoC (System on Chip) size, more and more peripheral like timers, USARTS, memory can be squeezed to occupy to same space available on SoC.

Unfortunately this is only applicable to internal space of SoC. The pins size outside the SoC have standard sizes and can’t be reduced any further. If more pins are added on SoC, again the size of SoC will increase to accommodate the space required for extra pins. What it means is even with the advancement of VLSI technology, though more and more functionalities can be integrated on SoC but no extra pins can be added as it will again increase SoC size so the end result will be useless.

In order to overcome this problem, Chip manufacturers decided to multiplex single pin functionality. i.e. a single pin on SoC can do multiple tasks one active at a time. For example a GPIO pin can be used as Digital input/output or as an analog input/output. Similarly another pin may be used to serve multiple functionality like UART (Tx, Rx), SPI (MOSI, MISO, SCLK, SS), PWM etc. as configured. Apart from the default pin function, all other functions that can be configured for a pin are called Alternate Functions.

STM32F4xx Alternate Function:

Many pins of STM32f4xx devices have multiple functions. They acts as GPIO, General Purpose Input/Output under ‘normal’ functionality. All the alternate functions for these pins can be selected directly by writing to the relevant registers. Figure-1 shows how alternate function for a pin can be selected via GPIOx_MODERGPIOx_AFRL and GPIOx_AFRL .

As shown in Figure-1, on the right most is the actual SoC GPIO pin. The functionalities of a Pins is divided into major groups.
1. As Digital Input/Output
2. As Analog Input/Output
3. As Alternate function Pin.

The first step is to decided what functionality is required on a specific pin under consideration. Once decided, the physical pin can be connected to that line via GPIOx_MODER Register/Multiplexer. The GPIOx_MODER is shown in Figure-2.

Figure-2: GPIOx_MODER Register.

MODERx, x = PIN# = {1,2,3 … 15}

MODERx[1:0] bits:
00: Digital Input (reset state)
01: General purpose output mode
10: Alternate function mode
11: Analog mode

For example, lets say we want to configure GPIOA port Pin#1 as an alternate function. In order to do so, bit-2 of GPIOA_MODER should be set to 0 and bit-3 of GPIOA_MODER should be set to 1.

After configuring GPIOx_MODER for ‘Alternate Function’, the physical pin is now connected to Alternate Function line. The next step is to connect Alternate function line to Alternate function implementor module. This is done via GPIOx_AFRL and GPIOx_AFRH registers.

GPIOx_AFRL: For Lower GPIOx 8-Pins. i.e. Pin#0 – to – Pin#7.
GPIOx_AFRH: For upper GPIOx 8-Pins. i.e. Pin#8 – to – Pin#15.

Following are the codes for alternate functions (AF0-A15).

Alternate FunctionCodeAlternate FunctionCode
AF00000AF81000
AF10001AF91001
AF20010AF101010
AF30011AF111011
AF40100AF121100
AF50101AF131101
AF60110AF141110
AF70111AF151111

Now which alternate function line (AF0 – AF15) connects to which Module (USART, I2C etc.) is implementation dependent. For example alternate functions on STM32F405xx/07xx and STM32F415xx/17xx are as shown in figure-5, figure-6.

Note: Not every GPIO pin can be connected to any Alternate Function (AF0 – AF15). Each Pin is assigned a number of available alternate functions as decided by Manufacturer. For example on STM32F407xx, PA15 pin is multiplexed with TIM 2_CH1, TIM 2_ETR, SPI1_NSS, and SPI3_NSS/ I2S3_W functionalities; – Alternate function mapping Reference Table-9 [1]. For more details on which pin is multiplexed with which modules, see relevant Reference Manual or Data sheet. Normally pins diagram in Datasheet gives the details.

[1] – Reference manual-RM0090

Programing external STM Microcontroller via STM32F4xx Evaluation board

Keywords: Embedded systems, ARM, STM32F4, SWD, JTAG, Debug Adapter You have been playing with your newly bought STM43F4-Discovery board for a while and got a good grasp of all its peripherals. Now you are planning to build your own custom PCB/Product based on ARM Cortex-M […]