I have configASSERT enabled, stack checking enabled, calling vPortValidateInterruptPriority from all interrupts to verify priorities, and only calling from ISR API functions inside interrupts. However, intermittent faults continue to exist, mainly while in idle task it appears. I am using the SAM4L tickles port, IAR compiler, and the ATMEL ASF.
Looking at the FAQ:
The application I created compiles, but does not run – it runs for a while…
Stacks – overflow detection is on, calls to uxTaskGetStackHighWaterMark() show over 1000 bytes of stack available to all stacks including cstack
I added a simple task to a demo, and now the demo crashes! – few thousands bytes of heap left after allocating all stacks
Using API functions within interrupts – not calling non ISR API from interrupt doing…
The RTOS scheduler crashes when attempting to start the first task – getting past this point
The interrupt enable flag gets set incorrectly – hmmm. See below.
My application crashes before the RTOS scheduler is even started – I may be allowing posting to queues prior to RTOS starting…
Suspending the RTOS scheduler (calling vTaskSuspendAll()) causes me problems – my application never suspends the scheduler.
I have created a new application - but it will not compile – my application compiles
I get stuck on the line that starts – not having this problem
I don’t believe my application disables interrupts, however, I am using the ASF which does. There are so many interrupt disabling functions, it is unclear to me what I can and cannot be using. Should I be changing the Atmel ASF to replace the interrupt disabling with portENTER_CRITICAL?
cpu_irq_disable/ Disable_global_interrupt —same as Disable_global_interrupt / used by ASF and WDT
taskENTER_CRITICAL – used in freeRTOS and SAM4L_low_power_tick_management
__disable_interrupt – used by port.c
__disable_irq- used by ASF (interrupt_sam_nvic)
portDISABLE_INTERRUPTS –used by freertos
vPortEnterCritical / portENTER_CRITICAL – used by port.c
portDISABLE_INTERRUPTS / ulPortSetInterruptMask – used by port.c and FreeRTOS
Does the issue occur when configUSE_TICKLESS_IDLE is set to 0?
Regarding the interrupt enabling/disabling:
FreeRTOS never completely disables interrupts - its critical regions are implemented by setting the BASEPRI register to mask a subset of interrupt priorities, rather than setting the i bit in the CPSR to globally disable interrupts. The only way you should disable or enable interrupts yourself is by calling taskENTER_CRITICAL and taskEXIT_CRITICAL if in a task, or portSET_INTERRUPT_MASK_FROM_ISR and portCLEAR_INTERRUPT_MASK_FROM_ISR if in an interrupt (the latter two there are actually intended for internal use, and you will see them being used in xQueueGenericSendFromISR() in queue.c, but there is nothing to stop you using them yourself). The big exception to this is when implementing the ‘suppress ticks and sleep’ function - where an global disable must be used for the reasons explained in the source code comments - that is kernel code rather than user code though.
I believe the ASF on the other hand effects critical sections by globally disabling interrupts using the i bit in the CPSR. So provided it always enables it again there should be no conflict between its critical sections and FreeRTOS’s.
Concerning the interrupts - it looks like there are ~14 different disable interrupt functions – some work by globally disabling interrupts, while others work by setting BASEPRI as you said.
//works by setting basepri, no nesting support - ok for ISR
portSET_INTERRUPT_MASK_FROM_ISR/taskDISABLE_INTERRUPTS/portDISABLE_INTERRUPTS/ulPortSetInterruptMask – used in freeRTOS and SAM4L_low_power_tick_management
//works by setting basepri, with nesting support - ok for tasks
taskENTER_CRITICAL/portENTER_CRITICAL/portENTER_CRITICAL/vPortEnterCritical – used in freeRTOS and SAM4L_low_power_tick_management
//global disable with DMB with nesting depth
cpu_irq_enter_critical – not used
//global disable - returns flags
cpu_irq_save – used by ASF and SAM4L_low_power_tick_managment
//global disable with DMB - is DMB needed?
cpu_irq_disable/Disable_global_interrupt — used by ASF and WDT
//global disable without DMB - is DMB needed?
__disable_irq/__disable_interrupt – used by port.c
Should the port.c usage of a global disable without DMB be changed to a call with DBM?
Something else we did was decrease the clock speed from max (48 MHz) and there may be a correlation between slowing down the clock rate and seeing less hard faults. There is a really sketchy remark in the atmel asf:
// These defines for homogeneity with other SAM header files. #define CHIP_FREQ_FWS_0 (18000000UL) /< \brief Maximum operating frequency when FWS is 0 */ #define CHIP_FREQ_FWS_1 (36000000UL) /< \brief Maximum operating frequency when FWS is 1 */
// WARNING NOTE: these are preliminary values. #define CHIP_FREQ_FLASH_HSEN_FWS_0 (18000000UL) /< \brief Maximum operating frequency when FWS is 0 and the FLASH HS mode is enabled */ #define CHIP_FREQ_FLASH_HSEN_FWS_1 (36000000UL) /< \brief Maximum operating frequency when FWS is 1 and the FLASH HS mode is enabled */