Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

hard fault when taking semaphore in FreeRTOS

Hi,

I'm trying to use a GPIO interrupt and a semaphore to trigger a free rtos taskm but whenever I run xSemaphoreTake i get a hard fault error.

// Semaphore to signal interrupt pin change
SemaphoreHandle_t m_ppg_semaphore;

static void ppg_test_task(void *pvParameter){
    UNUSED_PARAMETER(pvParameter);

    m_ppg_semaphore = xSemaphoreCreateBinary();
    ASSERT(NULL != m_ppg_semaphore);

    gpio_init();

    //volatile enum ppgInterupt ppgState = notReady;
    // Read the interrupt registers to clear them
    //uint8_t buffer;
    //bool stay = false;
    while (true) {
        bool temp = xSemaphoreTake(m_ppg_semaphore, portMAX_DELAY);

        // Turn an LED on to signify the start of data reading
        bsp_board_led_invert(BSP_BOARD_LED_3);
        }
}

void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
    BaseType_t yield_req = pdFALSE;

    /* The returned value may be safely ignored, if error is returned it only means that
    * the semaphore is already given (raised). */
    UNUSED_VARIABLE(xSemaphoreGiveFromISR(m_ppg_semaphore, &yield_req));
    portYIELD_FROM_ISR(yield_req);
}
/**
 * @brief Function for configuring: PIN_IN pin for input, PIN_OUT pin for output,
 * and configures GPIOTE to give an interrupt on pin change.
 */
static void gpio_init(void) {
    ret_code_t err_code;

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(INT_IN, &in_config, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(INT_IN, true);

    NRF_LOG_INFO("GPIO Configured");
}

Parents
  • Hi

    This is an issue where a corner case could make the FreeRTOS tick go ahead of an RTC tick. Please try replacing the SDK\external\freertos\portable\CMSIS\nrf52\port_cmsis_systick.c with this one.

    /*
        FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.
        All rights reserved
    
        VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
    
        This file is part of the FreeRTOS distribution.
    
        FreeRTOS is free software; you can redistribute it and/or modify it under
        the terms of the GNU General Public License (version 2) as published by the
        Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
    
        ***************************************************************************
        >>!   NOTE: The modification to the GPL is included to allow you to     !<<
        >>!   distribute a combined work that includes FreeRTOS without being   !<<
        >>!   obliged to provide the source code for proprietary components     !<<
        >>!   outside of the FreeRTOS kernel.                                   !<<
        ***************************************************************************
    
        FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
        WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
        FOR A PARTICULAR PURPOSE.  Full license text is available on the following
        link: http://www.freertos.org/a00114.html
    
        ***************************************************************************
         *                                                                       *
         *    FreeRTOS provides completely free yet professionally developed,    *
         *    robust, strictly quality controlled, supported, and cross          *
         *    platform software that is more than just the market leader, it     *
         *    is the industry's de facto standard.                               *
         *                                                                       *
         *    Help yourself get started quickly while simultaneously helping     *
         *    to support the FreeRTOS project by purchasing a FreeRTOS           *
         *    tutorial book, reference manual, or both:                          *
         *    http://www.FreeRTOS.org/Documentation                              *
         *                                                                       *
        ***************************************************************************
    
        http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
        the FAQ page "My application does not run, what could be wrong?".  Have you
        defined configASSERT()?
    
        http://www.FreeRTOS.org/support - In return for receiving this top quality
        embedded software for free we request you assist our global community by
        participating in the support forum.
    
        http://www.FreeRTOS.org/training - Investing in training allows your team to
        be as productive as possible as early as possible.  Now you can receive
        FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
        Ltd, and the world's leading authority on the world's leading RTOS.
    
        http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
        including FreeRTOS+Trace - an indispensable productivity tool, a DOS
        compatible FAT file system, and our tiny thread aware UDP/IP stack.
    
        http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
        Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
    
        http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
        Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
        licenses offer ticketed support, indemnification and commercial middleware.
    
        http://www.SafeRTOS.com - High Integrity Systems also provide a safety
        engineered and independently SIL3 certified version for use in safety and
        mission critical applications that require provable dependability.
    
        1 tab == 4 spaces!
    */
    
    /* Scheduler includes. */
    #include "FreeRTOS.h"
    #include "task.h"
    #include "app_util.h"
    #include "nrf_log.h"
    
    #ifdef SOFTDEVICE_PRESENT
    #include "nrf_soc.h"
    #include "softdevice_handler.h"
    #include "app_error.h"
    #include "app_util_platform.h"
    #endif
    
    /*-----------------------------------------------------------
     * Implementation of functions defined in portable.h for the ARM CM4F port.
     * CMSIS compatible layer to menage SysTick ticking source.
     *----------------------------------------------------------*/
    
    #if configTICK_SOURCE == FREERTOS_USE_SYSTICK
    
    
    #ifndef configSYSTICK_CLOCK_HZ
        #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
        /* Ensure the SysTick is clocked at the same frequency as the core. */
        #define portNVIC_SYSTICK_CLK_BIT    ( SysTick_CTRL_CLKSOURCE_Msk )
    #else
        /* The way the SysTick is clocked is not modified in case it is not the same
        as the core. */
        #define portNVIC_SYSTICK_CLK_BIT    ( 0 )
    #endif
    
    
    #if configUSE_TICKLESS_IDLE == 1
        #error SysTick port for RF52 does not support tickless idle. Use RTC mode instead.
    #endif /* configUSE_TICKLESS_IDLE */
    
    /*-----------------------------------------------------------*/
    
    void xPortSysTickHandler( void )
    {
        /* The SysTick runs at the lowest interrupt priority, so when this interrupt
        executes all interrupts must be unmasked.  There is therefore no need to
        save and then restore the interrupt mask value as its value is already
        known. */
        ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
        {
            /* Increment the RTOS tick. */
            if ( xTaskIncrementTick() != pdFALSE )
            {
                /* A context switch is required.  Context switching is performed in
                the PendSV interrupt.  Pend the PendSV interrupt. */
                SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
                __SEV();
            }
        }
        portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
    }
    
    /*-----------------------------------------------------------*/
    
    /*
     * Setup the systick timer to generate the tick interrupts at the required
     * frequency.
     */
    void vPortSetupTimerInterrupt( void )
    {
        /* Set interrupt priority */
        NVIC_SetPriority(SysTick_IRQn, configKERNEL_INTERRUPT_PRIORITY);
        /* Configure SysTick to interrupt at the requested rate. */
        SysTick->LOAD = ROUNDED_DIV(configSYSTICK_CLOCK_HZ, configTICK_RATE_HZ) - 1UL;
        SysTick->CTRL = ( portNVIC_SYSTICK_CLK_BIT | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk );
    }
    
    /*-----------------------------------------------------------*/
    
    #elif configTICK_SOURCE == FREERTOS_USE_RTC
    
    #if configUSE_16_BIT_TICKS == 1
    #error This port does not support 16 bit ticks.
    #endif
    
    #include "nrf_rtc.h"
    #include "nrf_drv_clock.h"
    
    /*-----------------------------------------------------------*/
    
    void xPortSysTickHandler( void )
    {
    #if configUSE_TICKLESS_IDLE == 1
        nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
    #endif
    
        BaseType_t switch_req = pdFALSE;
        uint32_t isrstate = portSET_INTERRUPT_MASK_FROM_ISR();
    
        uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
        nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
    
        if (configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG == 0)
        {
            /* check FreeRTOSConfig.h file for more details on configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG */
            TickType_t diff;
            diff = (systick_counter - xTaskGetTickCount()) & portNRF_RTC_MAXTICKS;
    
            /* At most 1 step if scheduler is suspended - the xTaskIncrementTick
             * would return the tick state from the moment when suspend function was called. */
            if ((diff > 1) && (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING))
            {
                diff = 1;
            }
            while ((diff--) > 0)
            {
                switch_req |= xTaskIncrementTick();
            }
        }
        else
        {
            switch_req = xTaskIncrementTick();
        }
    
        /* Increment the RTOS tick as usual which checks if there is a need for rescheduling */
        if ( switch_req != pdFALSE )
        {
            /* A context switch is required.  Context switching is performed in
            the PendSV interrupt.  Pend the PendSV interrupt. */
            SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
            __SEV();
        }
    
        portCLEAR_INTERRUPT_MASK_FROM_ISR( isrstate );
    }
    
    /*
     * Setup the RTC time to generate the tick interrupts at the required
     * frequency.
     */
    void vPortSetupTimerInterrupt( void )
    {
        /* Request LF clock */
        nrf_drv_clock_lfclk_request(NULL);
    
        /* Configure SysTick to interrupt at the requested rate. */
        nrf_rtc_prescaler_set(portNRF_RTC_REG, portNRF_RTC_PRESCALER);
        nrf_rtc_int_enable   (portNRF_RTC_REG, RTC_INTENSET_TICK_Msk);
        nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_CLEAR);
        nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_START);
        nrf_rtc_event_enable(portNRF_RTC_REG, RTC_EVTEN_OVRFLW_Msk);
    
        NVIC_SetPriority(portNRF_RTC_IRQn, configKERNEL_INTERRUPT_PRIORITY);
        NVIC_EnableIRQ(portNRF_RTC_IRQn);
    }
    
    #if configUSE_TICKLESS_IDLE == 1
    
    void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
    {
        /*
         * Implementation note:
         *
         * To help debugging the option configUSE_TICKLESS_IDLE_SIMPLE_DEBUG was presented.
         * This option would make sure that even if program execution was stopped inside
         * this function no more than expected number of ticks would be skipped.
         *
         * Normally RTC works all the time even if firmware execution was stopped
         * and that may lead to skipping too much of ticks.
         */
        TickType_t enterTime;
    
        /* Make sure the SysTick reload value does not overflow the counter. */
        if ( xExpectedIdleTime > portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
        {
            xExpectedIdleTime = portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP;
        }
        /* Block all the interrupts globally */
    #ifdef SOFTDEVICE_PRESENT
        do{
            uint8_t dummy = 0;
            uint32_t err_code = sd_nvic_critical_region_enter(&dummy);
            APP_ERROR_CHECK(err_code);
        }while (0);
    #else
        __disable_irq();
    #endif
    
        enterTime = nrf_rtc_counter_get(portNRF_RTC_REG);
    
        if ( eTaskConfirmSleepModeStatus() != eAbortSleep )
        {
            TickType_t xModifiableIdleTime;
            TickType_t wakeupTime = (enterTime + xExpectedIdleTime) & portNRF_RTC_MAXTICKS;
    
            /* Stop tick events */
            nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
    
            /* Configure CTC interrupt */
            nrf_rtc_cc_set(portNRF_RTC_REG, 0, wakeupTime);
            nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
            nrf_rtc_int_enable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
    
            __DSB();
    
            /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
             * set its parameter to 0 to indicate that its implementation contains
             * its own wait for interrupt or wait for event instruction, and so wfi
             * should not be executed again.  However, the original expected idle
             * time variable must remain unmodified, so a copy is taken. */
            xModifiableIdleTime = xExpectedIdleTime;
            configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
            if ( xModifiableIdleTime > 0 )
            {
    #ifdef SOFTDEVICE_PRESENT
                if (softdevice_handler_is_enabled())
                {
                    uint32_t err_code = sd_app_evt_wait();
                    APP_ERROR_CHECK(err_code);
                }
                else
    #endif
                {
                    /* No SD -  we would just block interrupts globally.
                    * BASEPRI cannot be used for that because it would prevent WFE from wake up.
                    */
                    do{
                        __WFE();
                    } while (0 == (NVIC->ISPR[0] | NVIC->ISPR[1]));
                }
            }
            configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
    
            nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
            nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
    
            /* Correct the system ticks */
            {
                TickType_t diff;
                TickType_t exitTime;
    
                nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
                nrf_rtc_int_enable (portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
    
                exitTime = nrf_rtc_counter_get(portNRF_RTC_REG);
                diff =  (exitTime - enterTime) & portNRF_RTC_MAXTICKS;
    
                /* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
                NVIC_ClearPendingIRQ(portNRF_RTC_IRQn);
    
                if ((configUSE_TICKLESS_IDLE_SIMPLE_DEBUG) && (diff > xExpectedIdleTime))
                {
                    diff = xExpectedIdleTime;
                }
    
                if (diff > 0)
                {
                    vTaskStepTick(diff);
                }
            }
        }
    #ifdef SOFTDEVICE_PRESENT
        uint32_t err_code = sd_nvic_critical_region_exit(0);
        APP_ERROR_CHECK(err_code);
    #else
        __enable_irq();
    #endif
    }
    
    #endif // configUSE_TICKLESS_IDLE
    
    #else // configTICK_SOURCE
        #error  Unsupported configTICK_SOURCE value
    #endif // configTICK_SOURCE == FREERTOS_USE_SYSTICK
    

    Best regards,

    Simon

  • Hi, i've replaced this as requested but the error still occurs

Reply Children
No Data
Related