STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Dear Forum: I am experiencing problems with the FreeRTOS port for the STM32L152 Eval. board and I am not sure if it is correct. The environment is as follows: Board: ST32L152-EVAL Processor: STM32L152VB FreeRTOS Version: 8.0.1 Toolchain: Rowley Crossworks for ARM The “FreeRTOS Blinkly” example for the STM32L Discovery Board works but “Example 1” for the Cortex M3 does not. I created the execution environment by cloning the environment from the Blinky example as much as possible. The problem is that when the example is executed only Task1 runs–indicating the scheduler is not working correctly. The modification to the Blinky environment are as follows.
  • Simple main.c (Example 1) and basic_io.h (Cortex M3 Version) PATH/CrossWorks for ARM/v3/packages/samples/FreeRTOS$
Stellaris features are disabled in main.c.
  • basic_io.c with minor modification (Cortex M3 Version)
Replaced printf() with debug_printf()
  • Default FreeRTOSConfig.h PATH/CrossWorks for ARM/v3/packages/targets/STSTM32L152CDISCOVERY$
Best Regards, Paul R.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Here are the relevant files.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Can you describe how you know only one task is running – are you getting any print outs at all, and if so, what is the pattern of the output. What happens if you replace the calls to print output with simple variable increments – with both tasks using a different variable. Do both variables indicate (showing that both tasks run if debug_printf() is not called)? Which project did you base your working blinky example on? I don’t think there is a Rowley project for the STM32L152 in the download. Does the project have any additional hardware setup that is required before you create the tasks and start the scheduler (I note you commented out the Stellaris specific hardware line). Regards.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

There are two ways I know Task1 is the only one running. First, it is the only task that prints anything. Second, if you put a breakpoint, just before the vPrintString() call, in Task1 and Task2 and disable the debugprintf() in basicio.c, only the breakpoint in Task1 is ever reached. Similarly, if you put a global execution counter in both Task1 and Task2, and stop execution only the counter in Task1 is updated. The Blinky example came as port of sample projects delivered by Rowley. The Blinky project does not appear to require special hardware setup. The Blinky example is very short and the relevant files, main.c and main_blinky.c are attached. As you will notice, there is no special hardware initialization.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

What about the interrupt vector table? How is the Rowley project installing the FreeRTOS handlers on the SysTick, PendSV and SVCall vectors? This can be done in [at least] one of two ways – either the names of the FreeRTOS handlers can be installed directly, or if the vector table is using CMSIS handler names then the FreeRTOS handlers can be mapped onto their CMSIS equivalents as described in bullet number 1 on the following page: http://www.freertos.org/FAQHelp.html Regards.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

ST sent intialization code which fails during clock initialiazation. The file with the board initialization code is attached to this note. The point of failure is as follows: void SystemInit() { RCC->CR |= RCCCRHSEON; // // ********* Comment: BUG – RCCCRHSERDY is never set ! ************ // while ((RCC->CR & RCCCRHSERDY)==0); FLASH->ACR |= FLASHACRACC64; FLASH->ACR |= FLASHACRPRFTEN; FLASH->ACR |= FLASHACRLATENCY;

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Sent code where? To you or to Richard (FreeRTOS)? Is your problem fixed now? Are you certain this is a bug? Sometimes clocks can fail to lock if there is a power rail problem. Presumably you are running this on real hardware not a simulator, how is the hardware powered?

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

The board is powered via USB and it is real hardware. ST sent the code to me.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Afterthought: If Richard would like, I can send him the package.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Correction: The package came from Rowley rather than ST !

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Crossworks suggested trying an external DC power supply. I tried it and it made no difference. I don’t think lack of power from the USB port is a problem because this is a very low power device and the Discovery version of Blinky runs on the board.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Below is a partially commented list of the differences between the STM32L152-EVAL and STM32L-Discovery board initialization code. The first obvious difference is the user of the internal clock on the Discovery board versus the external clock on the STM32L152-EVAL board. Search for the word “Comment” for further differences. (i.e. Only the code related to clock configuration has detailed comments.) Is it possible the use of the external clock is the problem ? **************** KEY ************* < Means STM32L152-Eval Board with
Means the STM32L-Discovery board
Both cases STM32L152VB Processor
#

Comment: Pin Names.

# 19,20c19,20 #

RCC_CR Register External Clock

# < RCC->CR |= RCCCRHSEON;

< while ((RCC->CR & RCCCRHSERDY)==0);

#

RCC_CR Register Internal Clock

#
RCC->CR |= RCCCRHSION; while ((RCC->CR & RCCCRHSIRDY)==0); 30c30 #

Comment: Exact clock configuration.

#

PLL: Entry Clock Source, MUL12 Configruation, Clock Output = CKVCO 3

#

< RCC->CFGR = RCCCFGRPLLSRC|RCCCFGRPLLMUL12|RCCCFGRPLLDIV3;

#

PLL: MUL 4 Configuration, Clock Ouput = CKVCO 2

#
RCC->CFGR = RCCCFGRPLLMUL4|RCCCFGRPLLDIV2; 35c35

< SystemCoreClock = 32000000; // 32 Mhz

SystemCoreClock = 32000000; // 32 Mhz 38c38

< //STM32L152-EVAL LD1 led connected to port D pin 0, Key push-button is connected to port C pin 13 (EXTI 13).

//STM32L-DISCOVERY LD3 led connected to port B pin 7, User push-button is connected to port A pin 0 (EXTI 0). 43,46c43,46 #

Comment: GPI Setup – TBD: Investigate

# < // Turn on GPIOD, GPIOC < RCC->AHBENR |= RCCAHBENRGPIOCEN | RCCAHBENRGPIODEN; < // Set PD_0 to output

< GPIOD->MODER |= GPIOMODERMODER0_0;

// Turn on GPIOA, GPIOB RCC->AHBENR |= RCCAHBENRGPIOAEN | RCCAHBENRGPIOBEN; // Set PB7 to output GPIOB->MODER |= GPIOMODERMODER70; 49,52c49,52 49,52c49,52 < // Associate PC13PIN to EXTINT13 – interrupt on a falling edge < SYSCFG->EXTICR[3] |= SYSCFGEXTICR4EXTI13_PC; < EXTI->FTSR |= 1 << 13; // falling edge trigger

< EXTI->IMR |= 1 << 13; // enable interrupt

// Associate PA0PIN to EXTINT0 – interrupt on a falling edge SYSCFG->EXTICR[0] |= SYSCFGEXTICR1EXTI0_PA; EXTI->FTSR |= 1 << 0; // falling edge trigger EXTI->IMR |= 1 << 0; // enable interrupt 59c59

< GPIOD->BSRRL = (1<<0);

GPIOB->BSRRL = (1<<7);
61c61

< GPIOD->BSRRH = (1<<0);

GPIOB->BSRRH = (1<<7);
67c67 #

Comment: Interrupt Configuration.

#

< EXTI1510IRQHandler(void)

EXTI0_IRQHandler(void) 70c70

< if (EXTI->PR & (1<<13))

if (EXTI->PR & (1<<0)) 73c73

< EXTI->PR = (1<<13);

  EXTI->PR = (1<<0);
82,83c82,83 < ctlsetpriority(EXTI1510IRQn, ctladjustisrpriority(ctlhighestisrpriority(), -1));

< ctlunmaskisr(EXTI1510IRQn);

ctlsetpriority(EXTI0IRQn, ctladjustisrpriority(ctlhighestisrpriority(), -1)); ctlunmaskisr(EXTI0IRQn);

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

The Blinky example of the ST32L152EVAL version of FreeRTOS works is you use an internal clock as in the Discovery version. This can be done by making the following minimal changes to the STM32ctl_board.c SystemInit() routine. However, this is just an experiment and probably isn’t completely correct. 1) Replace the following code segment. RCC->CR |= RCCCRHSEON; while ((RCC->CR & RCCCRHSERDY)==0); With the following code segment. RCC->CR |= RCCCRHSION; while ((RCC->CR & RCCCRHSIRDY)==0); 2) Replace the following line RCC->CFGR = RCCCFGRPLLSRC|RCCCFGRPLLMUL12|RCCCFGRPLLDIV3; With the following line of code. RCC->CFGR = RCCCFGRPLLMUL4|RCCCFGRPLLDIV2; However, basic FreeRTOS Example1 still does not execute correctly. In particular only Task1 is started–indicating the scheduler is not working correctly.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

It looks like the interrurpt handler names are being mapped to the CMSIS equivanlents. For example vPortSvcHandler() is mapped to SVCHandler(). I would assume this means SVCHAndler() should be plugged into the interrupt vector table but I am not sure where the table is being populated.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

This would normally be in the C start up assembly file. You sent me a zip files example1freertos.zip, STSTM32L152CDISCOVERY.zip and STSTM32L152C_DISCOVERY – none of which seem to contain any start up code that I can see. If you start a debug session without running to main() – so you break on program entry – you will most probably be in the file that has the vectors. Regards.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

The startup code is called before main() and the file with the code–STM_startup.s is attached.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

As per the links already provided, FreeRTOS needs three handlers installed: PendSV In the file you posted this is called PendSV_Handler. SVC In the file you posted this is called SVC_Handler. SysTick In the file you posted this is called SysTick_Handler. These are the CMSIS names for the functions, so the easiest thing to do is leave the start up code unedited, and instead map the FreeRTOS handlers to the CMSIS handlers as described on the link posted above, and replicated below:

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
Regards.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

This is already done in FreeRTOSConfig.h

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

The scheduler problem was that the FreeRTOS heap size–configured with configTOTALHEAPSIZE in FreeRTOSConfig.h was too small. Setting it 10K works. It is important to know that the FreeRTOS heap size is not the same as the Crossworks heap size, and you need to tune the FreeRTOS heap size rather than the Crossworks heap size. The clocking problem with the STM HSE clock is still open and may be a hardware problem.

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Does FreeRTOS manage its own stack space and does it follow the normal rule–the stack grows down the heap grows up ?

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Look at the return value when you create the task, see also malloc fail hook and read memory management on the FreeRTOS web pages. lots of ways to catch that failure

STM32L152 EVAL Board Port: Example 1 – Scheduler Failure

Here are some useful links: http://www.freertos.org/a00111.html http://www.freertos.org/a00016.html (for the malloc failed hook) http://www.freertos.org/Stacks-and-stack-overflow-checking.html Whether the stack grows up or down depends on the chip, not on FreeRTOS. In your case (as in most cases) it grows down. Regards.