I have an application built on the 52840 which is using a software interrupt triggered by the event generator unit. Occasionally my SWI function is being passed a zero for the flags value, despite the EGU being triggered by one of the task addresses.
More specifically, I have 4 timers each triggering GPIOTE tasks on 4 compare events via 16 PPI channels. For each timer, on one of the compare events, I have the PPI fork task set to an EGU trigger corresponding to the timer (all on EGU0, since they all call the same function). The SWI has a dedicated IRQ priority.
Everything works great except for the occasional hard fault if I don't explicitly check for the flags value being non-zero. My timers are running at 16MHz, but the SWI is only triggered every few milliseconds on each channel. I'm wondering if maybe IRQ collisions from the different EGU triggers are causing the flags value to somehow get 'lost'.
This is the setup code:
static nrfx_swi_t swi; static nrfx_gpiote_out_config_t gpiote_config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); static void gate_init(void) { nrfx_gpiote_init(); uint32_t pin; uint32_t task_addr; uint32_t evt_addr; nrf_ppi_channel_t ppi_channel; #define SET_GATE_PPI \ APP_ERROR_CHECK(nrfx_ppi_channel_alloc(&ppi_channel)); \ APP_ERROR_CHECK(nrfx_ppi_channel_assign(ppi_channel, evt_addr, task_addr)); \ APP_ERROR_CHECK(nrfx_ppi_channel_enable(ppi_channel)) // Configure Software Interrupt to call update_pulses APP_ERROR_CHECK(nrfx_swi_alloc(&swi, update_pulses, PULSE_UPDATES_IRQ_PRIORITY)); for (uint8_t channel = 0; channel < DEVICE_CHANNEL_COUNT; channel++) { egu_task_addrs[channel] = nrfx_swi_task_trigger_address_get(swi, channel); // Gate A pin pin = gate_pins[channel][0]; APP_ERROR_CHECK(nrfx_gpiote_out_init(pin, &gpiote_config)); task_addr = nrfx_gpiote_out_task_addr_get(pin); // Gate A rising edge evt_addr = nrfx_timer_compare_event_address_get(&timers[channel], 0); SET_GATE_PPI; ppi_channels[channel][0] = ppi_channel; // Gate A falling edge evt_addr = nrfx_timer_compare_event_address_get(&timers[channel], 1); SET_GATE_PPI; ppi_channels[channel][1] = ppi_channel; // Enable gate nrfx_gpiote_out_task_enable(pin); // Gate B pin pin = gate_pins[channel][1]; APP_ERROR_CHECK(nrfx_gpiote_out_init(pin, &gpiote_config)); task_addr = nrfx_gpiote_out_task_addr_get(pin); // Gate B rising edge evt_addr = nrfx_timer_compare_event_address_get(&timers[channel], 2); SET_GATE_PPI; ppi_channels[channel][2] = ppi_channel; // Gate B falling edge evt_addr = nrfx_timer_compare_event_address_get(&timers[channel], 3); SET_GATE_PPI; ppi_channels[channel][3] = ppi_channel; // Enable gate nrfx_gpiote_out_task_enable(pin); } }
And this is the SWI function:
static uint32_t volatile no_flags_count = 0; static void update_pulses(uint8_t __unused _swi, uint16_t flags) { if (!flags) { no_flags_count++; return; } // https://stackoverflow.com/a/18050458/161366 uint8_t channel = 31 - __builtin_clz(flags); /* Update timer compares */ }
When I check no_flags_count in a debugger it's always non-zero.