SAME70 ARM based priority question

rtimenoob wrote on Thursday, April 06, 2017:

Hello,

I hope somebody can help me.
I don’t know how to setup the freeRTOS priorities for my ATSAME70Q19.
In the datasheet I read that it is using 4 bits (See attachment):

Are these configs correct?

configMAX_PRIORITIES ((unsignes portBASE_TYPE) 15 )
configPRIO_BITS 4
configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 10
configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

Although I read the document about the ARM Cortex Priorities I am not quite sure what this means for me.
Does this mean That my freeRTOS User Task Priorities have to be between 0 (highest) and 15 (lowest)??
Right now my timer does nun start and I don’t know why.

I am really looking forward to your answers.

Werner

rtimenoob wrote on Thursday, April 06, 2017:

Serious? No one?

rtel wrote on Thursday, April 06, 2017:

Serious? No one?

Sorry I don’t understand what this means. Can you explain?

heinbali01 wrote on Sunday, April 09, 2017:

Serious? No one?

This forum is not a customer service where you can put your complaints. Many people try hard to give every person an appropriate answer within a reasonable time. When you show your impatience within a day already, some people may get irritated and unwilling to answer you.
Also you might clarify better what it is that you want (to do).

I’ll try to answer your questions, although I’m not an expert on Cortex-M7 and its NVIC.

#define configMAX_PRIORITIES ( 15 )

This defines the number of different task-priorities that you can use. In your example the highest task-priority is 14.
Do not confuse this with interrupt priorities.

The rest here below is all about interrupt priorities:

#define configPRIO_BITS 4

This macro was sometimes used to indicate the number of valid priority bits (for interrupts).
Sometime defined as __NVIC_PRIO_BITS.
It gives you 16 different priorities, 15 being the lowest, 0 the highest. Priority 0 can not be masked.

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f

Should be correct when configPRIO_BITS equals 4

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 10

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values). */

‘INTERRUPT SAFE FREERTOS API FUNCTIONS’ are functions with a name like xxxFromISR().

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

Defines the priority of the interrupts used by the kernel: PENDSV and SYSTICK.
The shift-left makes sure that the bits end up as the most significant bits: "pppp....", so that the value can be used to set an NVIC register (SYSPRI2).

#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

Same thing for the highest interrupt priority.

Although I read the document about the ARM Cortex Priorities
I am not quite sure what this means for me.

I hope the distinction is now clear: task priorities have nothing to do with ARM NVIC priorities.

Does this mean That my freeRTOS User Task Priorities have to be between 0 (highest) and 15 (lowest)??

In your example (configMAX_PRIORITIES = 15, the range would be 0 .. 14, where 14 is the highest. The Idle Task always has the lowest priority 0.

Right now my timer does nun start and I don’t know why.

Did you get that running already?

rtimenoob wrote on Thursday, April 13, 2017:

Hello,
thank u very much for your answer.
Unfortunatelly I wasn’t able to get it running.
Although in the datasheet is said BASPRI priority bits are [7:4] (4 BITS!!!) the definition for configPRIO_BITS in CMSIS is 3. I do not understand this.
Because I am not sure what is right, I am still using the above settings (4 Bits).
My problem is not, that I am not able to start the Scheduler.
I jump into dummy_handler (Hard Fault) when I hit the function
vTaskStartScheduler()–>xTaskCreate(prvIdleTask,…)–>xTaskGenericCreate(…)–>taskYIELD_IF_USING_PREEMPTION()–>xPortPendSVHandler()

Here I can step through, up to line “stmdb r0!, {r4-r11, r14}”. After that line I directly jump into dummy_handler() because of Hard Fault Error Interrupt.

void xPortPendSVHandler( void )
{
	/* This is a naked function. */

	__asm volatile
	(
	"	mrs r0, psp							\n"
	"	isb									\n"
	"										\n"
	"	ldr	r3, pxCurrentTCBConst			\n" /* Get the location of the current TCB. */
	"	ldr	r2, [r3]						\n"
	"										\n"
	"	tst r14, #0x10						\n" /* Is the task using the FPU context?  If so, push high vfp registers. */
	"	it eq								\n"
	"	vstmdbeq r0!, {s16-s31}				\n"
	"										\n"
	"	stmdb r0!, {r4-r11, r14}			\n" /* Save the core registers. */
	"										\n"
	"	str r0, [r2]						\n" /* Save the new top of stack into the first member of the TCB. */
	"										\n"
	"	stmdb sp!, {r3}						\n"
	"	mov r0, %0 							\n"
	"	cpsid i								\n" /* Errata workaround. */
	"	msr basepri, r0						\n"
	"	dsb									\n"
	"   isb									\n"
	"	cpsie i								\n" /* Errata workaround. */
	"	bl vTaskSwitchContext				\n"
	"	mov r0, #0							\n"
	"	msr basepri, r0						\n"
	"	ldmia sp!, {r3}						\n"
	"										\n"
	"	ldr r1, [r3]						\n" /* The first item in pxCurrentTCB is the task top of stack. */
	"	ldr r0, [r1]						\n"
	"										\n"
	"	ldmia r0!, {r4-r11, r14}			\n" /* Pop the core registers. */
	"										\n"
	"	tst r14, #0x10						\n" /* Is the task using the FPU context?  If so, pop the high vfp registers too. */
	"	it eq								\n"
	"	vldmiaeq r0!, {s16-s31}				\n"
	"										\n"
	"	msr psp, r0							\n"
	"	isb									\n"
	"										\n"
	#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
		#if WORKAROUND_PMU_CM001 == 1
	"			push { r14 }				\n"
	"			pop { pc }					\n"
		#endif
	#endif
	"										\n"
	"	bx r14								\n"
	"										\n"
	"	.align 2							\n"
	"pxCurrentTCBConst: .word pxCurrentTCB	\n"
	::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
	);
}

I also tried it with 3 bit and the following settings:

configMAX_PRIORITIES ((unsignes portBASE_TYPE) 5 )
configPRIO_BITS 3
configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

but without any success.
I am using freertos 8.2.3 and I don’t know what to do.
here is my small application code:

void User_init_tasks(void)
{
	xTaskHandle xINITHandle;
    portBASE_TYPE retVal=0;
    
     //Start init Task
     retVal =  xTaskCreate( init_task,                        // Function
                         ( signed portCHAR * ) "INIT_Task",  // Name
                           256,            // Stack Size
                           NULL,           // Parameter
                           tskIDLE_PRIORITY,              // Prio
                           &xINITHandle ); // Handel
    
    /* Start the scheduler. */
    
    vTaskStartScheduler();
   
    /* Will only get here if there was insufficient memory to create the idle
    task. */
    return 0;
}


void init_task(void *pvParameters)
{
	(void) pvParameters;
	portBASE_TYPE OK = pdPASS;
	
	//Blinky Task
	OK = xTaskCreate(Blink, "Blinky",
					 TASK_LED_STACK_SIZE,
					 NULL,
					 TASK_LED_PRIORITY,
					 &System.taskhandles[LED_HANDLE]);
	
//	OK |= xTaskCreate(vStartEthernetTask, "ETHLAUNCH",
//					 configMINIMAL_STACK_SIZE,
//					 NULL,
//					 tskIDLE_PRIORITY,
//					 NULL);
	
//	OK |= xTaskCreate(CAN_TO_ETH_TASK, "CAN_TO_ETH",
//					 CAN_TO_ETH_TASK_STACK_SIZE,
//					 NULL,
//					 CAN_TO_ETH_TASK_PRIORITY,
//					 &System.taskhandles[CAN_TO_ETHER_HANDLE]);
	
	//if(OK != pdPASS)
	//set_SystemStatus(SYSTEM_ERROR, 2);
	
	vTaskDelete(xTaskGetCurrentTaskHandle());
}


//Blink Task alle 200ms
void Blink(void *pvParameters)
{
	portTickType xLastWakeTime;
	const portTickType xFrequency = LIFE_PULS_CYCLE_TIME_MS;
	xLastWakeTime = xTaskGetTickCount();
	
	for(;;)
	{
		ioport_toggle_pin_level(LED_ON);
		
		vTaskDelayUntil(&xLastWakeTime, xFrequency); //Pause
	}
}

User_init_tasks() I am calling from my main().

I am really looking forwars to your ansers.
Thank u very much.

rtel wrote on Thursday, April 13, 2017:

Although in the datasheet is said BASPRI priority bits are [7:4] (4
BITS!!!) the definition for configPRIO_BITS in CMSIS is 3. I do not
understand this.

Which document are you looking at? Page 73 of
http://www.atmel.com/Images/Atmel-11296-32-bit-Cortex-M7-Microcontroller-SAM-E70Q-SAM-E70N-SAM-E70J_Datasheet.pdf
seems to indicate 3 is the right number. It would not be the first time
that we have seen different numbers of priority bits quoted in different
places though.

In any case, it might be that the value is not used. That would be the
case if your header files define __NVIC_PRIO_BITS, which would take
presedence if you are using the FreeRTOSConfig.h file from the FreeRTOS
download, due to the following code:

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
   /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
     #define configPRIO_BITS  __NVIC_PRIO_BITS
#else
     #define configPRIO_BITS  3 /* 7 priority levels */
#endif


> vTaskStartScheduler()-->xTaskCreate(prvIdleTask,...)-->xTaskGenericCreate(...)-->taskYIELD_IF_USING_PREEMPTION()-->xPortPendSVHandler()

This sequence does not look right.  You should not jump to 
xPortPendSVHandler() at that point because interrupts will be disabled. 
Can you tell me what the value of uxCriticalNesting is when you call 
vTaskStartScheduler().  It is defined in 
FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c.