Hardware: nRF5340DK
Software: SDK version v2.5.1
Description:
We are using the nrfx_spis driver and are debugging interrupt latency as we have tight timings to reload the SPIS DMA buffers. (<12.5us)
We are using CONFIG_ZERO_LATENCY_IRQS in an effort to keep the interrupt latency as short as possible.
Running our SPIS driver code with no other code running on the device, we see a ~4.5us interrupt latency from when the CS line goes HIGH and when our debug toggle IO.
Here is an example of this: I have a IO toggle in my own spis_handler as well as the irq_handler in nrfx_spis.c. Here the timing makes sense, <2us to enter the nrfx_spis handler, and another ~2us to get to our user handler.
Here is the relavant code:
#define BUFFER_SIZE (768) #define BUFFER_COUNT 2UL // Double Buffer static uint16_t dma_buf[BUFFER_COUNT][BUFFER_SIZE]; static uint16_t dummy_buf[BUFFER_SIZE] = {0}; /////***** SPIS Setup *****///// nrfx_spis_config_t spis_config = { .miso_pin = MISO_PIN, // .mosi_pin = MOSI_PIN, // .sck_pin = SCK_PIN, // .csn_pin = CSN_PIN, // .mode = NRF_SPIS_MODE_0, // .bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, // .csn_pullup = NRF_GPIO_PIN_NOPULL, // .miso_drive = NRF_GPIO_PIN_S0S1, // .def = 0xFF, // .orc = 0xFE, // .irq_priority = 0, // .skip_gpio_cfg = false, // .skip_psel_cfg = false, // }; err = nrfx_spis_init(&spis_inst, &spis_config, spis_handler, &spis_inst); if (err != NRFX_SUCCESS) { LOG_ERR("nrfx_spis_init"); } IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_SPIS_INST_GET(SPIS_INST_IDX)), 0, NRFX_SPIS_INST_HANDLER_GET(SPIS_INST_IDX), IRQ_ZERO_LATENCY); /////***** Start first transaction *****///// status = nrfx_spis_buffers_set(&spis_inst, (uint8_t*)dummy_buf, sizeof(dummy_buf), (uint8_t*)&dma_buf[0], sizeof(dma_buf[0])); if (status != NRFX_SUCCESS) { LOG_ERR("nrfx_spis_buffers_set"); } static void spis_handler(nrfx_spis_evt_t const* p_event, void* p_context) { nrfx_err_t status; if (p_event->evt_type == NRFX_SPIS_XFER_DONE) { gpio_pin_set_dt(&debug_pin, 1); static uint32_t buffer_inx = 0; if (buffer_inx == 0) { buffer_inx = 1; buf0_ready = true; } else { buffer_inx = 0; buf1_ready = true; } // Queue next status = nrfx_spis_buffers_set( &spis_inst, (uint8_t*)dummy_buf, sizeof(dummy_buf), (uint8_t*)&dma_buf[buffer_inx], sizeof(dma_buf[buffer_inx])); if (status != NRFX_SUCCESS) { LOG_ERR("nrfx_spis_buffers_set"); } gpio_pin_set_dt(&debug_pin, 0); } }
Issue:
However, we are encountering a ~12.5us increase in latency when a background task is running.
Here is the additional relevant code:
#define TASK_STACKSIZE 1024 #define TASK_PRIORITY 4 #define TASK_NAME "fpga" void FPGA_Init(void) { k_tid_t fpga_task_tid = k_thread_create(&fpga_task_thread, fpga_task_stack, K_THREAD_STACK_SIZEOF(fpga_task_stack), fpga_task, NULL, NULL, NULL, TASK_PRIORITY, 0, K_NO_WAIT); k_thread_name_set(fpga_task_tid, TASK_NAME); } void fpga_task(void* arg1, void* arg2, void* arg3) { while (1) { gpio_pin_set_dt(&fpga_reset_pin, 1); k_msleep(5); gpio_pin_set_dt(&fpga_reset_pin, 0); k_msleep(5); } }
Here is the logic capture:
The time-in-interrupt looks the same. There is simply a large shift in when the interrupt is serviced.
My hunch is that there is some kernel-call happening within the SPIS library irq_handler that is causing this delay sometimes, and this is related to a task running?
Any help is appreciated.