diff --git a/drivers/serial/uart_async_to_irq.c b/drivers/serial/uart_async_to_irq.c index 209e8d4f205..e18536449f3 100644 --- a/drivers/serial/uart_async_to_irq.c +++ b/drivers/serial/uart_async_to_irq.c @@ -105,12 +105,15 @@ static void on_rx_buf_req(const struct device *dev, static void on_rx_dis(const struct device *dev, struct uart_async_to_irq_data *data) { if (data->flags & A2I_RX_ENABLE) { - data->rx.pending_buf_req = 0; + int err; - int err = try_rx_enable(dev, data); + err = try_rx_enable(dev, data); + if (err == 0) { + data->rx.pending_buf_req = 0; + } LOG_INST_DBG(get_config(dev)->log, "Reenabling RX from RX_DISABLED (err:%d)", err); - __ASSERT_NO_MSG(err >= 0); + __ASSERT((err >= 0) || (err == -EBUSY), "err: %d", err); return; } diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 3a62057a47a..6e1ecfadfd8 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -1043,9 +1043,11 @@ static void rx_timeout(struct k_timer *timer) (data->async->rx_timeout_left < data->async->rx_timeout_slab)) { /* rx_timeout us elapsed since last receiving */ - notify_uart_rx_rdy(dev, len); - data->async->rx_offset += len; - data->async->rx_total_user_byte_cnt += len; + if (data->async->rx_buf != NULL) { + notify_uart_rx_rdy(dev, len); + data->async->rx_offset += len; + data->async->rx_total_user_byte_cnt += len; + } } else { data->async->rx_timeout_left -= data->async->rx_timeout_slab; diff --git a/drivers/spi/Kconfig.nrfx b/drivers/spi/Kconfig.nrfx index c185efa9f8f..0ee1c03065b 100644 --- a/drivers/spi/Kconfig.nrfx +++ b/drivers/spi/Kconfig.nrfx @@ -54,6 +54,7 @@ config SPI_NRFX_SPIS config SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 depends on SOC_NRF52832 + select NRFX_PPI bool "Allow enabling the SPIM driver despite PAN 58" help Allow enabling the nRF SPI Master with EasyDMA, despite @@ -74,14 +75,20 @@ config SPI_NRFX_RAM_BUFFER_SIZE default 8 depends on SPI_NRFX_SPIM help - SPIM peripherals cannot transmit data directly from flash. Therefore, - a buffer in RAM needs to be provided for each instance of SPI driver - using SPIM peripheral, so that the driver can copy there a chunk of - data from flash and transmit it. - The size is specified in bytes. A size of 0 means that this feature - should be disabled, and the application must then take care of not - supplying buffers located in flash to the driver, otherwise such - transfers will fail. + Because of using EasyDMA, SPIM peripherals cannot use transmit and + receive buffers from all memory locations. They are restricted to + buffers located in certain RAM memories only. Therefore, each SPIM + driver instance needs to use an intermediate local RAM buffer, + to transfer data in chunks not exceeding the size of that buffer, + and to copy those chunks between the local buffer and the one + specified in the transfer request if the latter is not accessible + by EasyDMA. + + This option specifies the size in bytes of such local RAM buffers + for both TX and RX paths. A size of 0 means that this feature should + be disabled and the driver user must take care of not making transfer + requests with buffers not accessible by EasyDMA since such transfers + will fail. config SPI_NRFX_WAKE_TIMEOUT_US int "Maximum time to wait for SPI slave to wake up" diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c index 04d7853d11d..752132fb248 100644 --- a/drivers/spi/spi_nrfx_spi.c +++ b/drivers/spi/spi_nrfx_spi.c @@ -161,8 +161,6 @@ static void finish_transaction(const struct device *dev, int error) struct spi_nrfx_data *dev_data = dev->data; struct spi_context *ctx = &dev_data->ctx; - spi_context_cs_control(ctx, false); - LOG_DBG("Transaction finished with status %d", error); spi_context_complete(ctx, dev, error); @@ -277,6 +275,8 @@ static int transceive(const struct device *dev, /* Clean up the driver state. */ k_sem_reset(&dev_data->ctx.sync); } + + spi_context_cs_control(&dev_data->ctx, false); } spi_context_release(&dev_data->ctx, error); diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index fb89f096cca..08012b389c5 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -11,8 +11,10 @@ #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 #include #endif -#include +#ifdef CONFIG_SOC_NRF5340_CPUAPP #include +#endif +#include #include #include @@ -39,8 +41,9 @@ struct spi_nrfx_data { size_t chunk_len; bool busy; bool initialized; -#if SPI_BUFFER_IN_RAM - uint8_t *buffer; +#ifdef SPI_BUFFER_IN_RAM + uint8_t *tx_buffer; + uint8_t *rx_buffer; #endif #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 bool anomaly_58_workaround_active; @@ -69,9 +72,9 @@ static inline uint32_t get_nrf_spim_frequency(uint32_t frequency) { /* Get the highest supported frequency not exceeding the requested one. */ - if (frequency >= MHZ(32) && NRF_SPIM_HAS_32_MHZ_FREQ) { + if (frequency >= MHZ(32) && (NRF_SPIM_HAS_32_MHZ_FREQ || NRF_SPIM_HAS_PRESCALER)) { return MHZ(32); - } else if (frequency >= MHZ(16) && NRF_SPIM_HAS_16_MHZ_FREQ) { + } else if (frequency >= MHZ(16) && (NRF_SPIM_HAS_16_MHZ_FREQ || NRF_SPIM_HAS_PRESCALER)) { return MHZ(16); } else if (frequency >= MHZ(8)) { return MHZ(8); @@ -291,8 +294,6 @@ static void finish_transaction(const struct device *dev, int error) struct spi_nrfx_data *dev_data = dev->data; struct spi_context *ctx = &dev_data->ctx; - spi_context_cs_control(ctx, false); - LOG_DBG("Transaction finished with status %d", error); spi_context_complete(ctx, dev, error); @@ -312,25 +313,40 @@ static void transfer_next_chunk(const struct device *dev) nrfx_spim_xfer_desc_t xfer; nrfx_err_t result; const uint8_t *tx_buf = ctx->tx_buf; -#if (CONFIG_SPI_NRFX_RAM_BUFFER_SIZE > 0) - if (spi_context_tx_buf_on(ctx) && !nrfx_is_in_ram(tx_buf)) { + uint8_t *rx_buf = ctx->rx_buf; + + if (chunk_len > dev_config->max_chunk_len) { + chunk_len = dev_config->max_chunk_len; + } + +#ifdef SPI_BUFFER_IN_RAM + if (spi_context_tx_buf_on(ctx) && + !nrf_dma_accessible_check(&dev_config->spim.p_reg, tx_buf)) { + if (chunk_len > CONFIG_SPI_NRFX_RAM_BUFFER_SIZE) { chunk_len = CONFIG_SPI_NRFX_RAM_BUFFER_SIZE; } - memcpy(dev_data->buffer, tx_buf, chunk_len); - tx_buf = dev_data->buffer; + memcpy(dev_data->tx_buffer, tx_buf, chunk_len); + tx_buf = dev_data->tx_buffer; } -#endif - if (chunk_len > dev_config->max_chunk_len) { - chunk_len = dev_config->max_chunk_len; + + if (spi_context_rx_buf_on(ctx) && + !nrf_dma_accessible_check(&dev_config->spim.p_reg, rx_buf)) { + + if (chunk_len > CONFIG_SPI_NRFX_RAM_BUFFER_SIZE) { + chunk_len = CONFIG_SPI_NRFX_RAM_BUFFER_SIZE; + } + + rx_buf = dev_data->rx_buffer; } +#endif dev_data->chunk_len = chunk_len; xfer.p_tx_buffer = tx_buf; xfer.tx_length = spi_context_tx_buf_on(ctx) ? chunk_len : 0; - xfer.p_rx_buffer = ctx->rx_buf; + xfer.p_rx_buffer = rx_buf; xfer.rx_length = spi_context_rx_buf_on(ctx) ? chunk_len : 0; #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 @@ -374,6 +390,15 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 anomaly_58_workaround_clear(dev_data); +#endif +#ifdef SPI_BUFFER_IN_RAM + if (spi_context_rx_buf_on(&dev_data->ctx) && + p_event->xfer_desc.p_rx_buffer != NULL && + p_event->xfer_desc.p_rx_buffer != dev_data->ctx.rx_buf) { + (void)memcpy(dev_data->ctx.rx_buf, + dev_data->rx_buffer, + dev_data->chunk_len); + } #endif spi_context_update_tx(&dev_data->ctx, 1, dev_data->chunk_len); spi_context_update_rx(&dev_data->ctx, 1, dev_data->chunk_len); @@ -443,6 +468,8 @@ static int transceive(const struct device *dev, anomaly_58_workaround_clear(dev_data); #endif } + + spi_context_cs_control(&dev_data->ctx, false); } spi_context_release(&dev_data->ctx, error); @@ -602,7 +629,10 @@ static int spi_nrfx_init(const struct device *dev) nrfx_isr, nrfx_spim_##idx##_irq_handler, 0); \ } \ IF_ENABLED(SPI_BUFFER_IN_RAM, \ - (static uint8_t spim_##idx##_buffer \ + (static uint8_t spim_##idx##_tx_buffer \ + [CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \ + SPIM_MEMORY_SECTION(idx); \ + static uint8_t spim_##idx##_rx_buffer \ [CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \ SPIM_MEMORY_SECTION(idx);)) \ static struct spi_nrfx_data spi_##idx##_data = { \ @@ -610,7 +640,8 @@ static int spi_nrfx_init(const struct device *dev) SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(SPIM(idx), ctx) \ IF_ENABLED(SPI_BUFFER_IN_RAM, \ - (.buffer = spim_##idx##_buffer,)) \ + (.tx_buffer = spim_##idx##_tx_buffer, \ + .rx_buffer = spim_##idx##_rx_buffer,)) \ .dev = DEVICE_DT_GET(SPIM(idx)), \ .busy = false, \ }; \ @@ -639,7 +670,7 @@ static int spi_nrfx_init(const struct device *dev) WAKE_PIN_NOT_USED), \ .wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \ }; \ - BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIM(idx), wake_gpios) || \ + BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \ !(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ "WAKE line must be configured as active high"); \ PM_DEVICE_DT_DEFINE(SPIM(idx), spim_nrfx_pm_action); \ diff --git a/soc/arm/nordic_nrf/nrf53/Kconfig.soc b/soc/arm/nordic_nrf/nrf53/Kconfig.soc index f72ae5ab004..b3ca2661675 100644 --- a/soc/arm/nordic_nrf/nrf53/Kconfig.soc +++ b/soc/arm/nordic_nrf/nrf53/Kconfig.soc @@ -12,13 +12,14 @@ config SOC_NRF5340_CPUAPP select HAS_POWEROFF select SOC_COMPATIBLE_NRF5340_CPUAPP imply SOC_NRF53_RTC_PRETICK + imply SOC_NRF53_ANOMALY_168_WORKAROUND config SOC_NRF5340_CPUNET bool - select ARM_ON_EXIT_CPU_IDLE select SOC_COMPATIBLE_NRF5340_CPUNET imply SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED imply SOC_NRF53_RTC_PRETICK if !WDT_NRFX + imply SOC_NRF53_ANOMALY_168_WORKAROUND choice prompt "nRF53x MCU Selection" @@ -79,6 +80,25 @@ config SOC_NRF53_RTC_PRETICK_IPC_CH_TO_NET endif +config SOC_NRF53_ANOMALY_168_WORKAROUND + bool "Workaround for nRF5340 anomaly 168" + select ARM_ON_EXIT_CPU_IDLE + help + Indicates that the workaround for the anomaly 168 that affects + the nRF5340 SoC should be applied. + The workaround involves execution of 8 NOP instructions when the CPU + exist its idle state (when the WFI/WFE instruction returns) and it is + enabled by default for both the application and network core. + +config SOC_NRF53_ANOMALY_168_WORKAROUND_FOR_EXECUTION_FROM_RAM + bool "Extend the workaround to execution at 128 MHz from RAM" + depends on SOC_NRF53_ANOMALY_168_WORKAROUND && SOC_NRF5340_CPUAPP + help + Indicates that the anomaly 168 workaround is to be extended to cover + also a specific case when the WFI/WFE instruction is executed at 128 + MHz from RAM. Then, 26 instead of 8 NOP instructions needs to be + executed after WFI/WFE. This extension is not enabled by default. + if SOC_NRF5340_CPUAPP config SOC_DCDC_NRF53X_APP diff --git a/soc/arm/nordic_nrf/nrf53/soc_cpu_idle.h b/soc/arm/nordic_nrf/nrf53/soc_cpu_idle.h index b6cd92ca092..c02c9451419 100644 --- a/soc/arm/nordic_nrf/nrf53/soc_cpu_idle.h +++ b/soc/arm/nordic_nrf/nrf53/soc_cpu_idle.h @@ -11,10 +11,16 @@ #if defined(_ASMLANGUAGE) +#if defined(CONFIG_SOC_NRF53_ANOMALY_168_WORKAROUND_FOR_EXECUTION_FROM_RAM) #define SOC_ON_EXIT_CPU_IDLE \ + .rept 26; \ nop; \ + .endr +#elif defined(CONFIG_SOC_NRF53_ANOMALY_168_WORKAROUND) +#define SOC_ON_EXIT_CPU_IDLE \ + .rept 8; \ nop; \ - nop; \ - nop; + .endr +#endif #endif /* _ASMLANGUAGE */