HardFault Handler on SIM3U167 (Cortex M3) when calling vTaskNotifyGiveFromISR

Hello everybody ๐Ÿ™‚ I’m developping a firmware for a SIM3U167 and I’m trying to implement FreeRTOS 8.2.0 on this one. To summary, my firmware uses the ADC of my ยตC and I want to notify a task when I am in the scan done’s interruption routine. This is my problem : when I want to increase the speed of my ADC, I go in an HardFault Handler when I want to call the function vTaskNotifyGiveFromISR in my interruption. When I go in the SARADC0scandone_handler over 1 kHz (approximately), it crashes. I don’t know if I have a problem with priorities, if I try to switch contexts to quickly for FreeRTOS or if it is an other problem. I use the IDE furnished by Silabs : Precision32 I have cut the code to show you only principal things (sorry I don’t know how to color C language) ~~~~~~ int main() { extern uint8_t start;
extern TaskHandle_t xTaskPotentiometers;

// Enter the default operating mode for this application (gModes.c)
enter_default_mode_from_reset();
NVIC_SetPriority(SARADC0_IRQn, 100);

xTaskCreate(vTaskPotentiometers, "pot", 200, NULL, 1, &xTaskPotentiometers);

// Initialisation
mySARADC0_init();

/* Start the scheduler running the tasks and co-routines just created. */
vTaskStartScheduler();

while(1);
// Loop forever...
} ~~~~~~ ~~~~~~ void SARADC0convcompletehandler(void) { SI32SARADCAclearsingleconversioncompleteinterrupt(SI32SARADC0); } void SARADC0scandonehandler(void) { uint8t k=0;
extern TaskHandle_t xTaskPotentiometers;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

SI32_SARADC_A_clear_single_conversion_complete_interrupt(SI32_SARADC_0);
SI32_SARADC_A_clear_scan_done_interrupt(SI32_SARADC_0);
SI32_SARADC_A_disable_autoscan(SI32_SARADC_0);
SI32_SARADC_A_enable_autoscan(SI32_SARADC_0);

for (k = 0; k < 8; k++)
{
    adc_read[k] = SI32_SARADC_A_read_data(SI32_SARADC_0);
}

vTaskNotifyGiveFromISR(xTaskPotentiometers, &xHigherPriorityTaskWoken);    <--------------BUG

portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} ~~~~~~ ~~~~~~ void vTaskPotentiometers(void *pvParameters) { extern SemaphoreHandle_t xMutexUsb;
uint32_t adc_output_old[8], adc_output[8];
uint32_t adc_output_old128[8], adc_output128[8];

uint32_t adc_value_send[8];
uint8_t adc_number_send[8];
extern uint32_t adc_read[8];

uint8_t first_conversion = 1;
uint8_t index_adc = 0;

SI32_TIMER_A_start_high_timer(SI32_TIMER_0);

for( ;; )
{
    ulTaskNotifyTake( pdTRUE,           /* Clear the notification value before exiting. */
            portMAX_DELAY );            /* Block indefinitely. */

    index_adc = 0;

    for (uint8_t i = 0; i < 8; i++)
    {
        if (first_conversion == 1)
        {
            adc_output_old[i] = 0;
            adc_output_old128[i] = 0;

            adc_output[i] = adc_read[i] >> 2;
            adc_output128[i] = (adc_output[i]*8388)>>16;

            if (adc_output128[i] >= 128)
            {
                adc_output128[i] = 127;
            }

            adc_number_send[index_adc] = i;
            adc_value_send[index_adc] = adc_output128[i];
            index_adc++;

            if (i == 7)
            {
                first_conversion = 0;
            }
        }
        else
        {
            adc_output_old[i] = adc_output[i];
            adc_output_old128[i] = adc_output128[i];

            adc_output[i] = (adc_read[i] >> 2) + (adc_output_old[i]*3/4);
            adc_output128[i] = (adc_output[i]*8388)>>16;

            if (adc_output128[i] >= 128)
            {
                adc_output128[i] = 127;
            }

            if (adc_output128[i] != adc_output_old128[i])
            {
                adc_number_send[index_adc] = i;
                adc_value_send[index_adc] = adc_output128[i];
                index_adc++;
            }
        }
    }

    if (index_adc != 0)
    {
        xSemaphoreTake(xMutexUsb, 0);
        while(index_adc > 0)
        {
            SI32_USBEP_A_write_fifo_u8(SI32_USB_0_EP1, 0x01);
            SI32_USBEP_A_write_fifo_u8(SI32_USB_0_EP1, adc_number_send[index_adc-1]);
            SI32_USBEP_A_write_fifo_u8(SI32_USB_0_EP1, (uint8_t) adc_value_send[index_adc-1]);
            index_adc--;
        }
        xSemaphoreGive(xMutexUsb);
        vTaskResume(xTaskSendUSBControls);
    }
    index_adc = 0;
}
} ~~~~~~ I also show you the FreeRTOSConfig.h ~~~~~~

define configUSE_PREEMPTION 1

define configUSEIDLEHOOK 0

define configUSETICKHOOK 0

define configCPUCLOCKHZ ( ( unsigned long ) 48000000 )

define configTICKRATEHZ ( ( TickType_t ) 1000 )

define configMINIMALSTACKSIZE ( ( unsigned short ) 70 )

define configTOTALHEAPSIZE ( ( size_t ) ( 7000 ) )

define configMAXTASKNAME_LEN ( 10 )

define configUSETRACEFACILITY 0

define configUSE16BIT_TICKS 0

define configIDLESHOULDYIELD 0

define configUSECOROUTINES 0

define configUSEPORTOPTIMISEDTASKSELECTION 1

define configMAX_PRIORITIES ( 5 )

define configMAXCOROUTINE_PRIORITIES ( 2 )

define configUSE_MUTEXES 1

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

define INCLUDE_vTaskPrioritySet 0

define INCLUDE_uxTaskPriorityGet 0

define INCLUDE_vTaskDelete 1

define INCLUDE_vTaskCleanUpResources 0

define INCLUDE_vTaskSuspend 1

define INCLUDE_vTaskDelayUntil 1

define INCLUDE_vTaskDelay 1

define INCLUDE_xTaskGetSchedulerState 1

define configKERNELINTERRUPTPRIORITY 255

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

define configMAXSYSCALLINTERRUPT_PRIORITY 95 /* equivalent to priority 5. */

endif /* FREERTOSCONFIGH */

~~~~~~ I am a new user of FreeRTOS and new on the forum, if information are missing, don’t hesitate to ask me. Thank you in advance for your help ๐Ÿ™‚ (sorry if there are mistakes in my English, I’m French ^^) Thomas

HardFault Handler on SIM3U167 (Cortex M3) when calling vTaskNotifyGiveFromISR

Bonjours Thomas, Salut mec, merci bien pour ton message ๐Ÿ™‚ There is one thing that surprises me, the tick-count of zero that you use here: ~~~~~ xSemaphoreTake(xMutexUsb, 0); while(indexadc > 0) { … indexadc–; } xSemaphoreGive(xMutexUsb); vTaskResume(xTaskSendUSBControls); ~~~~~ At least I would expect code like: ~~~~~ if( xSemaphoreTake(xMutexUsb, 0) != pdFALSE ) { while(indexadc > 0) { … indexadc–; } xSemaphoreGive(xMutexUsb); } else { /* failed to take the semaphore. */ } ~~~~~ I can not understand why the call vTaskNotifyGiveFromISR() would lead to an exception. ( I don’t like HardFault or exception handlers at all. Debuggers can not show from where they’re called because the stack pointer is different. You must inspect a stack that is stored in some register ) Is it exactly above 1 KHz that things go wrong? Or does the probability increase along with the frequency? My guess is that something goes wrong at a higher frequency because your xMutexUsb can not be taken. Your USB task is still busy doing thing. Could that be? Regards, Hein

HardFault Handler on SIM3U167 (Cortex M3) when calling vTaskNotifyGiveFromISR

Agree with Hein’s comment regarding the semaphore. You would need to either: 1) Use an infinite block time, so xSemaphoreTake() only returns when it has the semaphore, so you don’t need to check the function’s return value. Note infinite block times are used all over the place in example code, but are generally not a good idea in production code as it does not allow for error recovery should the semaphore never arrive. 2) Use a finite block time, then check the return value of xSemaphoreTake() to determine if the semaphore was obtained or not – as per Hein’s code. ….however, I am suspicious of the line NVICSetPriority(SARADC0IRQn, 100); If this is the CMSIS function the second parameter looks wrong, as it will expect an unshifted value. This is a common err on Cortex-M (in fact, on all Cortex) where the interrupt priorities are very confusing. This page tries to explain it, but may also confuse ;o) http://www.freertos.org/RTOS-Cortex-M3-M4.html Do you have configASSERT() defined? I would strongly recommend it as if it is defined then the interrupt priority problem would get found immediately. http://www.freertos.org/a00110.html#configASSERT Regarding debugging faults. Some IDE’s will do that for you. For example, Atollic’s TrueStudio. I don’t know about Sil Labs IDE though. This page may help if not: http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html Regards.

HardFault Handler on SIM3U167 (Cortex M3) when calling vTaskNotifyGiveFromISR

Hi ๐Ÿ™‚ Thank you for your very quick answers. You’re right, I had a problem with the priority. If I have well understood, to use ISR functions, the interrupt priority must be higher than configMAXSYSCALLINTERRUPTPRIORITY. In my case, configMAXSYSCALLINTERRUPTPRIORITY = 95, so for my Cortex-M it is a priority of 5 (there are 4 priority bits), so, the interrupt priority must be lower than 5 (because lower value is higher priority on the Cortex-M) and the function NVIC_SetPriority expects the unshifted value as you said. I wanted to define configASSERT(), but the line #define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( FILE, LINE ) returns this error : “(” may not appear in macro parameter list I tried this one : #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( FILE, LINE ) but there are 2 errors: undefined reference to configASSERT' and undefined reference tovAssertCalled’ in the file queue.c Have you an idea to resolve this error? About the Mutex, I will follow your recommandations and add a finite block time. Regards, Thomas

HardFault Handler on SIM3U167 (Cortex M3) when calling vTaskNotifyGiveFromISR

vAssertCalled() is a function you would have to provide yourself, so you can implement it to do what you want. You could alternative just switch interrupts off and sit in a loop without calling a function:
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); 
for( ;; ); }
Regards.