This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

HardFault with GPIOTE & SD

Hi!

I am getting a HardFault when I try to read a GATTs value inside a GPIOTE ISR handler.

I already tried setting the ISR priority to low as suggested in various posts.

Here is my code:

#include "app_settings.h"

#include "control.h"
#include "services.h"
#include "nrf_drv_gpiote.h"
#include "ble_srv_common.h"
#include "app_util_platform.h"

APP_TIMER_DEF(m_control_timer_id);

static void on_zx(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action){
    UNUSED_PARAMETER(pin);
    UNUSED_PARAMETER(action);
    //nrf_drv_gpiote_in_event_disable(ZX_PIN);

    ret_code_t err_code = 0;

    // This ISR is called when a ZX interrupt occurs
    // Start a timer in _level_ proportional ticks to allow dimming

    // Disable Triac immediately
    //nrf_drv_gpiote_out_set(TRIAC_PIN);

    // Get level value from the GATT DB
    ble_gatts_value_t gatts_value;
    gatts_value.offset = 0;
    err_code = sd_ble_gatts_value_get(m_ctl.conn_handle, m_ctl.ctl_level_handles.value_handle, &gatts_value);
    APP_ERROR_CHECK(err_code);
    float level = *((float*)gatts_value.p_value);

    // Check level boundaries
    if(level > 1){
        level = 1;
    }
    if(level < 0){
        level = 0.1;
    }
    //nrf_drv_gpiote_in_event_enable(ZX_PIN, true);

    // Calculate wait time and start timer
    // float T2 = 1.0 / 100;
    // uint32_t wait_ms = (uint32_t)(T2 * (1 - level) * 1000);
    // err_code = app_timer_start(m_control_timer_id, wait_ms, NULL);
    // APP_ERROR_CHECK(err_code);
}

// static void on_timer(void * p_context){
//     // Enable Triac
//     nrf_drv_gpiote_out_clear(TRIAC_PIN);
// }

void init_ctl(void){
    ret_code_t err_code;

    // Init GPIOTE if not yet initialized
    if(!nrf_drv_gpiote_is_init()){
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    }

    // Init timer for phase angle
    //err_code = app_timer_create(&m_control_timer_id, APP_TIMER_MODE_SINGLE_SHOT, on_timer);

    // Init pin for triac on
    nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);
    err_code = nrf_drv_gpiote_out_init(TRIAC_PIN, &out_config);
    APP_ERROR_CHECK(err_code);

    // Init pin for ZX ISR
    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
    in_config.pull = NRF_GPIO_PIN_PULLDOWN;

    err_code = nrf_drv_gpiote_in_init(ZX_PIN, &in_config, on_zx);
    APP_ERROR_CHECK(err_code);

    // Lower IRQ prio so SD does not get fucked
    NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_LOW);

    // Enable ISR on ZX rising edge
    nrf_drv_gpiote_in_event_enable(ZX_PIN, true);
}

What I would like to do is having the ISR on a pin rising edge which starts a timer. The timer ISR should then set another pin to high. I am not quite sure how to make sure the priorities are set properly as apparently the priorities 0-5 are reserved for the SD. Also I do not like having to lower the priority for those said interrupts I want as they are timing critical. So using the app scheduler or the likes wont work either (as suggested in a few posts).

Thanks for any help in advance!

Best regards

Noah

Parents
    1. Are you saying that your code above with GPIOTE irq priority APP_IRQ_PRIORITY_LOW doesn't work?
    2. Assuming that you are using nRF52 then the softdevice reserves priorities 0, 1, and 4. You are free to use the other levels for application interrupts.
    3. If latency is important to you I suggest that you check out the possibility of using PPI and GPIOTE channels, together with a timer. You can make a level change on an input start the timer, and when the timer reaches a certain value it will trigger a level change on a different output pin. By using PPI you can do all this without interrupts at all and completely independent of the CPU.
Reply
    1. Are you saying that your code above with GPIOTE irq priority APP_IRQ_PRIORITY_LOW doesn't work?
    2. Assuming that you are using nRF52 then the softdevice reserves priorities 0, 1, and 4. You are free to use the other levels for application interrupts.
    3. If latency is important to you I suggest that you check out the possibility of using PPI and GPIOTE channels, together with a timer. You can make a level change on an input start the timer, and when the timer reaches a certain value it will trigger a level change on a different output pin. By using PPI you can do all this without interrupts at all and completely independent of the CPU.
Children
No Data
Related