Bringing up a SAM4S with Keil and FreeRTOS, Failure in XPortStartScheduler with configPRIO_BITS check

ppotts wrote on Thursday, May 23, 2019:

Hello all,

I have previously used FreeRTOS successfully for a project targeting the SAM4E16E. I’m now doing a project on a SAM4S2A and having some trouble. I’m using Keil uVision V5.27.1.0.

I noticed that recent uVision project wizards had the ability to include FreeRTOS, so I did that when configuring the project, rather than using the manually-configured version as in the older project. It seems like there is some conflict in how the priority bits are defined.

I’m getting a failure in xPortStartScheduler, particularly the line:

configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );

The version of port.c I’m using comes from:

Keil_v5\ARM\PACK\ARM\CMSIS-FREERTOS\10.2.0\Source\portable\GCC\ARM_CM3\port.c

I’m not sure this is the right version, but the values in the CM4 versions looked similar.

portMAX_PRIOGROUP_BITS is defined as 7

The version of FreeRTOSConfig.h I’m using was created under RTE\RTOS\FreeRTOSConfig.h and defines configPRIO_BITS like this:

#ifdef __NVIC_PRIO_BITS
  /* __NVIC_PRIO_BITS will be specified when CMSIS is being used. */
  #define configPRIO_BITS                     __NVIC_PRIO_BITS
#else
  /* 7 priority levels */
  #define configPRIO_BITS                     3
#endif

NVIC_PRIO_BITS comes from the pack: SAM4\DFP\1.6.1\Device\Include\Sam4S\sam4s2b.h where it is defined as 4.

So, it appears that maybe when parsing FreeRTOS.h, NVIC_PRIO_BITS is not in scope, and therefore we’re getting configPRIO_BITS equal to 3, and the runtime value of ulMaxPRIGROUPValue is 3, so it’s checking to see if 7 - 3 == 3.

I could do something to hack these generated files so NVIC_PRIO_BITS would be in scope when FreeRTOSConfig.h is parsed, but it seems like this should be something that the generated project code took care of. I’d like to do this the “right way” if possible. Any ideas where it went wrong?

Thanks,

Paul

rtel wrote on Thursday, May 23, 2019:

Are you saying that if configPRIO_BITS is manually set to 4 in
FreeRTOSConfig.h then the configASSERT() passes? If so then it does
seem to be an include dependency issue somewhere - to which I would ask
have ARM changed the source files in any way? FreeRTOS.h must always be
included first, then the header file for the APIs you are using (task.h,
queue.h, event_groups.h, etc.) - and never include FreeRTOSConfig.h
manually as it is brought in at the right time by FreeRTOS.h.

If it is not a dependency issue, and port.c is genuinely using
__NVIC_PRIO_BITS and not the hard coded 3, and __NVIC_PRIOR_BITS is set
correctly for the device (more than once found that not to be the case),
then most likely cause is that somewhere in the start up code the
priority bits are being split between preemption and sub priorities.
That is normal on STM32, where has to be manually switched back to all
preemption priority and no sub priority (what it needs to be), but I’ve
never seen anything like that on a SAM device.

ppotts wrote on Thursday, May 23, 2019:

Hi Richard,

Are you saying that if configPRIO_BITS is manually set to 4 in FreeRTOSConfig.h then the configASSERT() passes?

Testing that theory now…

ppotts wrote on Thursday, May 23, 2019:

Hmmm. If I make that change, it seems to fail a few lines earlier, line 276 in port.c:

		/* The kernel interrupt priority should be set to the lowest
		priority. */
		configASSERT( ucMaxPriorityValue == ( configKERNEL_INTERRUPT_PRIORITY & ucMaxPriorityValue ) );

ucMaxPriorityValue is 0xF0 and it looks like configKERNEL_INTERRUPT_PRIORITY is defined in FreeRTOSConfig.h as:

#define configKERNEL_INTERRUPT_PRIORITY               (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

Looks like I also may need to change need to change configLIBRARY_LOWEST_INTERRUPT_PRIORITY to 0x0F if I’m going to force configPRIO_BITS to 4?

That seems to result in passing all the asserts, and I see that my initial startup task is executing, but it looks like the first task I launch from there is not executing, so I’m looking into that now.

ppotts wrote on Thursday, May 23, 2019:

It appears that my first task is never returning from its first attempt at xSemaphoreTake(). It seems that it is never timing out and getting stuck in portSUPPRESS_TICKS_AND_SLEEP(). Looking into that.

rtel wrote on Thursday, May 23, 2019:

Is the tick interrupt executing? If you pause the debugger and inspect
the variable xTickCount is it increasing at the expected rate? If not,
timeouts won’t happen.

ppotts wrote on Thursday, May 23, 2019:

I will continue to look into it tomorrow. I guess I expected the Keil project configurator to produce settings for this project that would support bringing up and running at least a couple of my tasks (ported from my previous project also for the SAM4 family). But that does not seem to be the case, so I guess I have to step through everything…

ppotts wrote on Thursday, May 23, 2019:

No, it looks like xTickCount is not increasing, although oddly it appears to be going back and forth between 0 and 1.

I also had to fix a problem where the default heap size was only 4096 bytes, which seems a little ridiculous, and meant that I couldn’t launch more than one task.

ppotts wrote on Friday, May 24, 2019:

Well, I spoke too soon. It does seem like SysTick is running. It is hard to get a breakpoint and watch on xTickCount to work reliably, but the system peripheral viewer in the uVision IDE shows it is running. Reading the datasheet last night, I thought it might be stopped because it might be configured by default to use an external crystal, and I’m using the embedded 4/8/12MHz fast RC oscillator. That can’t be the case because it looks like it is set up by default to use the processor clock. However, I’m still seeing the execution get stuck and never return from the first call to vTaskDelayUntil().

I’m going to dig into my clock configuration, and see if I can get the same clock onto a microcontroller pin so I can verify the speed.

Thanks for your suggestions!

rtel wrote on Friday, May 24, 2019:

Sorry - its not clear - if I understand you correctly then SysTick is
running but xTickCount is not incrementing. If that is the case then it
is probably because the FreeRTOS systick interrupt handler is not
installed. Search for vPortSVCHandler on this page
https://www.freertos.org/FAQHelp.html

ppotts wrote on Friday, May 24, 2019:

I don’t think it is that. The macros xPortSysTickHandler, etc. are defined in my FreeRTOSConfig and I can see in the link map that the SysTick from port.c is included:

startup_sam4s.o(RESET) refers to port.o(i.SysTick_Handler) for SysTick_Handler
...
SysTick_Handler                          0x00400751   Thumb Code    46  port.o(i.SysTick_Handler)

I was also able to catch a breakpoint in the SysTick interrupt handler xPortSysTickHandler(), but they don’t seem to be happening consistently, so I think it may be a clocking issue.

ppotts wrote on Friday, May 24, 2019:

Looks like the tick problem was the clocking configuration for master clock (MCK). I’ve got task switching and timeouts going now and SysTick is coming from the internal RC oscillator which is what I want for my prototype board. Thanks for your help!