Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

ATSAM4S FreeRTOS Interrupt handling

Posted by m2b821 on October 30, 2017

Hello, I have a problem with my code. I run a several tasks on FreeRTOS (v7.3, supplied from Atmel ASF) and added a set of new tasks for ADC conversion. I tested the ADC part before without FreeRTOS and it worked fine. But after calling NVIC_EnableIRQ(ADC_IRQn);, FreeRTOS scheduling ends (no task is called again) while the ADC interrupts remain. I have the standard configuration from Atmel, which is using 4 bits for the priorities. I tried to call also moving the call to NVIC_EnableIRQ(ADC_IRQn); before creating any tasks, but this resulted in the same behaviour. Can someone please explain me why, as I am pretty sure that NVICEnableIRQ causes the crash, this stops the FreeRTOS kernel. I have already read http://www.freertos.org/RTOS-Cortex-M3-M4.html and used configASSERT on all semaphores and tasks related to this issue. The ADC interrupts simply loads the result of from two ADC channels and stores them in a local variable. Afterwards it calls the corresponding task through releasing a binary semaphore. The ADC is operating hardware controlled using timer 0 with 10Hz. I understand FreeRTOS this way, the timer 0 and 1 are not consumed by it (it uses sysclk, correct?). As I have other components which will be integrated in my main application with FreeRTOS, I fear that similar errors might occur, as I2C and USB CDC also use hardware interrupts with NVIC_EnableIRQ(...). The semaphore is all 10Hz released, but no task is ever called after startup (where the ADC task is once called): ~~~ long prio = pdFALSE; xSemaphoreGiveFromISR(*(getSemaphoreHandlerADCDriver()), &prio); portENDSWITCHING_ISR(prio); ~~~ Thank you!


ATSAM4S FreeRTOS Interrupt handling

Posted by rtel on October 30, 2017

Hello, I have a problem with my code. I run a several tasks on FreeRTOS (v7.3, supplied from Atmel ASF)

Grr, so old.

and added a set of new tasks for ADC conversion. I tested the ADC part before without FreeRTOS and it worked fine. But after calling |NVICEnableIRQ(ADCIRQn);|, FreeRTOS scheduling ends (no task is called again) while the ADC interrupts remain.

Do you mean no tasks run because 100% of time is spend processing the interrupt?

I have the standard configuration from Atmel, which is using 4 bits for the priorities. I tried to call also moving the call to |NVICEnableIRQ(ADCIRQn);| before creating any tasks, but this resulted in the same behaviour. Can someone please explain me why, as I am pretty sure that NVIC_EnableIRQ causes the crash, this stops the FreeRTOS kernel. I have already read http://www.freertos.org/RTOS-Cortex-M3-M4.html and used configASSERT on all semaphores and tasks related to this issue.

Not sure how much help configASSERT() will be in V7.3. Try using the head revision from SVN, which has many more assert points specifically to catch Cortex-M mis-configurations.

The ADC interrupts simply loads the result of from two ADC channels and stores them in a local variable. Afterwards it calls the corresponding task through releasing a binary semaphore. The ADC is operating hardware controlled using timer 0 with 10Hz.

All sounds fine.

I understand FreeRTOS this way, the timer 0 and 1 are not consumed by it (it uses sysclk, correct?).

Correct.

As I have other components which will be integrated in my main application with FreeRTOS, I fear that similar errors might occur, as I2C and USB CDC also use hardware interrupts with |NVIC_EnableIRQ(...)|. The semaphore is all 10Hz released, but no task is ever called after startup (where the ADC task is once called):

I need to understand exactly what that means. If you call FreeRTOS API functions before the scheduler has started (creating tasks, etc.) then interrupt below the max syscall interrupt will be left disabled - deliberately so because you don't want the interrupt's service routines to try using FreeRTOS functions before the scheduler has started. Interrupts are then fully enabled when the first task starts. If you call API functions, then enable the interrupt but don't start the scheduler, and interrupts are firing at that time, then it sounds like the priority is wrong - and if the ISR is trying to give a semaphore before the scheduler has started then even worst (that is exactly the reason interrupts are left disabled at that time).

FreeRTOS V7 is so old though that I'm not going to remember exactly what it does in these regards.


ATSAM4S FreeRTOS Interrupt handling

Posted by m2b821 on October 31, 2017

Hello, I have updated to kernel version 9.0 (why is the version in Atmel Studio ASF so old?). I also changed all old type names to the new ones. In compliance with your last explanation, I checked that the ADC unit is initialize and the ADC interrupt enable with the first call of adc handling task which also creates another task to take the data from the ADC. This second task is blocked using a binary semaphore as already said. When I am now debugging, the ADC interrupt is only called once but afterwards, the debugger stops always in portmarco.h at portFORCEINLINE static void vPortRaiseBASEPRI(void). The code of this function is below. I found that this occurs when calling xSemaphoreGiveFromISR(...). So I checked in the debugger that the semaphore is initialized (and also with configASSERT before calling xSemaphoreGiveFromISR). And it is initialized, the debugger reports SemaphoreHandlet with value 0x200031e0 . So my question is now why this now working and why is this even blocking the hardware timer triggered AD conversion? I suspect that the next AD conversion only starts if the previous interrupt handler has been executed, which is prevented by this vPortRaiseBASEPRI. ~~~ portFORCEINLINE static void vPortRaiseBASEPRI( void ) { uint32t ulNewBASEPRI;

__asm volatile
(
	"	mov %0, %1												\n"	\
	"	msr basepri, %0											\n" \
	"	isb														\n" \
	"	dsb														\n" \
	:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);

} ~~~ The blocked ADC task is also called once after beginning (and blocked successfully by the semaphore). What I find interesting is, that I cannot break at the call to NVIC_EnableIRQ in the debugger, only in the line before or after. When I step through, it is also not possible to stop at this line. Is this a normal behaviour (I said the optimiziation to debugging level (-Og).


ATSAM4S FreeRTOS Interrupt handling

Posted by m2b821 on November 1, 2017

Hello, my answer is below (my mistake not to answer directly). I followed your guidelines and it seems that I am now closer to the source of the problem. Could you please tell me what vPoirtRaiseBASEPRI does? I have the semaphore fully initialized and I have a pointer to it, which I use (after dereferencing).


ATSAM4S FreeRTOS Interrupt handling

Posted by rtel on November 1, 2017

Where/why is NVIC_EnableIRQ being called. Can you show the call?

what vPoirtRaiseBASEPRI does

BASEPRI is a register in the Cortex-M hardware - you can read about it in the hardware manuals from ARM (not in the SAM4 manuals). It sets the interrupt priority mask level. The function in question raises the mask to whatever you have cnofigMAXSYSCALLINTERRUPT_PRIORITY set to, so only interrupts above that priority will execute until BASEPRI is set back to 0.


ATSAM4S FreeRTOS Interrupt handling

Posted by m2b821 on November 1, 2017

NVICEnableIRQ is called to enable the ADCIRQn interrupt, the following code is called in the ADC task after scheduling has started. Without calling NVICEnableIRQ, I do not get any ADC interrupts. ~~~ //! Init ADC unit, using Timer0 with channel 1 void adccontrolinit() { // Configure timer, we want to have 10Hz sysclkenableperipheralclock(IDTC1); uint32t uldiv = 0; uint32t ultcclks = 0; uint32t ulsysclk = sysclkgetcpuhz(); tcfindmckdivisor(10, ulsysclk, &uldiv, &ultcclks, ulsysclk); // Init timer clock 0 channel 1 with the found timings and set up counter which resets/clears on reaching the target tcinit(TC0, 1, ultcclks|TCCMRWAVE|TCCMRWAVSELUPRC|TCCMRACPACLEAR|TCCMRACPCSET); tcwriterc(TC0, 1, (ulsysclk / uldiv)); tcwritera(TC0, 1, (ulsysclk / uldiv) / 2); sysclkenableperipheralclock(IDADC); adcinit(ADC, sysclkgetcpuhz(), 5000000UL, ADCMRSTARTUPSUT512); adcconfiguretiming(ADC, 0, ADCMRSETTLINGAST9, 2); adcsetresolution(ADC, ADCMRLOWRESBITS12); adcenabletag(ADC); NVICEnableIRQ(ADCIRQn); } ~~~


ATSAM4S FreeRTOS Interrupt handling

Posted by m2b821 on November 1, 2017

Hello, I tried a different use cases, which uses the USB controller. Again, I got stuck in vPortRaiseBASEPRI. I think it might be a problem with my configuration, which I imported from the reference project. I would appreciate any idea to fix this, because I cannot use any of the semaphore (I only use them in interrupts), should xSemaphoreGiveFromISR not be working in case of functions called in my interrupt routine? Note: Both of my used tasks where running succesfully, but blocked through the semaphores. My FreeRTOS config: ~~~

include

extern uint32_t SystemCoreClock;

define configUSE_PREEMPTION 1
define configUSEPORTOPTIMISEDTASKSELECTION 1
define configUSEIDLEHOOK 0
define configCPUCLOCKHZ ( SystemCoreClock )
define configTICKRATEHZ ( ( TickType_t ) 1000 )
define configMAX_PRIORITIES ( 5 )
define configMINIMALSTACKSIZE ( ( unsigned short ) 130 )
define configTOTALHEAPSIZE ( ( size_t ) ( 40960 ) )
define configMAXTASKNAME_LEN ( 50 )
define configUSETRACEFACILITY 0
define configUSE16BIT_TICKS 0
define configIDLESHOULDYIELD 1
define configUSE_MUTEXES 1
define configQUEUEREGISTRYSIZE 20
define configUSERECURSIVEMUTEXES 1
define configUSEAPPLICATIONTASK_TAG 0
define configUSECOUNTINGSEMAPHORES 1
define configUSEQUEUESETS 1
define configGENERATERUNTIME_STATS 0
define configUSEAPPLICATIONTICK_HOOK 0
define configUSETICKHOOK 0
define configCHECKFORSTACK_OVERFLOW 0
define configUSEMALLOCFAILED_HOOK 0

/* Co-routine definitions. */

define configUSECOROUTINES 0
define configMAXCOROUTINE_PRIORITIES ( 2 )

/* Software timer definitions. */

define configUSE_TIMERS 1
define configTIMERTASKPRIORITY ( 2 )
define configTIMERQUEUELENGTH 5
define configTIMERTASKSTACKDEPTH ( configMINIMALSTACK_SIZE * 2 )

/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */

define INCLUDE_vTaskPrioritySet 1
define INCLUDE_uxTaskPriorityGet 1
define INCLUDE_vTaskDelete 1
define INCLUDE_vTaskCleanUpResources 1
define INCLUDE_vTaskSuspend 1
define INCLUDE_vTaskDelayUntil 1
define INCLUDE_vTaskDelay 1
define INCLUDE_eTaskGetState 1
define INCLUDE_xTimerPendFunctionCall 1

/* Cortex-M specific definitions. */

ifdef _NVICPRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS       		__NVIC_PRIO_BITS
else
#define configPRIO_BITS       		4        /* 15 priority levels */
endif

/* The lowest interrupt priority that can be used in a call to a "set priority" function. */

define configLIBRARYLOWESTINTERRUPT_PRIORITY 0x0f
define configENABLEBACKWARDCOMPATIBILITY 0

/* 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. */

define configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 10

/* Interrupt priorities used by the kernel port layer itself. These are generic to all Cortex-M ports, and do not rely on any particular library functions. */

define configKERNELINTERRUPTPRIORITY ( configLIBRARYLOWESTINTERRUPTPRIORITY << (8 - configPRIOBITS) )

/* !!!! configMAXSYSCALLINTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */

define configMAXSYSCALLINTERRUPTPRIORITY ( configLIBRARYMAXSYSCALLINTERRUPTPRIORITY << (8 - configPRIOBITS) )

/* Normal assert() semantics without relying on the provision of an assert.h header file. */

define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names. */

define vPortSVCHandler SVC_Handler
define xPortPendSVHandler PendSV_Handler
define xPortSysTickHandler SysTick_Handler
endif /* FREERTOSCONFIGH */

~~~


ATSAM4S FreeRTOS Interrupt handling

Posted by m2b821 on November 3, 2017

Hi, I have now set the interrupt priority for the ADC interrupt to be 13, but the problem is still the same. I am not sure what the priority was before. Interesting is that the first time, xSemaphoreGiveFromISR is executed, then nothing happens and in the next interupt, configASSERT fails. Is configASSERT allowed in interrupts, I think it is? The result is, that my application is stuck in startupsam4s.c: DummyHandler. Maybe my interrupts were deactived by the vPortRaiseBASEPRI?


ATSAM4S FreeRTOS Interrupt handling

Posted by rtel on November 3, 2017

If the code is in the dummy_handler routine then an interrupt or exception has occurred for which a specific handler was not installed. I'm going to guess it is a hardfault handler. Have you installed a handler for faults? It is always best to have individual handlers for all fault exceptions so you know right away when one gets called. Go to the 'my application does not run, what could be wrong' page on the FreeRTOS.org site and follow your nose to find a page that describes how to debug hard faults, and how to find out which fault or interrupt actually executed.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS