Our project is built wit NRF Connect SDK 2.9.0. For the UART we use nrfx_uarte library directly.
RX works perfectly, but TX is working only in blocking mode. If I call `nrfx_uarte_tx()` with flags=0, which assumes that the entire buffer will be sent over DMA in one go, the packet gets corrupted. I think this is because zephyr is not aware that the sleep should not be that deep.
To circumvent entering the sleep mode I place a loop after the nrfx_uarte_tx() which runs until the ISR resets a flag indicating the TX completion
static void uart0_handler(nrfx_uarte_event_t const * p_event, void * p_context) { nrfx_uarte_t * p_inst = p_context; static k_timeout_t idle_period = K_MSEC(IDLE_PERIOD); switch (p_event->type) { case NRFX_UARTE_EVT_TX_DONE: LOG_INF("TX0 done"); txRunning = false; // this is the flag indicating the completion break; // other event types ... } } bool uart0_tx_blocking(uint8_t *data, uint16_t size, uart0_tx_done_cb cb) { nrfx_err_t err; err = nrfx_uarte_tx(&uart0_inst, data, size, 0); if (err == NRFX_SUCCESS) { // prevent sleep while DMA transfer is running txRunning = true; while (txRunning) {} return true; } return false; }
So far it works like this, but as you can see it is blocking now. I can of course call it in a separate thread, but it's not nice to create a thread just for that.
Cleaner solution would be to somehow tell the Zephyr, that it should not sleep, it should use less restrictive power mode, so that DMA could finish the transaction.
I tried different pm_* functions, but without success. Obviously I'm missing something.
So the question is how to force a power mode that will allow DMA to finish?