Sfoglia il codice sorgente

bsp/nrf5x: nrf52840添加spim驱动 (#10576)

* 添加了spim的底层驱动和设备驱动

* 添加了nrf52840 的spim底层驱动和设备驱动

* 添加了spim的底层驱动和设备驱动

* 添加了spim的底层驱动和设备驱动

* 代码规范

* 1. 在rt-thread\bsp\nrf5x\nrf52840\.ci\attachconfig\ci.attachconfig.yml中添加了spim的相关设置。
devices.spim:
    kconfig:
      - CONFIG_RT_USING_SPIM=y
      - CONFIG_BSP_USING_SPIM=y
2. nrfx_dpim.h 注释中纠正了错误的拼写
3. 多个文件中:nrfx_spim.c drv_spim.c drv_spim.h 删减了多余的宏定义:USING_SPI_DMA
4. nrfx_spim.c中删除了DMA_TRANS_MIN_LEN,该宏定义定义了spi+dma最小传输字节,直接定义20。
Core0349 1 mese fa
parent
commit
fbf4856ffa

+ 10 - 7
bsp/nrf5x/libraries/drivers/drv_adc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -221,13 +221,13 @@ INIT_BOARD_EXPORT(rt_hw_adc_init);
 /*test saadc*/
 #include <drv_adc.h>
 
-#define SAMPLE_ADC_MODE_SINGLE_ENDED    0   //single-ended mode
-#define SAMPLE_ADC_MODE_DIFFERENTIAL    1   //differential mode
+#define SAMPLE_ADC_MODE_SINGLE_ENDED    0   /* single-ended mode */
+#define SAMPLE_ADC_MODE_DIFFERENTIAL    1   /* differential mode */
 
 #define SAMPLE_ADC_AIN1     1
 #define SAMPLE_ADC_AIN2     2
 #define SAMPLE_ADC_AIN7     7
-#define SAMPLE_ADC_AIN_NC   0   //disable input of AINx
+#define SAMPLE_ADC_AIN_NC   0   /* disable input of AINx */
 
 #define SAMPLE_ADC_CHANNEL_0   0
 #define SAMPLE_ADC_CHANNEL_1   1
@@ -242,19 +242,22 @@ void saadc_sample(void)
     adc_dev = (rt_adc_device_t)rt_device_find(ADC_NAME);
     adc_dev->parent.user_data = &channel_config;
 
-    channel_config = (drv_nrfx_saadc_channel_t){.mode = SAMPLE_ADC_MODE_SINGLE_ENDED,
+    channel_config = (drv_nrfx_saadc_channel_t)
+    {.mode = SAMPLE_ADC_MODE_SINGLE_ENDED,
                                                 .pin_p = SAMPLE_ADC_AIN1,
                                                 .pin_n = SAMPLE_ADC_AIN_NC,
                                                 .channel_num = SAMPLE_ADC_CHANNEL_0};
     rt_adc_enable(adc_dev, channel_config.channel_num);
 
-    channel_config = (drv_nrfx_saadc_channel_t){.mode = SAMPLE_ADC_MODE_SINGLE_ENDED,
+    channel_config = (drv_nrfx_saadc_channel_t)
+    {.mode = SAMPLE_ADC_MODE_SINGLE_ENDED,
                                                 .pin_p = SAMPLE_ADC_AIN2,
                                                 .pin_n = SAMPLE_ADC_AIN_NC,
                                                 .channel_num = SAMPLE_ADC_CHANNEL_1};
     rt_adc_enable(adc_dev, channel_config.channel_num);
 
-    channel_config = (drv_nrfx_saadc_channel_t){.mode = SAMPLE_ADC_MODE_SINGLE_ENDED,
+    channel_config = (drv_nrfx_saadc_channel_t)
+    {.mode = SAMPLE_ADC_MODE_SINGLE_ENDED,
                                                 .pin_p = SAMPLE_ADC_AIN7,
                                                 .pin_n = SAMPLE_ADC_AIN_NC,
                                                 .channel_num = SAMPLE_ADC_CHANNEL_5};

+ 6 - 5
bsp/nrf5x/libraries/drivers/drv_adc.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -31,10 +31,10 @@
  */
 typedef struct
 {
-    nrf_saadc_mode_t    mode;           ///< SAADC mode. Single-ended or differential.
-    uint8_t             pin_p;          ///< Input positive pin selection.
-    uint8_t             pin_n;          ///< Input negative pin selection.
-    uint8_t             channel_num;    ///< Channel number.
+    nrf_saadc_mode_t    mode;           /* /< SAADC mode. Single-ended or differential. */
+    uint8_t             pin_p;          /* /< Input positive pin selection. */
+    uint8_t             pin_n;          /* /< Input negative pin selection. */
+    uint8_t             channel_num;    /* /< Channel number. */
 } drv_nrfx_saadc_channel_t;
 
 typedef struct
@@ -46,3 +46,4 @@ typedef struct
 } drv_nrfx_saadc_result_t;
 
 #endif /* __DRV_ADC_H__ */
+

+ 5 - 3
bsp/nrf5x/libraries/drivers/drv_flash.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -95,8 +95,8 @@ int mcu_flash_write(rt_uint32_t addr, const uint8_t *buf, size_t size)
     if (addr % 4 != 0)
     {
         LOG_E("write addr should be 4-byte alignment");
-        //4byte write
-        //else byts
+        /* 4byte write */
+        /* else byts */
         return -RT_EINVAL;
     }
 
@@ -104,6 +104,7 @@ int mcu_flash_write(rt_uint32_t addr, const uint8_t *buf, size_t size)
     {
         return -RT_ERROR;
     }
+
     if (size % 4 != 0)
     {
         nrfx_nvmc_bytes_write(addr, buf, size);
@@ -186,3 +187,4 @@ const struct fal_flash_dev mcu_onchip_flash =
 };
 #endif
 #endif /* BSP_USING_ON_CHIP_FLASH */
+

+ 11 - 5
bsp/nrf5x/libraries/drivers/drv_gpio.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -223,6 +223,7 @@ static rt_err_t nrf5x_pin_attach_irq(struct rt_device *device, rt_base_t pin,
             break;
         }
     }
+
     if(irqindex == -1)
     {
         return -RT_ENOMEM;
@@ -298,6 +299,7 @@ static rt_err_t nrf5x_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
             break;
         }
     }
+
     if(i >= irq_quantity)
     {
         return -RT_ENOSYS;
@@ -414,6 +416,7 @@ void button_1_callback(void *args)
         rt_pin_write(DK_BOARD_LED_1, PIN_HIGH);
     }
 }
+
 void button_2_callback(void *args)
 {
     static int flag2 = 0;
@@ -428,6 +431,7 @@ void button_2_callback(void *args)
         rt_pin_write(DK_BOARD_LED_2, PIN_HIGH);
     }
 }
+
 void button_3_callback(void *args)
 {
     static int flag3 = 0;
@@ -442,6 +446,7 @@ void button_3_callback(void *args)
         rt_pin_write(DK_BOARD_LED_3, PIN_HIGH);
     }
 }
+
 void button_4_callback(void *args)
 {
     static int flag4 = 0;
@@ -470,21 +475,22 @@ void gpio_sample(void)
     rt_pin_write(DK_BOARD_LED_4, PIN_HIGH);
 
     rt_pin_attach_irq(DK_BOARD_BUTTON_1, PIN_IRQ_MODE_FALLING,
-                                    button_1_callback, (void*) true); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT)
+                                    button_1_callback, (void*) true); /* true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) */
     rt_pin_irq_enable(DK_BOARD_BUTTON_1, PIN_IRQ_ENABLE);
 
     rt_pin_attach_irq(DK_BOARD_BUTTON_2, PIN_IRQ_MODE_FALLING,
-                                    button_2_callback, (void*) true); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT)
+                                    button_2_callback, (void*) true); /* true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) */
     rt_pin_irq_enable(DK_BOARD_BUTTON_2, PIN_IRQ_ENABLE);
 
     rt_pin_attach_irq(DK_BOARD_BUTTON_3, PIN_IRQ_MODE_FALLING,
-                                    button_3_callback, (void*) true); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT)
+                                    button_3_callback, (void*) true); /* true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) */
     rt_pin_irq_enable(DK_BOARD_BUTTON_3, PIN_IRQ_ENABLE);
 
     rt_pin_attach_irq(DK_BOARD_BUTTON_4, PIN_IRQ_MODE_FALLING,
-                                    button_4_callback, (void*) false); //true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT)
+                                    button_4_callback, (void*) false); /* true: hi_accuracy(IN_EVENT),false: lo_accuracy(PORT_EVENT) */
     rt_pin_irq_enable(DK_BOARD_BUTTON_4, PIN_IRQ_ENABLE);
 }
 MSH_CMD_EXPORT(gpio_sample, gpio sample);
 
 #endif /* RT_USING_PIN */
+

+ 2 - 2
bsp/nrf5x/libraries/drivers/drv_gpio.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -34,7 +34,7 @@
 struct pin_index
 {
     int index;
-    NRF_GPIO_Type *gpio;//NRF_P0 or NRF_P1
+    NRF_GPIO_Type *gpio;/* NRF_P0 or NRF_P1 */
     rt_base_t pin;
 };
 

+ 7 - 7
bsp/nrf5x/libraries/drivers/drv_hwtimer.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -27,7 +27,7 @@
 #ifdef RT_USING_HWTIMER
 
 #ifndef TIM_DEV_INFO_CONFIG
-// maxfreq and minfreq unit is HZ
+/* maxfreq and minfreq unit is HZ */
 #define TIM_DEV_INFO_CONFIG                     \
     {                                           \
         .maxfreq = 16000000,                    \
@@ -103,7 +103,7 @@ static void timer_callback(nrf_timer_event_t event_type, void* p_context)
 {
     rt_hwtimer_t       *timer_device = (struct rt_hwtimer_device *)p_context;
 
-    // no matter what event_type is(NRF_TIMER_EVENT_COMPARE0 or others), call same function "rt_device_hwtimer_isr"
+    /* no matter what event_type is(NRF_TIMER_EVENT_COMPARE0 or others), call same function "rt_device_hwtimer_isr" */
     LOG_D("timer_callback event_type = %d, inst_id = %d, cc conunt = %d\r\n",
            event_type, timer_info->timer_inst.instance_id, timer_info->timer_inst.cc_channel_count);
     rt_device_hwtimer_isr(timer_device);
@@ -137,12 +137,12 @@ static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_
 
     if (opmode == HWTIMER_MODE_ONESHOT)
     {
-        // means TIMER_SHORTS_COMPARE0_STOP_Msk or TIMER_SHORTS_COMPARE1_STOP_Msk ..., according to cc_channel.
+        /* means TIMER_SHORTS_COMPARE0_STOP_Msk or TIMER_SHORTS_COMPARE1_STOP_Msk ..., according to cc_channel. */
         mask = (nrf_timer_short_mask_t)(1 << (timer_info->cc_channel + 8));
     }
     else
     {
-        // means TIMER_SHORTS_COMPARE0_CLEAR_Msk or TIMER_SHORTS_COMPARE1_CLEAR_Msk ..., according to cc_channel.
+        /* means TIMER_SHORTS_COMPARE0_CLEAR_Msk or TIMER_SHORTS_COMPARE1_CLEAR_Msk ..., according to cc_channel. */
         mask = (nrf_timer_short_mask_t)(1 << timer_info->cc_channel);
     }
 
@@ -276,8 +276,8 @@ static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
 
     timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
 
-    // capture method will copy the current counter register to the specified cc channel (here is NRF_TIMER_CC_CHANNEL5).
-    // the specified cc channel cannot be same with the already used cc channels
+    /* capture method will copy the current counter register to the specified cc channel (here is NRF_TIMER_CC_CHANNEL5). */
+    /* the specified cc channel cannot be same with the already used cc channels */
     count = nrfx_timer_capture(&(timer_info->timer_inst), NRF_TIMER_CC_CHANNEL5);
     return count;
 }

+ 2 - 1
bsp/nrf5x/libraries/drivers/drv_i2c.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -173,3 +173,4 @@ int rt_hw_i2c_init(void)
 
 INIT_BOARD_EXPORT(rt_hw_i2c_init);
 #endif /* defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) */
+

+ 2 - 1
bsp/nrf5x/libraries/drivers/drv_i2c.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -21,3 +21,4 @@ extern "C" {
 
 
 #endif  /* __DRV_I2C_H__ */
+

+ 6 - 3
bsp/nrf5x/libraries/drivers/drv_pwm.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -223,9 +223,9 @@ static rt_err_t mcu_hw_pwm_init(struct mcu_pwm *device)
     nrfx_pwm_config_t config0 =
     {
         .irq_priority = _PRIO_APP_LOWEST,
-        .base_clock   = NRF_PWM_CLK_1MHz,  //default value
+        .base_clock   = NRF_PWM_CLK_1MHz,  /* default value */
         .count_mode   = NRF_PWM_MODE_UP,
-        .top_value    = 5000,              //default vaule
+        .top_value    = 5000,              /* default vaule */
         .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
         .step_mode    = NRF_PWM_STEP_AUTO
     };
@@ -414,10 +414,12 @@ static int pwm_led_sample(int argc, char *argv[])
         {
             pulse -= 500;
         }
+
         if (pulse >= period)
         {
             dir = 0;
         }
+
         if (0 == pulse)
         {
             dir = 1;
@@ -430,3 +432,4 @@ static int pwm_led_sample(int argc, char *argv[])
 MSH_CMD_EXPORT(pwm_led_sample, pwm sample);
 
 #endif
+

+ 7 - 5
bsp/nrf5x/libraries/drivers/drv_qspi_flash.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -14,7 +14,7 @@
 #if defined(RT_USING_FAL)
 #include <fal.h>
 
-//log
+/* log */
 #include <rtdbg.h>
 #define LOG_TAG                "drv.qspiflash"
 
@@ -47,14 +47,14 @@ static void configure_memory()
         .wren      = true
     };
 
-    // Send reset enable
+    /* Send reset enable */
     err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
     if (NRFX_SUCCESS != err_code)
     {
         LOG_E("\r\n ERROR: QSPI_STD_CMD_RSTEN:0x%x\n", err_code);
         return ;
     }
-    // Send reset command
+    /* Send reset command */
     cinstr_cfg.opcode = QSPI_STD_CMD_RST;
     err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
     if (NRFX_SUCCESS != err_code)
@@ -63,7 +63,7 @@ static void configure_memory()
         return ;
     }
 
-    // Switch to qspi mode
+    /* Switch to qspi mode */
     cinstr_cfg.opcode = QSPI_STD_CMD_WRSR;
     cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
     err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, &temporary, NULL);
@@ -73,6 +73,7 @@ static void configure_memory()
         return;
     }
 }
+
 static int init(void)
 {
     rt_uint32_t err_code;
@@ -151,3 +152,4 @@ struct fal_flash_dev nor_flash0 =
 };
 
 #endif
+

+ 4 - 4
bsp/nrf5x/libraries/drivers/drv_rtc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -33,7 +33,7 @@
 #define RTC_INSTANCE_ID (2)
 #endif
 
-#define TICK_FREQUENCE_HZ        (RT_TICK_PER_SECOND)     // RTC tick frequence, in HZ
+#define TICK_FREQUENCE_HZ        (RT_TICK_PER_SECOND)     /* RTC tick frequence, in HZ */
 
 static struct rt_rtc_device rtc;
 static time_t init_time;
@@ -62,7 +62,7 @@ static rt_err_t rt_rtc_config(struct rt_device *dev)
     nrf_clock_lf_src_set(NRF_CLOCK, (nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
     nrfx_clock_lfclk_start();
 
-    //Initialize RTC instance
+    /* Initialize RTC instance */
     nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
     config.prescaler = RTC_PRESCALER;
 
@@ -70,7 +70,7 @@ static rt_err_t rt_rtc_config(struct rt_device *dev)
 
     nrfx_rtc_tick_enable(&rtc_instance, true);
 
-    //Power on RTC instance
+    /* Power on RTC instance */
     nrfx_rtc_enable(&rtc_instance);
 
     return RT_EOK;

+ 15 - 10
bsp/nrf5x/libraries/drivers/drv_spi.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -49,7 +49,7 @@ static struct nrfx_drv_spi_config spi_config[] =
 
 static struct nrfx_drv_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])];
 
-//Configure SPI bus pins using the menuconfig
+/* Configure SPI bus pins using the menuconfig */
 static struct nrfx_drv_spi_pin_config bsp_spi_pin[] =
 {
 #ifdef BSP_USING_SPI0
@@ -128,10 +128,12 @@ static void spi2_handler(const nrfx_spim_evt_t *p_event, void *p_context)
 {
     LOG_I("\nspi2_handler");
 }
+
 static void spi3_handler(const nrfx_spim_evt_t *p_event, void *p_context)
 {
     LOG_I("\nspi3_handler");
 }
+
 static void spi4_handler(const nrfx_spim_evt_t *p_event, void *p_context)
 {
     LOG_I("\nspi4_handler");
@@ -224,7 +226,7 @@ static rt_err_t spi_configure(struct rt_spi_device *device,
     }
 
     rt_memcpy((void*)&spi_bus_obj[index].spi_config, (void*)&config, sizeof(nrfx_spim_config_t));
-    nrfx_spim_evt_handler_t handler = RT_NULL;    //spi send callback handler ,default NULL
+    nrfx_spim_evt_handler_t handler = RT_NULL;    /* spi send callback handler ,default NULL */
     void * context = RT_NULL;
     nrfx_err_t nrf_ret = nrfx_spim_init(&spi, &config, handler, context);
     if(NRFX_SUCCESS == nrf_ret)
@@ -258,6 +260,7 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
     {
         p_xfer_desc.tx_length = 0;
     }
+
     if(message->recv_buf == RT_NULL)
     {
         p_xfer_desc.rx_length = 0;
@@ -293,7 +296,7 @@ static int rt_hw_spi_bus_init(void)
     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
     {
         spi_bus_obj[i].spi = spi_config[i].spi;
-        spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   //SPI INSTANCE
+        spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   /* SPI INSTANCE */
         result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &nrfx_spi_ops);
         RT_ASSERT(result == RT_EOK);
     }
@@ -350,7 +353,7 @@ static int spi_sample(int argc, char *argv[])
 
 
 
-       /* 查找 spi 设备获取设备句柄 */
+    /* find spi device to get handler */
     spi_dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
     if (!spi_dev)
     {
@@ -359,10 +362,10 @@ static int spi_sample(int argc, char *argv[])
     else
     {
          rt_spi_configure(spi_dev, &cfg);
-        /* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */
+        /* use func: rt_spi_send_then_recv() send and read ID */
          while(1)
        { rt_spi_send(spi_dev, m_tx_buf, 6);rt_thread_mdelay(500);}
-        //rt_kprintf("use rt_spi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]);
+        /* rt_kprintf("use rt_spi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]); */
         }
 return RT_EOK;
 
@@ -389,7 +392,7 @@ static struct nrfx_drv_spi_config spi_config[] =
 
 static struct nrfx_drv_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])];
 
-//Configure SPI bus pins using the menuconfig
+/* Configure SPI bus pins using the menuconfig */
 static struct nrfx_drv_spi_pin_config bsp_spi_pin[] =
 {
 #ifdef BSP_USING_SPI0
@@ -534,7 +537,7 @@ static rt_err_t spi_configure(struct rt_spi_device *device,
     }
 
     rt_memcpy((void*)&spi_bus_obj[index].spi_config, (void*)&config, sizeof(nrfx_spi_config_t));
-    nrfx_spi_evt_handler_t handler = RT_NULL;    //spi send callback handler ,default NULL
+    nrfx_spi_evt_handler_t handler = RT_NULL;    /* spi send callback handler ,default NULL */
     void * context = RT_NULL;
     nrfx_err_t nrf_ret = nrfx_spi_init(&spi, &config, handler, context);
     if(NRFX_SUCCESS == nrf_ret)
@@ -568,6 +571,7 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
     {
         p_xfer_desc.tx_length = 0;
     }
+
     if(message->recv_buf == RT_NULL)
     {
         p_xfer_desc.rx_length = 0;
@@ -603,7 +607,7 @@ static int rt_hw_spi_bus_init(void)
     for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
     {
         spi_bus_obj[i].spi = spi_config[i].spi;
-        spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   //SPI INSTANCE
+        spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];   /* SPI INSTANCE */
         result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &nrfx_spi_ops);
         RT_ASSERT(result == RT_EOK);
     }
@@ -644,3 +648,4 @@ rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name,
 #endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */
 #endif
 #endif /*BSP_USING_SPI*/
+

+ 4 - 3
bsp/nrf5x/libraries/drivers/drv_spi.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -29,7 +29,7 @@
 */
 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin);
 
-//SPI bus config
+/* SPI bus config */
 #ifdef BSP_USING_SPI0
 #define NRFX_SPI0_CONFIG         \
 {                                \
@@ -101,7 +101,7 @@ struct nrfx_drv_spi_pin_config
 */
 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin);
 
-//SPI bus config
+/* SPI bus config */
 #ifdef BSP_USING_SPI0
 #define NRFX_SPI0_CONFIG         \
 {                                \
@@ -149,3 +149,4 @@ struct nrfx_drv_spi_pin_config
 #endif
 #endif /* BSP_USING_SPI */
 #endif  /*__DRV_SPI_H_*/
+

+ 332 - 0
bsp/nrf5x/libraries/drivers/drv_spim.c

@@ -0,0 +1,332 @@
+#include <stdint.h>
+#include <string.h>
+#include "board.h"
+#include "drv_spim.h"
+#include "rtconfig.h"
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_LEVEL   DBG_LOG
+#include <rtdbg.h>
+/* #define LOG_TAG                "drv.spim" */
+
+#ifdef BSP_USING_SPIM
+
+#if defined(BSP_USING_SPIM0) || defined(BSP_USING_SPIM1) || defined(BSP_USING_SPIM2) || defined(BSP_USING_SPIM3)
+
+static struct nrfx_drv_spim_config spim_config[] =
+{
+#ifdef BSP_USING_SPIM0
+    NRFX_SPIM0_CONFIG,
+#endif
+
+#ifdef BSP_USING_SPIM1
+    NRFX_SPIM1_CONFIG,
+#endif
+
+#ifdef BSP_USING_SPIM2
+    NRFX_SPIM2_CONFIG,
+#endif
+
+#ifdef BSP_USING_SPIM3
+    NRFX_SPIM3_CONFIG,
+#endif
+
+};
+
+static struct nrfx_drv_spim spim_bus_obj[sizeof(spim_config) / sizeof(spim_config[0])];
+
+/* Configure SPIM bus pins using the menuconfig */
+static struct nrfx_drv_spim_pin_config bsp_spim_pin[] =
+{
+#ifdef BSP_USING_SPIM0
+    {
+        .sck_pin  = BSP_SPIM0_SCK_PIN,
+        .mosi_pin = BSP_SPIM0_MOSI_PIN,
+        .miso_pin = BSP_SPIM0_MISO_PIN,
+        .ss_pin   = BSP_SPIM0_SS_PIN
+    },
+#endif
+
+#ifdef BSP_USING_SPIM1
+    {
+        .sck_pin  = BSP_SPIM1_SCK_PIN,
+        .mosi_pin = BSP_SPIM1_MOSI_PIN,
+        .miso_pin = BSP_SPIM1_MISO_PIN,
+        .ss_pin   = BSP_SPIM1_SS_PIN
+    },
+#endif
+
+#ifdef BSP_USING_SPIM2
+    {
+        .sck_pin  = BSP_SPIM2_SCK_PIN,
+        .mosi_pin = BSP_SPIM2_MOSI_PIN,
+        .miso_pin = BSP_SPIM2_MISO_PIN,
+        .ss_pin   = BSP_SPIM2_SS_PIN
+    },
+#endif
+
+#ifdef BSP_USING_SPIM3
+    {
+        .sck_pin  = BSP_SPIM3_SCK_PIN,
+        .mosi_pin = BSP_SPIM3_MOSI_PIN,
+        .miso_pin = BSP_SPIM3_MISO_PIN,
+        .ss_pin   = BSP_SPIM3_SS_PIN
+    },
+#endif
+
+};
+
+static rt_uint8_t spim_index_find(struct rt_spi_bus *spi_bus)
+{
+    for (int i = 0; i < sizeof(spim_config) / sizeof(spim_config[0]); i++)
+    {
+        if(spi_bus == &spim_bus_obj[i].spim_bus)
+            return i;
+    }
+    return 0xFF;
+}
+
+/**
+ * spi event handler function
+ */
+#ifdef BSP_USING_SPIM0
+static void spim0_handler(const nrfx_spim_evt_t *p_event, void *p_context)
+{
+    LOG_I("\nspim0_handler");
+}
+#endif
+
+#ifdef BSP_USING_SPIM1
+static void spim1_handler(const nrfx_spim_evt_t *p_event, void *p_context)
+{
+    LOG_I("\nspim1_handler");
+}
+#endif
+
+#ifdef BSP_USING_SPIM2
+static void spim2_handler(const nrfx_spim_evt_t *p_event, void *p_context)
+{
+        return;
+}
+#endif
+
+#ifdef BSP_USING_SPIM3
+static void spim3_handler(const nrfx_spim_evt_t *p_event, void *p_context)
+{
+    return;
+}
+#endif
+
+nrfx_spim_evt_handler_t spim_handler[] = {
+#ifdef BSP_USING_SPIM0
+    spim0_handler,
+#endif
+
+#ifdef BSP_USING_SPIM1
+    spim1_handler,
+#endif
+
+#ifdef BSP_USING_SPIM2
+    spim2_handler,
+#endif
+
+#ifdef BSP_USING_SPIM3
+    spim3_handler,
+#endif
+
+};
+
+/**
+  * @brief  This function config spi bus
+  * @param  device
+  * @param  configuration
+  * @retval RT_EOK / -RT_ERROR
+  */
+static rt_err_t spim_configure(struct rt_spi_device *device,
+                               struct rt_spi_configuration *configuration)
+{
+    RT_ASSERT(device != RT_NULL);
+    RT_ASSERT(device->bus != RT_NULL);
+    RT_ASSERT(device->bus->parent.user_data != RT_NULL);
+    RT_ASSERT(configuration != RT_NULL);
+
+    rt_uint8_t index = spim_index_find(device->bus);
+    RT_ASSERT(index != 0xFF);
+
+    nrfx_spim_t spim = spim_bus_obj[index].spim;
+    nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG(bsp_spim_pin[index].sck_pin,
+                                                        bsp_spim_pin[index].mosi_pin,
+                                                        bsp_spim_pin[index].miso_pin,
+                                                        bsp_spim_pin[index].ss_pin);
+    config.ss_active_high = false;
+
+    /* spi config ss pin */
+
+    /* spi config bit order */
+    if(configuration->mode & RT_SPI_MSB)
+    {
+        config.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
+    }
+    else
+    {
+        config.bit_order = NRF_SPIM_BIT_ORDER_LSB_FIRST;
+    }
+    /* spi mode config */
+    switch (configuration->mode & NRF_SPIM_MODE_3)
+    {
+    case NRF_SPIM_MODE_0/* RT_SPI_CPOL:0 , RT_SPI_CPHA:0 */:
+        config.mode = NRF_SPIM_MODE_0;
+        break;
+    case NRF_SPIM_MODE_1/* RT_SPI_CPOL:0 , RT_SPI_CPHA:1 */:
+        config.mode = NRF_SPIM_MODE_1;
+        break;
+    case NRF_SPIM_MODE_2/* RT_SPI_CPOL:1 , RT_SPI_CPHA:0 */:
+        config.mode = NRF_SPIM_MODE_2;
+        break;
+    case NRF_SPIM_MODE_3/* RT_SPI_CPOL:1 , RT_SPI_CPHA:1 */:
+        config.mode = NRF_SPIM_MODE_3;
+        break;
+    default:
+        LOG_E("spim_configure mode error %x\n",configuration->mode);
+        return -RT_ERROR;
+    }
+    /* spi frequency config */
+    switch (configuration->max_hz / 1000)
+    {
+    case 125:
+        config.frequency = NRF_SPIM_FREQ_125K;
+        break;
+    case 250:
+        config.frequency = NRF_SPIM_FREQ_250K;
+        break;
+    case 500:
+        config.frequency = NRF_SPIM_FREQ_500K;
+        break;
+    case 1000:
+        config.frequency = NRF_SPIM_FREQ_1M;
+        break;
+    case 2000:
+        config.frequency = NRF_SPIM_FREQ_2M;
+        break;
+    case 4000:
+        config.frequency = NRF_SPIM_FREQ_4M;
+        break;
+    case 8000:
+        config.frequency = NRF_SPIM_FREQ_8M;
+        break;
+    case 16000:
+        config.frequency = NRF_SPIM_FREQ_16M;
+        break;
+    case 32000:
+        config.frequency = NRF_SPIM_FREQ_32M;
+        break;
+
+    default:
+        LOG_E("spim_configure rate error %d\n",configuration->max_hz);
+        break;
+    }
+
+    rt_memcpy((void*)&spim_bus_obj[index].spim_config, (void*)&config, sizeof(nrfx_spim_config_t));
+
+    void * context = RT_NULL;
+    nrfx_spim_evt_handler_t handler = RT_NULL;    /* spi send callback handler ,default NULL */
+
+    /* create and init completion */
+    struct rt_completion *cpt = (struct rt_completion*)rt_malloc(sizeof(struct rt_completion));
+    rt_completion_init(cpt);
+    /* create and init message about spim */
+    struct spi_dma_message *mess = (struct spi_dma_message*)rt_malloc(sizeof(struct spi_dma_message));
+    /* step 1: cs pin */
+    mess->cs_pin         = device->cs_pin;
+    /* step 2: cs pin behavior */
+    mess->cs_take        = 0;
+    mess->cs_release     = 0;
+    /* step 3 */
+    mess->use_hw_ss      = config.use_hw_ss;
+    /* step 4: cs pin active */
+    mess->ss_active_high = config.ss_active_high;
+    /* step 6 */
+    mess->cpt            = cpt;
+    context              = (void*)mess;
+    handler              = spim_handler[index];
+
+    nrfx_err_t nrf_ret = nrfx_spim_init(&spim, &config, handler, context);
+    if(NRFX_SUCCESS == nrf_ret)
+        return RT_EOK;
+    else
+        LOG_E("spim configure fail. %x", nrf_ret);
+
+    return -RT_ERROR;
+}
+
+
+static rt_ssize_t spimxfer(struct rt_spi_device *device, struct rt_spi_message *message)
+{
+    RT_ASSERT(device != RT_NULL);
+    RT_ASSERT(device->bus != RT_NULL);
+    RT_ASSERT(device->bus->parent.user_data != RT_NULL);
+
+    rt_uint8_t index = spim_index_find(device->bus);
+    nrfx_err_t nrf_ret;
+    RT_ASSERT(index != 0xFF);
+
+    nrfx_spim_t * p_instance = &(spim_bus_obj[index].spim);
+
+    nrfx_spim_xfer_desc_t p_xfer_desc = NRFX_SPIM_XFER_TRX(message->send_buf, message->length, message->recv_buf, message->length);
+
+    if(message->send_buf == RT_NULL)
+    {
+        p_xfer_desc.tx_length = 0;
+    }
+
+    if(message->recv_buf == RT_NULL)
+    {
+        p_xfer_desc.rx_length = 0;
+    }
+
+    nrf_ret = rtt_nrfx_spim_xfer(p_instance, &p_xfer_desc, 0, message, device);
+
+    if( NRFX_SUCCESS != nrf_ret)
+    {
+        LOG_E("SPIM data transfer fail. %x", nrf_ret);
+        return 0;
+    }
+    else
+    {
+        return message->length;
+    }
+}
+
+
+/* spi bus callback function  */
+static const struct rt_spi_ops nrfx_spim_ops =
+{
+    .configure = spim_configure,
+    .xfer = spimxfer,
+};
+
+/*spim bus init*/
+static int rt_hw_spim_bus_init(void)
+{
+    rt_err_t result = -RT_ERROR;
+    for (int i = 0; i < sizeof(spim_config) / sizeof(spim_config[0]); i++)
+    {
+        spim_bus_obj[i].spim = spim_config[i].spi;
+        spim_bus_obj[i].spim_bus.parent.user_data = &spim_config[i];   /* SPI INSTANCE */
+        result = rt_spi_bus_register(&spim_bus_obj[i].spim_bus, spim_config[i].bus_name, &nrfx_spim_ops);
+        RT_ASSERT(result == RT_EOK);
+    }
+    return result;
+}
+
+int rt_hw_spim_init(void)
+{
+    return rt_hw_spim_bus_init();
+}
+
+INIT_BOARD_EXPORT(rt_hw_spim_init);
+
+#endif /* BSP_USING_SPIM0 || BSP_USING_SPIM1 || BSP_USING_SPIM2 || BSP_USING_SPIM3 */
+#endif /*BSP_USING_SPIM*/
+

+ 96 - 0
bsp/nrf5x/libraries/drivers/drv_spim.h

@@ -0,0 +1,96 @@
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+
+#ifndef __DRV_SPIM_H_
+#define __DRV_SPIM_H_
+
+#ifdef BSP_USING_SPIM
+
+#include "nrfx_spim.h"
+#include "nrf_spi.h"
+#include "rtconfig.h"
+
+struct spi_dma_message
+{
+    rt_base_t cs_pin;
+    unsigned cs_take;
+    unsigned cs_release;
+    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+    bool use_hw_ss;
+    #endif
+    bool ss_active_high;
+    struct rt_completion *cpt;
+    uint32_t flags;
+    NRF_SPIM_Type* spim;
+
+};
+
+/**
+ * @brief Attach the spi device to SPIM bus, this function must be used after initialization.
+ * @param bus_name     spim bus name  "spim0"/"spim1"/"spim2"/"spim3"
+ * @param device_name  spim device name "spim0x"/"spim1x"/"spim2x"/"spim3x"
+ * @param ss_pin       spim ss pin number
+ * @retval  -RT_ERROR / RT_EOK
+*/
+rt_err_t rt_hw_spim_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin);
+
+/* SPIM bus config */
+#ifdef BSP_USING_SPIM0
+#define NRFX_SPIM0_CONFIG         \
+{                                \
+    .bus_name = "spim0",          \
+    .spi = NRFX_SPIM_INSTANCE(0)  \
+}
+#endif
+#ifdef BSP_USING_SPIM1
+#define NRFX_SPIM1_CONFIG         \
+{                                \
+    .bus_name = "spim1",          \
+    .spi = NRFX_SPIM_INSTANCE(1)  \
+}
+#endif
+
+#ifdef BSP_USING_SPIM2
+#define NRFX_SPIM2_CONFIG         \
+{                                \
+    .bus_name = "spim2",          \
+    .spi = NRFX_SPIM_INSTANCE(2)  \
+}
+#endif
+
+#ifdef BSP_USING_SPIM3
+#define NRFX_SPIM3_CONFIG         \
+{                                \
+    .bus_name = "spim3",          \
+    .spi = NRFX_SPIM_INSTANCE(3)  \
+}
+#endif
+
+
+struct nrfx_drv_spim_config
+{
+    char *bus_name;
+    nrfx_spim_t spi;
+};
+
+struct nrfx_drv_spim
+{
+    nrfx_spim_t spim;    /* nrfx spim driver instance. */
+    nrfx_spim_config_t   spim_config; /* nrfx spim config Configuration */
+    struct rt_spi_configuration *cfg;
+    struct rt_spi_bus spim_bus;
+};
+
+struct nrfx_drv_spim_pin_config
+{
+    rt_uint8_t sck_pin;
+    rt_uint8_t mosi_pin;
+    rt_uint8_t miso_pin;
+    rt_uint8_t ss_pin;
+};
+
+#endif /* BSP_USING_SPIM */
+
+#endif /* __DRV_SPIM_H_ */
+

+ 8 - 3
bsp/nrf5x/libraries/drivers/drv_uart.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -53,12 +53,13 @@ static void uart0_event_hander(nrfx_uart_event_t const *p_event,void *p_context)
             m_uart0_cfg.rx_length = p_event->data.rxtx.bytes;
 
             /* rx_byte equal p_data  */
-            //m_uart0_cfg.rx_byte = *(p_event->data.rxtx.p_data);
+            /* m_uart0_cfg.rx_byte = *(p_event->data.rxtx.p_data); */
 
             rt_hw_serial_isr(m_uart0_cfg.serial, RT_SERIAL_EVENT_RX_IND);
         }
         nrfx_uart_rx(&(m_uart0_cfg.uart),&m_uart0_cfg.rx_byte,1);
     }
+
     if (p_event->type == NRFX_UART_EVT_TX_DONE)
     {
         /* @TODO:[RT_DEVICE_FLAG_INT_TX]*/
@@ -166,10 +167,12 @@ static rt_err_t _uart_ctrl(struct rt_serial_device *serial, int cmd, void *arg)
 
     return RT_EOK;
 }
+
 rt_weak int uart_putc_hook(rt_uint8_t *ch)
 {
     return -1;
 }
+
 static int _uart_putc(struct rt_serial_device *serial, char c)
 {
     drv_uart_cfg_t *instance = NULL;
@@ -187,7 +190,7 @@ static int _uart_putc(struct rt_serial_device *serial, char c)
     uart_putc_hook((rt_uint8_t *)&c);
     while (!nrf_uart_event_check(instance->uart.p_reg, NRF_UART_EVENT_TXDRDY))
     {
-        //wait for TXD send
+        /* wait for TXD send */
     }
     return rtn;
 }
@@ -207,6 +210,7 @@ static int _uart_getc(struct rt_serial_device *serial)
     {
         instance = (drv_uart_cfg_t*)serial->parent.user_data;
     }
+
     if(instance->rx_length)
     {
         ch = instance->rx_byte;
@@ -252,3 +256,4 @@ int rt_hw_uart_init(void)
     return result;
 }
 #endif /* BSP_USING_UART */
+

+ 3 - 1
bsp/nrf5x/libraries/drivers/drv_uarte.c

@@ -1,5 +1,5 @@
  /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -270,6 +270,7 @@ static int _uart_getc(struct rt_serial_device *serial)
     {
         p_cb = (drv_uart_cb_t*)serial->parent.user_data;
     }
+
     if(p_cb->rx_length)
     {
         ch = p_cb->rx_buffer[0];
@@ -331,3 +332,4 @@ int rt_hw_uart_init(void)
 }
 #endif /* defined(BSP_USING_UART0) || defined(BSP_USING_UART1) */
 #endif /* BSP_USING_UART */
+

+ 2 - 1
bsp/nrf5x/libraries/drivers/drv_uarte.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -31,3 +31,4 @@ void rt_hw_uart_init(void);
 #endif
 
 #endif /* __DRV_UART_H__ */
+

+ 2 - 1
bsp/nrf5x/libraries/drivers/drv_wdt.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2025, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -89,3 +89,4 @@ static int wdt_sample(int argc, char *argv[])
 MSH_CMD_EXPORT(wdt_sample, wdt sample);
 
 #endif /* RT_USING_WDT */
+

+ 1056 - 0
bsp/nrf5x/libraries/drivers/nrfx_spim.c

@@ -0,0 +1,1056 @@
+/*
+ * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <nrfx.h>
+#include <drivers/pin.h>
+
+#if NRFX_CHECK(NRFX_SPIM_ENABLED)
+
+#if !(NRFX_CHECK(NRFX_SPIM0_ENABLED) || NRFX_CHECK(NRFX_SPIM1_ENABLED) || \
+      NRFX_CHECK(NRFX_SPIM2_ENABLED) || NRFX_CHECK(NRFX_SPIM3_ENABLED) || \
+      NRFX_CHECK(NRFX_SPIM4_ENABLED))
+#error "No enabled SPIM instances. Check <nrfx_config.h>."
+#endif
+
+#include "drv_spim.h"
+
+#include <nrfx_spim.h>
+#include "prs/nrfx_prs.h"
+#include <hal/nrf_gpio.h>
+
+#define NRFX_LOG_MODULE SPIM
+#include <nrfx_log.h>
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) && \
+    ((!NRF_SPIM_HW_CSN_PRESENT) || !(NRF_SPIM_DCX_PRESENT) || !(NRF_SPIM_RXDELAY_PRESENT))
+#error "Extended options are not available in the SoC currently in use."
+#endif
+
+#define SPIMX_LENGTH_VALIDATE(peripheral, drv_inst_idx, rx_len, tx_len) \
+    (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+     NRFX_EASYDMA_LENGTH_VALIDATE(peripheral, rx_len, tx_len))
+
+#define SPIMX_HW_CSN_PRESENT_VALIDATE(peripheral, drv_inst_idx)         \
+    (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+     NRFX_CONCAT_2(peripheral, _FEATURE_HARDWARE_CSN_PRESENT))
+
+#define SPIMX_DCX_PRESENT_VALIDATE(peripheral, drv_inst_idx)            \
+    (((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) && \
+    NRFX_CONCAT_2(peripheral, _FEATURE_DCX_PRESENT))
+
+#define SPIMX_SUPPORTED_FREQ_VALIDATE(peripheral, drv_inst_idx, freq)                            \
+    (                                                                                            \
+    ((drv_inst_idx) == NRFX_CONCAT_3(NRFX_, peripheral, _INST_IDX)) &&                           \
+    (                                                                                            \
+        (((freq) != NRF_SPIM_FREQ_16M) && ((freq) != NRF_SPIM_FREQ_32M)) ||                      \
+        (((freq) == NRF_SPIM_FREQ_16M) && ((NRFX_CONCAT_2(peripheral, _MAX_DATARATE) >= 16))) || \
+        (((freq) == NRF_SPIM_FREQ_32M) && ((NRFX_CONCAT_2(peripheral, _MAX_DATARATE) >= 32)))    \
+    )                                                                                            \
+    )
+
+#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+#define SPIM0_LENGTH_VALIDATE(...)          SPIMX_LENGTH_VALIDATE(SPIM0, __VA_ARGS__)
+#define SPIM0_HW_CSN_PRESENT_VALIDATE(...)  SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM0, __VA_ARGS__)
+#define SPIM0_DCX_PRESENT_VALIDATE(...)     SPIMX_DCX_PRESENT_VALIDATE(SPIM0, __VA_ARGS__)
+#define SPIM0_SUPPORTED_FREQ_VALIDATE(...)  SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM0, __VA_ARGS__)
+#else
+#define SPIM0_LENGTH_VALIDATE(...)          0
+#define SPIM0_HW_CSN_PRESENT_VALIDATE(...)  0
+#define SPIM0_DCX_PRESENT_VALIDATE(...)     0
+#define SPIM0_SUPPORTED_FREQ_VALIDATE(...)  0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+#define SPIM1_LENGTH_VALIDATE(...)          SPIMX_LENGTH_VALIDATE(SPIM1, __VA_ARGS__)
+#define SPIM1_HW_CSN_PRESENT_VALIDATE(...)  SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM1, __VA_ARGS__)
+#define SPIM1_DCX_PRESENT_VALIDATE(...)     SPIMX_DCX_PRESENT_VALIDATE(SPIM1, __VA_ARGS__)
+#define SPIM1_SUPPORTED_FREQ_VALIDATE(...)  SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM1, __VA_ARGS__)
+#else
+#define SPIM1_LENGTH_VALIDATE(...)          0
+#define SPIM1_HW_CSN_PRESENT_VALIDATE(...)  0
+#define SPIM1_DCX_PRESENT_VALIDATE(...)     0
+#define SPIM1_SUPPORTED_FREQ_VALIDATE(...)  0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+#define SPIM2_LENGTH_VALIDATE(...)          SPIMX_LENGTH_VALIDATE(SPIM2, __VA_ARGS__)
+#define SPIM2_HW_CSN_PRESENT_VALIDATE(...)  SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM2, __VA_ARGS__)
+#define SPIM2_DCX_PRESENT_VALIDATE(...)     SPIMX_DCX_PRESENT_VALIDATE(SPIM2, __VA_ARGS__)
+#define SPIM2_SUPPORTED_FREQ_VALIDATE(...)  SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM2, __VA_ARGS__)
+#else
+#define SPIM2_LENGTH_VALIDATE(...)          0
+#define SPIM2_HW_CSN_PRESENT_VALIDATE(...)  0
+#define SPIM2_DCX_PRESENT_VALIDATE(...)     0
+#define SPIM2_SUPPORTED_FREQ_VALIDATE(...)  0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+#define SPIM3_LENGTH_VALIDATE(...)          SPIMX_LENGTH_VALIDATE(SPIM3, __VA_ARGS__)
+#define SPIM3_HW_CSN_PRESENT_VALIDATE(...)  SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM3, __VA_ARGS__)
+#define SPIM3_DCX_PRESENT_VALIDATE(...)     SPIMX_DCX_PRESENT_VALIDATE(SPIM3, __VA_ARGS__)
+#define SPIM3_SUPPORTED_FREQ_VALIDATE(...)  SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM3, __VA_ARGS__)
+#else
+#define SPIM3_LENGTH_VALIDATE(...)          0
+#define SPIM3_HW_CSN_PRESENT_VALIDATE(...)  0
+#define SPIM3_DCX_PRESENT_VALIDATE(...)     0
+#define SPIM3_SUPPORTED_FREQ_VALIDATE(...)  0
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM4_ENABLED)
+#define SPIM4_LENGTH_VALIDATE(...)          SPIMX_LENGTH_VALIDATE(SPIM4, __VA_ARGS__)
+#define SPIM4_HW_CSN_PRESENT_VALIDATE(...)  SPIMX_HW_CSN_PRESENT_VALIDATE(SPIM4, __VA_ARGS__)
+#define SPIM4_DCX_PRESENT_VALIDATE(...)     SPIMX_DCX_PRESENT_VALIDATE(SPIM4, __VA_ARGS__)
+#define SPIM4_SUPPORTED_FREQ_VALIDATE(...)  SPIMX_SUPPORTED_FREQ_VALIDATE(SPIM4, __VA_ARGS__)
+#else
+#define SPIM4_LENGTH_VALIDATE(...)          0
+#define SPIM4_HW_CSN_PRESENT_VALIDATE(...)  0
+#define SPIM4_DCX_PRESENT_VALIDATE(...)     0
+#define SPIM4_SUPPORTED_FREQ_VALIDATE(...)  0
+#endif
+
+#define SPIM_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len)  \
+    (SPIM0_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+     SPIM1_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+     SPIM2_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+     SPIM3_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len) || \
+     SPIM4_LENGTH_VALIDATE(drv_inst_idx, rx_len, tx_len))
+
+#define SPIM_HW_CSN_PRESENT_VALIDATE(drv_inst_idx)  \
+    (SPIM0_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM1_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM2_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM3_HW_CSN_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM4_HW_CSN_PRESENT_VALIDATE(drv_inst_idx))
+
+#define SPIM_DCX_PRESENT_VALIDATE(drv_inst_idx)  \
+    (SPIM0_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM1_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM2_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM3_DCX_PRESENT_VALIDATE(drv_inst_idx) || \
+     SPIM4_DCX_PRESENT_VALIDATE(drv_inst_idx))
+
+#define SPIM_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq)  \
+    (SPIM0_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
+     SPIM1_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
+     SPIM2_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
+     SPIM3_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq) || \
+     SPIM4_SUPPORTED_FREQ_VALIDATE(drv_inst_idx, freq))
+
+/* Requested pin can either match dedicated pin or be not connected at all. */
+#define SPIM_DEDICATED_PIN_VALIDATE(requested_pin, supported_pin) \
+    (((requested_pin) == NRFX_SPIM_PIN_NOT_USED) || ((requested_pin) == (supported_pin)))
+
+#if !defined(USE_WORKAROUND_FOR_ANOMALY_195) && \
+    defined(NRF52840_XXAA) && NRFX_CHECK(NRFX_SPIM3_ENABLED)
+/* Enable workaround for nRF52840 anomaly 195 (SPIM3 continues to draw current after disable). */
+#define USE_WORKAROUND_FOR_ANOMALY_195 1
+#endif
+
+
+/* Control block - driver instance local data. */
+typedef struct
+{
+    nrfx_spim_evt_handler_t handler;
+    void *                  p_context;
+    nrfx_spim_evt_t         evt;  /* Keep the struct that is ready for event handler. Less memcpy. */
+    nrfx_drv_state_t        state;
+    volatile bool           transfer_in_progress;
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+    bool                    use_hw_ss;
+#endif
+
+    /* [no need for 'volatile' attribute for the following members, as they */
+    /*  are not concurrently used in IRQ handlers and main line code] */
+    bool            ss_active_high;
+    uint8_t         ss_pin;
+    uint8_t         orc;
+
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+    size_t          tx_length;
+    size_t          rx_length;
+#endif
+} spim_control_block_t;
+static spim_control_block_t m_cb[NRFX_SPIM_ENABLED_COUNT];
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+
+/* Workaround for nRF52840 anomaly 198: SPIM3 transmit data might be corrupted. */
+
+static uint32_t m_anomaly_198_preserved_value;
+
+static void anomaly_198_enable(uint8_t const * p_buffer, size_t buf_len)
+{
+    m_anomaly_198_preserved_value = *((volatile uint32_t *)0x40000E00);
+
+    if (buf_len == 0)
+    {
+        return;
+    }
+    uint32_t buffer_end_addr = ((uint32_t)p_buffer) + buf_len;
+    uint32_t block_addr      = ((uint32_t)p_buffer) & ~0x1FFF;
+    uint32_t block_flag      = (1UL << ((block_addr >> 13) & 0xFFFF));
+    uint32_t occupied_blocks = 0;
+
+    if (block_addr >= 0x20010000)
+    {
+        occupied_blocks = (1UL << 8);
+    }
+    else
+    {
+        do {
+            occupied_blocks |= block_flag;
+            block_flag <<= 1;
+            block_addr  += 0x2000;
+        } while ((block_addr < buffer_end_addr) && (block_addr < 0x20012000));
+    }
+
+    *((volatile uint32_t *)0x40000E00) = occupied_blocks;
+}
+
+static void anomaly_198_disable(void)
+{
+    *((volatile uint32_t *)0x40000E00) = m_anomaly_198_preserved_value;
+}
+#endif /* NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED) */
+
+static void spim_abort(NRF_SPIM_Type * p_spim, spim_control_block_t * p_cb)
+{
+    nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_STOP);
+    bool stopped;
+    NRFX_WAIT_FOR(nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STOPPED), 100, 1, stopped);
+    if (!stopped)
+    {
+        NRFX_LOG_ERROR("Failed to stop instance with base address: %p.", (void *)p_spim);
+    }
+    p_cb->transfer_in_progress = false;
+}
+
+nrfx_err_t nrfx_spim_init(nrfx_spim_t const *        p_instance,
+                          nrfx_spim_config_t const * p_config,
+                          nrfx_spim_evt_handler_t    handler,
+                          void *                     p_context)
+{
+    NRFX_ASSERT(p_config);
+    spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    nrfx_err_t err_code;
+
+    if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
+    {
+        err_code = NRFX_ERROR_INVALID_STATE;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+    /* Check if SPIM instance supports the extended features. */
+    if (
+        (!SPIM_SUPPORTED_FREQ_VALIDATE(p_instance->drv_inst_idx, p_config->frequency)) ||
+        ((p_config->use_hw_ss) &&
+         !SPIM_HW_CSN_PRESENT_VALIDATE(p_instance->drv_inst_idx)) ||
+        ((p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED) &&
+         !SPIM_DCX_PRESENT_VALIDATE(p_instance->drv_inst_idx))
+        )
+    {
+        err_code = NRFX_ERROR_NOT_SUPPORTED;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+#endif
+
+    NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+
+#if NRF_SPIM_HAS_32_MHZ_FREQ && defined(NRF5340_XXAA_APPLICATION)
+    /* Check if dedicated SPIM pins are used. */
+    if ((p_spim == NRF_SPIM4) && (p_config->frequency == NRF_SPIM_FREQ_32M))
+    {
+        enum {
+            SPIM_SCK_DEDICATED  = NRF_GPIO_PIN_MAP(0, 8),
+            SPIM_MOSI_DEDICATED = NRF_GPIO_PIN_MAP(0, 9),
+            SPIM_MISO_DEDICATED = NRF_GPIO_PIN_MAP(0, 10),
+            SPIM_CSN_DEDICATED  = NRF_GPIO_PIN_MAP(0, 11),
+            SPIM_DCX_DEDICATED  = NRF_GPIO_PIN_MAP(0, 12),
+        };
+
+        if (!SPIM_DEDICATED_PIN_VALIDATE(p_config->sck_pin, SPIM_SCK_DEDICATED) ||
+            !SPIM_DEDICATED_PIN_VALIDATE(p_config->ss_pin,  SPIM_CSN_DEDICATED) ||
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+            !SPIM_DEDICATED_PIN_VALIDATE(p_config->dcx_pin, SPIM_DCX_DEDICATED) ||
+#endif
+            !SPIM_DEDICATED_PIN_VALIDATE(p_config->mosi_pin, SPIM_MOSI_DEDICATED) ||
+            !SPIM_DEDICATED_PIN_VALIDATE(p_config->miso_pin, SPIM_MISO_DEDICATED))
+        {
+            err_code = NRFX_ERROR_INVALID_PARAM;
+            NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                             __func__,
+                             NRFX_LOG_ERROR_STRING_GET(err_code));
+            return err_code;
+        }
+    }
+#endif
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+    static nrfx_irq_handler_t const irq_handlers[NRFX_SPIM_ENABLED_COUNT] = {
+        #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+        nrfx_spim_0_irq_handler,
+        #endif
+        #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+        nrfx_spim_1_irq_handler,
+        #endif
+        #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+        nrfx_spim_2_irq_handler,
+        #endif
+        #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+        nrfx_spim_3_irq_handler,
+        #endif
+        #if NRFX_CHECK(NRFX_SPIM4_ENABLED)
+        nrfx_spim_4_irq_handler,
+        #endif
+    };
+    if (nrfx_prs_acquire(p_instance->p_reg,
+            irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
+    {
+        err_code = NRFX_ERROR_BUSY;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+#endif /* NRFX_CHECK(NRFX_PRS_ENABLED) */
+
+    p_cb->handler = handler;
+    p_cb->p_context = p_context;
+
+    uint32_t mosi_pin;
+    uint32_t miso_pin;
+    /* Configure pins used by the peripheral: */
+    /* - SCK - output with initial value corresponding with the SPI mode used: */
+    /*   0 - for modes 0 and 1 (CPOL = 0), 1 - for modes 2 and 3 (CPOL = 1); */
+    /*   according to the reference manual guidelines this pin and its input */
+    /*   buffer must always be connected for the SPI to work. */
+    if (p_config->mode <= NRF_SPIM_MODE_1)
+    {
+        nrf_gpio_pin_clear(p_config->sck_pin);
+    }
+    else
+    {
+        nrf_gpio_pin_set(p_config->sck_pin);
+    }
+
+    nrf_gpio_pin_drive_t pin_drive;
+    /* Configure pin drive - high drive for 32 MHz clock frequency. */
+#if NRF_SPIM_HAS_32_MHZ_FREQ
+    pin_drive = (p_config->frequency == NRF_SPIM_FREQ_32M) ? NRF_GPIO_PIN_H0H1 : NRF_GPIO_PIN_S0S1;
+#else
+    pin_drive = NRF_GPIO_PIN_S0S1;
+#endif
+
+    nrf_gpio_cfg(p_config->sck_pin,
+                 NRF_GPIO_PIN_DIR_OUTPUT,
+                 NRF_GPIO_PIN_INPUT_CONNECT,
+                 NRF_GPIO_PIN_NOPULL,
+                 pin_drive,
+                 NRF_GPIO_PIN_NOSENSE);
+    /* - MOSI (optional) - output with initial value 0, */
+    if (p_config->mosi_pin != NRFX_SPIM_PIN_NOT_USED)
+    {
+        mosi_pin = p_config->mosi_pin;
+        nrf_gpio_pin_clear(mosi_pin);
+        nrf_gpio_cfg(mosi_pin,
+                     NRF_GPIO_PIN_DIR_OUTPUT,
+                     NRF_GPIO_PIN_INPUT_DISCONNECT,
+                     NRF_GPIO_PIN_NOPULL,
+                     pin_drive,
+                     NRF_GPIO_PIN_NOSENSE);
+    }
+    else
+    {
+        mosi_pin = NRF_SPIM_PIN_NOT_CONNECTED;
+    }
+    /* - MISO (optional) - input, */
+    if (p_config->miso_pin != NRFX_SPIM_PIN_NOT_USED)
+    {
+        miso_pin = p_config->miso_pin;
+        nrf_gpio_cfg(miso_pin,
+                     NRF_GPIO_PIN_DIR_INPUT,
+                     NRF_GPIO_PIN_INPUT_CONNECT,
+                     p_config->miso_pull,
+                     pin_drive,
+                     NRF_GPIO_PIN_NOSENSE);
+    }
+    else
+    {
+        miso_pin = NRF_SPIM_PIN_NOT_CONNECTED;
+    }
+    /* - Slave Select (optional) - output with initial value 1 (inactive). */
+
+    /* 'p_cb->ss_pin' variable is used during transfers to check if SS pin should be toggled, */
+    /* so this field needs to be initialized even if the pin is not used. */
+    p_cb->ss_pin = p_config->ss_pin;
+
+    if (p_config->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+    {
+        if (p_config->ss_active_high)
+        {
+            nrf_gpio_pin_clear(p_config->ss_pin);
+        }
+        else
+        {
+            nrf_gpio_pin_set(p_config->ss_pin);
+        }
+        nrf_gpio_cfg(p_config->ss_pin,
+                     NRF_GPIO_PIN_DIR_OUTPUT,
+                     NRF_GPIO_PIN_INPUT_DISCONNECT,
+                     NRF_GPIO_PIN_NOPULL,
+                     pin_drive,
+                     NRF_GPIO_PIN_NOSENSE);
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+        if (p_config->use_hw_ss)
+        {
+            p_cb->use_hw_ss = p_config->use_hw_ss;
+            nrf_spim_csn_configure(p_spim,
+                                   p_config->ss_pin,
+                                   (p_config->ss_active_high == true ?
+                                        NRF_SPIM_CSN_POL_HIGH : NRF_SPIM_CSN_POL_LOW),
+                                   p_config->ss_duration);
+        }
+#endif
+        p_cb->ss_active_high = p_config->ss_active_high;
+    }
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+    /* - DCX (optional) - output. */
+    if (p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED)
+    {
+        nrf_gpio_pin_set(p_config->dcx_pin);
+        nrf_gpio_cfg(p_config->dcx_pin,
+                     NRF_GPIO_PIN_DIR_OUTPUT,
+                     NRF_GPIO_PIN_INPUT_DISCONNECT,
+                     NRF_GPIO_PIN_NOPULL,
+                     pin_drive,
+                     NRF_GPIO_PIN_NOSENSE);
+        nrf_spim_dcx_pin_set(p_spim, p_config->dcx_pin);
+    }
+
+    /* Change rx delay */
+    nrf_spim_iftiming_set(p_spim, p_config->rx_delay);
+#endif
+
+    nrf_spim_pins_set(p_spim, p_config->sck_pin, mosi_pin, miso_pin);
+    nrf_spim_frequency_set(p_spim, p_config->frequency);
+    nrf_spim_configure(p_spim, p_config->mode, p_config->bit_order);
+
+    nrf_spim_orc_set(p_spim, p_config->orc);
+
+    nrf_spim_enable(p_spim);
+
+    if (p_cb->handler)
+    {
+        NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg),
+            p_config->irq_priority);
+        NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
+    }
+
+    p_cb->transfer_in_progress = false;
+    p_cb->state = NRFX_DRV_STATE_INITIALIZED;
+
+    err_code = NRFX_SUCCESS;
+    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+    return err_code;
+}
+
+static void spim_pin_uninit(uint32_t pin)
+{
+    if (pin == NRF_SPIM_PIN_NOT_CONNECTED)
+    {
+        return;
+    }
+
+    nrf_gpio_cfg_default(pin);
+}
+
+void nrfx_spim_uninit(nrfx_spim_t const * p_instance)
+{
+    spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+    NRF_SPIM_Type * p_spim = p_instance->p_reg;
+
+    if (p_cb->handler)
+    {
+        NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
+        nrf_spim_int_disable(p_spim, NRF_SPIM_ALL_INTS_MASK);
+        if (p_cb->transfer_in_progress)
+        {
+            /* Ensure that SPI is not performing any transfer. */
+            spim_abort(p_spim, p_cb);
+        }
+    }
+
+    nrf_spim_disable(p_spim);
+
+    spim_pin_uninit(nrf_spim_sck_pin_get(p_spim));
+    spim_pin_uninit(nrf_spim_miso_pin_get(p_spim));
+    spim_pin_uninit(nrf_spim_mosi_pin_get(p_spim));
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+    if (SPIM_DCX_PRESENT_VALIDATE(p_instance->drv_inst_idx))
+    {
+        spim_pin_uninit(nrf_spim_dcx_pin_get(p_spim));
+    }
+#endif
+    if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+    {
+        nrf_gpio_cfg_default(p_cb->ss_pin);
+    }
+
+#if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_195)
+    if (p_spim == NRF_SPIM3)
+    {
+        *(volatile uint32_t *)0x4002F004 = 1;
+    }
+#endif
+
+#if NRFX_CHECK(NRFX_PRS_ENABLED)
+    nrfx_prs_release(p_instance->p_reg);
+#endif
+
+    p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
+}
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const *           p_instance,
+                              nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                              uint32_t                      flags,
+                              uint8_t                       cmd_length)
+{
+    (void)flags;
+
+    NRFX_ASSERT(cmd_length <= NRF_SPIM_DCX_CNT_ALL_CMD);
+    nrf_spim_dcx_cnt_set((NRF_SPIM_Type *)p_instance->p_reg, cmd_length);
+    return nrfx_spim_xfer(p_instance, p_xfer_desc, 0);
+}
+#endif
+
+
+static void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable);
+
+static void finish_transfer(spim_control_block_t * p_cb)
+{
+    struct spi_dma_message *mess = (struct spi_dma_message*)(p_cb->p_context);
+    if (mess->cs_pin != PIN_NONE && mess->cs_release)
+    {
+    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+        if (!mess->use_hw_ss)
+    #endif
+        {
+            if (mess->ss_active_high)
+            {
+                nrf_gpio_pin_clear(mess->cs_pin);
+            }
+            else
+            {
+                nrf_gpio_pin_set(mess->cs_pin);
+            }
+        }
+    }
+    /* By clearing this flag before calling the handler we allow subsequent */
+    /* transfers to be started directly from the handler function. */
+    p_cb->transfer_in_progress = false;
+
+    p_cb->evt.type = NRFX_SPIM_EVENT_DONE;
+    p_cb->handler(&p_cb->evt, p_cb->p_context);
+
+    spim_int_enable(mess->spim, ((mess->flags) & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
+    rt_completion_done(mess->cpt);
+}
+
+static void spim_int_enable(NRF_SPIM_Type * p_spim, bool enable)
+{
+    if (!enable)
+    {
+        nrf_spim_int_disable(p_spim, NRF_SPIM_INT_END_MASK);
+    }
+    else
+    {
+        nrf_spim_int_enable(p_spim, NRF_SPIM_INT_END_MASK);
+    }
+}
+
+static void spim_list_enable_handle(NRF_SPIM_Type * p_spim, uint32_t flags)
+{
+    if (NRFX_SPIM_FLAG_TX_POSTINC & flags)
+    {
+        nrf_spim_tx_list_enable(p_spim);
+    }
+    else
+    {
+        nrf_spim_tx_list_disable(p_spim);
+    }
+
+    if (NRFX_SPIM_FLAG_RX_POSTINC & flags)
+    {
+        nrf_spim_rx_list_enable(p_spim);
+    }
+    else
+    {
+        nrf_spim_rx_list_disable(p_spim);
+    }
+}
+
+static nrfx_err_t spim_xfer(NRF_SPIM_Type               * p_spim,
+                            spim_control_block_t        * p_cb,
+                            nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                            uint32_t                      flags)
+{
+    nrfx_err_t err_code;
+    /* EasyDMA requires that transfer buffers are placed in Data RAM region; */
+    /* signal error if they are not. */
+    if ((p_xfer_desc->p_tx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_tx_buffer)) ||
+        (p_xfer_desc->p_rx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_rx_buffer)))
+    {
+        p_cb->transfer_in_progress = false;
+        err_code = NRFX_ERROR_INVALID_ADDR;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+    p_cb->tx_length = 0;
+    p_cb->rx_length = 0;
+#endif
+
+    nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
+    nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length);
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+    if (p_spim == NRF_SPIM3)
+    {
+        anomaly_198_enable(p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
+    }
+#endif
+
+    nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+
+    spim_list_enable_handle(p_spim, flags);
+
+    if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
+    {
+        nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+    }
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+    if (flags & NRFX_SPIM_FLAG_HOLD_XFER)
+    {
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
+        p_cb->tx_length = p_xfer_desc->tx_length;
+        p_cb->rx_length = p_xfer_desc->rx_length;
+        nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0);
+        nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0);
+        nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK);
+    }
+#endif
+
+    if (!p_cb->handler)
+    {
+        if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
+        {
+            while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
+            {}
+        }
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+        if (p_spim == NRF_SPIM3)
+        {
+            anomaly_198_disable();
+        }
+#endif
+        if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+        {
+    #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+            if (!p_cb->use_hw_ss)
+    #endif
+            {
+                if (p_cb->ss_active_high)
+                {
+                    nrf_gpio_pin_clear(p_cb->ss_pin);
+                }
+                else
+                {
+                    nrf_gpio_pin_set(p_cb->ss_pin);
+                }
+            }
+        }
+    }
+    else
+    {
+        spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
+    }
+    err_code = NRFX_SUCCESS;
+    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+    return err_code;
+}
+
+nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const *           p_instance,
+                          nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                          uint32_t                      flags)
+{
+    spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+    NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
+    NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
+    NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
+                                     p_xfer_desc->rx_length,
+                                     p_xfer_desc->tx_length));
+    NRFX_ASSERT(!(flags & NRFX_SPIM_FLAG_HOLD_XFER) ||
+                (p_cb->ss_pin == NRFX_SPIM_PIN_NOT_USED));
+
+    nrfx_err_t err_code = NRFX_SUCCESS;
+
+    if (p_cb->transfer_in_progress)
+    {
+        err_code = NRFX_ERROR_BUSY;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+    else
+    {
+        if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
+                                        NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
+        {
+            p_cb->transfer_in_progress = true;
+        }
+    }
+
+    p_cb->evt.xfer_desc = *p_xfer_desc;
+
+    if (p_cb->ss_pin != NRFX_SPIM_PIN_NOT_USED)
+    {
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+        if (!p_cb->use_hw_ss)
+#endif
+        {
+            if (p_cb->ss_active_high)
+            {
+                nrf_gpio_pin_set(p_cb->ss_pin);
+            }
+            else
+            {
+                nrf_gpio_pin_clear(p_cb->ss_pin);
+            }
+        }
+    }
+
+    return spim_xfer(p_instance->p_reg, p_cb,  p_xfer_desc, flags);
+}
+
+
+static nrfx_err_t rtt_spim_xfer(NRF_SPIM_Type           * p_spim,
+                            spim_control_block_t        * p_cb,
+                            nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                            uint32_t                      flags,
+                            struct rt_spi_message       * message,
+                            struct rt_spi_device        * dev)
+{
+    nrfx_err_t err_code;
+    /* EasyDMA requires that transfer buffers are placed in Data RAM region; */
+    /* signal error if they are not. */
+    if ((p_xfer_desc->p_tx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_tx_buffer)) ||
+        (p_xfer_desc->p_rx_buffer != NULL && !nrfx_is_in_ram(p_xfer_desc->p_rx_buffer)))
+    {
+        p_cb->transfer_in_progress = false;
+        err_code = NRFX_ERROR_INVALID_ADDR;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+
+    struct spi_dma_message *mess = (struct spi_dma_message *)(p_cb->p_context);
+    mess->cs_take = message->cs_take;
+    mess->cs_release = message->cs_release;
+    mess->flags = flags;
+    mess->spim = p_spim;
+
+    nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+
+    #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+        p_cb->tx_length = 0;
+        p_cb->rx_length = 0;
+    #endif
+
+    nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
+    nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, p_xfer_desc->rx_length);
+
+    #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+        if (p_spim == NRF_SPIM3)
+        {
+            anomaly_198_enable(p_xfer_desc->p_tx_buffer, p_xfer_desc->tx_length);
+        }
+    #endif
+
+    spim_list_enable_handle(p_spim, flags);
+
+    if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
+    {
+        nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+/*      rt_kprintf("SPIM task started.\n"); */
+    }
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+    if (flags & NRFX_SPIM_FLAG_HOLD_XFER)
+    {
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
+        p_cb->tx_length = p_xfer_desc->tx_length;
+        p_cb->rx_length = p_xfer_desc->rx_length;
+        nrf_spim_tx_buffer_set(p_spim, p_xfer_desc->p_tx_buffer, 0);
+        nrf_spim_rx_buffer_set(p_spim, p_xfer_desc->p_rx_buffer, 0);
+        nrf_spim_int_enable(p_spim, NRF_SPIM_INT_STARTED_MASK);
+    }
+#endif
+
+    if (p_cb->handler == RT_NULL || (p_xfer_desc->rx_length<= 20 && p_xfer_desc->tx_length<= 20))
+    {
+        /* no cb func or lenth < 20, wait for transfer end */
+/*      spim_int_enable(p_spim, ((mess->flags) & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)); */
+        if (!(flags & NRFX_SPIM_FLAG_HOLD_XFER))
+        {
+            while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
+            {
+
+            }
+/*          rt_kprintf("SPIM transfer end.\n"); */
+             p_cb->transfer_in_progress = false;
+        }
+
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+        if (p_spim == NRF_SPIM3)
+        {
+            anomaly_198_disable();
+        }
+#endif
+
+        if (dev->cs_pin != PIN_NONE && message->cs_release)
+        {
+        #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+            if (!p_cb->use_hw_ss)
+        #endif
+            {
+                if (p_cb->ss_active_high)
+                    nrf_gpio_pin_clear(dev->cs_pin);
+                else
+                    nrf_gpio_pin_set(dev->cs_pin);
+            }
+        }
+    }
+    else
+    {
+        spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER));
+        p_cb->transfer_in_progress = false;
+        if (rt_completion_wait(mess->cpt, 5000) != RT_EOK)
+            {
+                rt_kprintf("wait for DMA interrupt overtime!");
+                return NRFX_ERROR_TIMEOUT;
+            }
+    }
+    err_code = NRFX_SUCCESS;
+    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
+    return err_code;
+}
+
+nrfx_err_t rtt_nrfx_spim_xfer(nrfx_spim_t const         *p_instance,
+                            nrfx_spim_xfer_desc_t const *p_xfer_desc,
+                            uint32_t                     flags,
+                            struct rt_spi_message       *message,
+                            struct rt_spi_device        *dev)
+{
+    spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+    NRFX_ASSERT(p_xfer_desc->p_tx_buffer != NULL || p_xfer_desc->tx_length == 0);
+    NRFX_ASSERT(p_xfer_desc->p_rx_buffer != NULL || p_xfer_desc->rx_length == 0);
+    NRFX_ASSERT(SPIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,
+                                     p_xfer_desc->rx_length,
+                                     p_xfer_desc->tx_length));
+    NRFX_ASSERT(!(flags & NRFX_SPIM_FLAG_HOLD_XFER) ||
+                (p_cb->ss_pin == NRFX_SPIM_PIN_NOT_USED));
+
+    nrfx_err_t err_code = NRFX_SUCCESS;
+
+    if (p_cb->transfer_in_progress)
+    {
+        err_code = NRFX_ERROR_BUSY;
+        NRFX_LOG_WARNING("Function: %s, error code: %s.",
+                         __func__,
+                         NRFX_LOG_ERROR_STRING_GET(err_code));
+        return err_code;
+    }
+    else
+    {
+        if (p_cb->handler && !(flags & (NRFX_SPIM_FLAG_REPEATED_XFER |
+                                        NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)))
+        {
+            p_cb->transfer_in_progress = true;
+        }
+    }
+
+    p_cb->evt.xfer_desc = *p_xfer_desc;
+
+    if (dev->cs_pin != PIN_NONE && message->cs_take)
+    {
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED)
+        if (!p_cb->use_hw_ss && message->cs_take)
+#endif
+        {
+            if (p_cb->ss_active_high)
+            {
+                nrf_gpio_pin_set(dev->cs_pin);
+            }
+            else
+            {
+                nrf_gpio_pin_clear(dev->cs_pin);
+            }
+        }
+    }
+
+    return rtt_spim_xfer(p_instance->p_reg, p_cb, p_xfer_desc, flags, message, dev);
+}
+
+void nrfx_spim_abort(nrfx_spim_t const * p_instance)
+{
+    spim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
+    NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
+
+    spim_abort(p_instance->p_reg, p_cb);
+}
+
+uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance)
+{
+    NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+    return nrf_spim_task_address_get(p_spim, NRF_SPIM_TASK_START);
+}
+
+uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance)
+{
+    NRF_SPIM_Type * p_spim = (NRF_SPIM_Type *)p_instance->p_reg;
+    return nrf_spim_event_address_get(p_spim, NRF_SPIM_EVENT_END);
+}
+
+static void irq_handler(NRF_SPIM_Type * p_spim, spim_control_block_t * p_cb)
+{
+#if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
+    if ((nrf_spim_int_enable_check(p_spim, NRF_SPIM_INT_STARTED_MASK)) &&
+        (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_STARTED)) )
+    {
+        /* Handle first, zero-length, auxiliary transmission. */
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_STARTED);
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+
+        NRFX_ASSERT(p_spim->TXD.MAXCNT == 0);
+        p_spim->TXD.MAXCNT = p_cb->tx_length;
+
+        NRFX_ASSERT(p_spim->RXD.MAXCNT == 0);
+        p_spim->RXD.MAXCNT = p_cb->rx_length;
+
+        /* Disable STARTED interrupt, used only in auxiliary transmission. */
+        nrf_spim_int_disable(p_spim, NRF_SPIM_INT_STARTED_MASK);
+
+        /* Start the actual, glitch-free transmission. */
+        nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
+        return;
+    }
+#endif
+
+    if (nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END))
+    {
+#if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED)
+        if (p_spim == NRF_SPIM3)
+        {
+            anomaly_198_disable();
+        }
+#endif
+        nrf_spim_event_clear(p_spim, NRF_SPIM_EVENT_END);
+        NRFX_ASSERT(p_cb->handler);
+        NRFX_LOG_DEBUG("Event: NRF_SPIM_EVENT_END.");
+        finish_transfer(p_cb);
+    }
+}
+
+#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+void nrfx_spim_0_irq_handler(void)
+{
+    irq_handler(NRF_SPIM0, &m_cb[NRFX_SPIM0_INST_IDX]);
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+void nrfx_spim_1_irq_handler(void)
+{
+    rt_interrupt_enter();
+    irq_handler(NRF_SPIM1, &m_cb[NRFX_SPIM1_INST_IDX]);
+    rt_interrupt_leave();
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+void nrfx_spim_2_irq_handler(void)
+{
+    rt_interrupt_enter();
+    irq_handler(NRF_SPIM2, &m_cb[NRFX_SPIM2_INST_IDX]);
+    rt_interrupt_leave();
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+void nrfx_spim_3_irq_handler(void)
+{
+    rt_interrupt_enter();
+    irq_handler(NRF_SPIM3, &m_cb[NRFX_SPIM3_INST_IDX]);
+    rt_interrupt_leave();
+}
+#endif
+
+#if NRFX_CHECK(NRFX_SPIM4_ENABLED)
+void nrfx_spim_4_irq_handler(void)
+{
+    rt_interrupt_enter();
+    irq_handler(NRF_SPIM4, &m_cb[NRFX_SPIM4_INST_IDX]);
+    rt_interrupt_leave();
+}
+#endif
+
+#endif /* NRFX_CHECK(NRFX_SPIM_ENABLED) */
+

+ 423 - 0
bsp/nrf5x/libraries/drivers/nrfx_spim.h

@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NRFX_SPIM_H__
+#define NRFX_SPIM_H__
+
+#include <stdint.h>
+#include <string.h>
+#include "board.h"
+#include "rtconfig.h"
+
+#include <nrfx.h>
+#include <hal/nrf_spim.h>
+#include <hal/nrf_gpio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrfx_spim SPIM driver
+ * @{
+ * @ingroup nrf_spim
+ * @brief   Serial Peripheral Interface Master with EasyDMA (SPIM) driver.
+ */
+
+/** @brief Data structure of the Serial Peripheral Interface Master with EasyDMA (SPIM) driver instance. */
+typedef struct
+{
+    NRF_SPIM_Type * p_reg;        /* /< Pointer to a structure with SPIM registers. */
+    uint8_t         drv_inst_idx; /* /< Index of the driver instance. For internal use only. */
+} nrfx_spim_t;
+
+#ifndef __NRFX_DOXYGEN__
+enum {
+#if NRFX_CHECK(NRFX_SPIM0_ENABLED)
+    NRFX_SPIM0_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM1_ENABLED)
+    NRFX_SPIM1_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM2_ENABLED)
+    NRFX_SPIM2_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM3_ENABLED)
+    NRFX_SPIM3_INST_IDX,
+#endif
+#if NRFX_CHECK(NRFX_SPIM4_ENABLED)
+    NRFX_SPIM4_INST_IDX,
+#endif
+    NRFX_SPIM_ENABLED_COUNT
+};
+#endif
+
+/** @brief Macro for creating an instance of the SPIM driver. */
+#define NRFX_SPIM_INSTANCE(id)                               \
+{                                                            \
+    .p_reg        = NRFX_CONCAT_2(NRF_SPIM, id),             \
+    .drv_inst_idx = NRFX_CONCAT_3(NRFX_SPIM, id, _INST_IDX), \
+}
+
+/**
+ * @brief This value can be provided instead of a pin number for signals MOSI,
+ *        MISO, and Slave Select to specify that the given signal is not used and
+ *        therefore does not need to be connected to a pin.
+ */
+#define NRFX_SPIM_PIN_NOT_USED  0xFF
+
+/** @brief Configuration structure of the SPIM driver instance. */
+typedef struct
+{
+    uint8_t               sck_pin;        /* /< SCK pin number. */
+    uint8_t               mosi_pin;       /* /< MOSI pin number (optional). */
+                                          /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
+                                           *   if this signal is not needed. */
+    uint8_t               miso_pin;       /* /< MISO pin number (optional). */
+                                          /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
+                                           *   if this signal is not needed. */
+    uint8_t               ss_pin;         /* /< Slave Select pin number (optional). */
+                                          /**< Set to @ref NRFX_SPIM_PIN_NOT_USED
+                                           *   if this signal is not needed. */
+    bool                  ss_active_high; /* /< Polarity of the Slave Select pin during transmission. */
+    uint8_t               irq_priority;   /* /< Interrupt priority. */
+    uint8_t               orc;            /* /< Overrun character. */
+                                          /**< This character is used when all bytes from the TX buffer are sent,
+                                               but the transfer continues due to RX. */
+    nrf_spim_frequency_t frequency;       /* /< SPIM frequency. */
+    nrf_spim_mode_t      mode;            /* /< SPIM mode. */
+    nrf_spim_bit_order_t bit_order;       /* /< SPIM bit order. */
+    nrf_gpio_pin_pull_t  miso_pull;       /* /< MISO pull up configuration. */
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
+    uint8_t              dcx_pin;         /* /< D/CX pin number (optional). */
+    uint8_t              rx_delay;        /* /< Sample delay for input serial data on MISO. */
+                                          /**< The value specifies the delay, in number of 64 MHz clock cycles
+                                           *   (15.625 ns), from the the sampling edge of SCK (leading edge for
+                                           *   CONFIG.CPHA = 0, trailing edge for CONFIG.CPHA = 1) until
+                                           *   the input serial data is sampled. */
+    bool                 use_hw_ss;       /* /< Indication to use software or hardware controlled Slave Select pin. */
+    uint8_t              ss_duration;     /* /< Slave Select duration before and after transmission. */
+                                          /**< Minimum duration between the edge of CSN and the edge of SCK.
+                                           *   Also, minimum duration of CSN inactivity between transactions.
+                                           *   The value is specified in number of 64 MHz clock cycles (15.625 ns).
+                                           *   Supported only for hardware-controlled Slave Select. */
+#endif
+} nrfx_spim_config_t;
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief SPIM driver extended default configuration.
+ *
+ * This configuration sets up SPIM additional options with the following values:
+ * - DCX pin disabled
+ * - RX sampling delay: 2 clock cycles
+ * - hardware SS disabled
+ * - hardware SS duration before and after transmission: 2 clock cycles
+ */
+#define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG   \
+    .dcx_pin      = NRFX_SPIM_PIN_NOT_USED, \
+    .rx_delay     = 0x02,                   \
+    .use_hw_ss    = false,                  \
+    .ss_duration  = 0x02,
+#else
+    #define NRFX_SPIM_DEFAULT_EXTENDED_CONFIG
+#endif
+
+/**
+ * @brief SPIM driver default configuration.
+ *
+ * This configuration sets up SPIM with the following options:
+ * - SS pin active low
+ * - over-run character set to 0xFF
+ * - clock frequency: 4 MHz
+ * - mode: 0 (SCK active high, sample on leading edge of the clock signal;)
+ * - MSB shifted out first
+ * - MISO pull-up disabled
+ *
+ * @param[in] _pin_sck  SCK pin.
+ * @param[in] _pin_mosi MOSI pin.
+ * @param[in] _pin_miso MISO pin.
+ * @param[in] _pin_ss   SS pin.
+ */
+#define NRFX_SPIM_DEFAULT_CONFIG(_pin_sck, _pin_mosi, _pin_miso, _pin_ss)   \
+{                                                                           \
+    .sck_pin        = _pin_sck,                                             \
+    .mosi_pin       = _pin_mosi,                                            \
+    .miso_pin       = _pin_miso,                                            \
+    .ss_pin         = _pin_ss,                                              \
+    .ss_active_high = false,                                                \
+    .irq_priority   = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY,                \
+    .orc            = 0xFF,                                                 \
+    .frequency      = NRF_SPIM_FREQ_4M,                                     \
+    .mode           = NRF_SPIM_MODE_0,                                      \
+    .bit_order      = NRF_SPIM_BIT_ORDER_MSB_FIRST,                         \
+    .miso_pull      = NRF_GPIO_PIN_NOPULL,                                  \
+    NRFX_SPIM_DEFAULT_EXTENDED_CONFIG                                       \
+}
+
+/** @brief Flag indicating that TX buffer address will be incremented after transfer. */
+#define NRFX_SPIM_FLAG_TX_POSTINC          (1UL << 0)
+/** @brief Flag indicating that RX buffer address will be incremented after transfer. */
+#define NRFX_SPIM_FLAG_RX_POSTINC          (1UL << 1)
+/** @brief Flag indicating that the interrupt after each transfer will be suppressed, and the event handler will not be called. */
+#define NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER (1UL << 2)
+/** @brief Flag indicating that the transfer will be set up, but not started. */
+#define NRFX_SPIM_FLAG_HOLD_XFER           (1UL << 3)
+/** @brief Flag indicating that the transfer will be executed multiple times. */
+#define NRFX_SPIM_FLAG_REPEATED_XFER       (1UL << 4)
+
+/** @brief Single transfer descriptor structure. */
+typedef struct
+{
+    uint8_t const * p_tx_buffer; /* /< Pointer to TX buffer. */
+    size_t          tx_length;   /* /< TX buffer length. */
+    uint8_t       * p_rx_buffer; /* /< Pointer to RX buffer. */
+    size_t          rx_length;   /* /< RX buffer length. */
+} nrfx_spim_xfer_desc_t;
+
+/**
+ * @brief Macro for setting up single transfer descriptor.
+ *
+ * This macro is for internal use only.
+ */
+#define NRFX_SPIM_SINGLE_XFER(p_tx, tx_len, p_rx, rx_len) \
+    {                                                     \
+    .p_tx_buffer = (uint8_t const *)(p_tx),               \
+    .tx_length = (tx_len),                                \
+    .p_rx_buffer = (p_rx),                                \
+    .rx_length = (rx_len),                                \
+    }
+
+/** @brief Macro for setting the duplex TX RX transfer. */
+#define NRFX_SPIM_XFER_TRX(p_tx_buf, tx_length, p_rx_buf, rx_length) \
+        NRFX_SPIM_SINGLE_XFER(p_tx_buf, tx_length, p_rx_buf, rx_length)
+
+/** @brief Macro for setting the TX transfer. */
+#define NRFX_SPIM_XFER_TX(p_buf, length) \
+        NRFX_SPIM_SINGLE_XFER(p_buf, length, NULL, 0)
+
+/** @brief Macro for setting the RX transfer. */
+#define NRFX_SPIM_XFER_RX(p_buf, length) \
+        NRFX_SPIM_SINGLE_XFER(NULL, 0, p_buf, length)
+
+/**
+ * @brief SPIM master driver event types, passed to the handler routine provided
+ *        during initialization.
+ */
+typedef enum
+{
+    NRFX_SPIM_EVENT_DONE, /* /< Transfer done. */
+} nrfx_spim_evt_type_t;
+
+/** @brief SPIM event description with transmission details. */
+typedef struct
+{
+    nrfx_spim_evt_type_t  type;      /* /< Event type. */
+    nrfx_spim_xfer_desc_t xfer_desc; /* /< Transfer details. */
+} nrfx_spim_evt_t;
+
+/** @brief SPIM driver event handler type. */
+typedef void (* nrfx_spim_evt_handler_t)(nrfx_spim_evt_t const * p_event,
+                                         void *                  p_context);
+
+/**
+ * @brief Function for initializing the SPIM driver instance.
+ *
+ * This function configures and enables the specified peripheral.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ * @param[in] p_config   Pointer to the structure with the initial configuration.
+ * @param[in] handler    Event handler provided by the user. If NULL, transfers
+ *                       will be performed in blocking mode.
+ * @param[in] p_context  Context passed to event handler.
+ *
+ * @warning On nRF5340, 32 MHz setting for SPIM4 peripheral instance is supported
+ *          only on the dedicated pins with @ref NRF_GPIO_PIN_MCUSEL_PERIPHERAL configuration.
+ *          See the chapter <a href=@nRF5340pinAssignmentsURL>Pin assignments</a> in the Product Specification.
+ *
+ * @retval NRFX_SUCCESS             Initialization was successful.
+ * @retval NRFX_ERROR_INVALID_STATE The driver was already initialized.
+ * @retval NRFX_ERROR_BUSY          Some other peripheral with the same
+ *                                  instance ID is already in use. This is
+ *                                  possible only if @ref nrfx_prs module
+ *                                  is enabled.
+ * @retval NRFX_ERROR_NOT_SUPPORTED Requested configuration is not supported
+ *                                  by the SPIM instance.
+ * @retval NRFX_ERROR_INVALID_PARAM Requested frequency is not available on the specified pins.
+ */
+nrfx_err_t nrfx_spim_init(nrfx_spim_t const *        p_instance,
+                          nrfx_spim_config_t const * p_config,
+                          nrfx_spim_evt_handler_t    handler,
+                          void *                     p_context);
+
+/**
+ * @brief Function for uninitializing the SPIM driver instance.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spim_uninit(nrfx_spim_t const * p_instance);
+
+/**
+ * @brief Function for starting the SPIM data transfer.
+ *
+ * Additional options are provided using the @c flags parameter:
+ *
+ * - @ref NRFX_SPIM_FLAG_TX_POSTINC and @ref NRFX_SPIM_FLAG_RX_POSTINC -
+ *   Post-incrementation of buffer addresses.
+ * - @ref NRFX_SPIM_FLAG_HOLD_XFER - Driver is not starting the transfer. Use this
+ *   flag if the transfer is triggered externally by PPI. Use
+ *   @ref nrfx_spim_start_task_get to get the address of the start task.
+ *   Chip select must be configured to @ref NRFX_SPIM_PIN_NOT_USED and managed outside the driver.
+ * - @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER - No user event handler after transfer
+ *   completion. This also means no interrupt at the end of the transfer.
+ *   If @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER is used, the driver does not set the instance into
+ *   busy state, so you must ensure that the next transfers are set up when SPIM is not active.
+ *   @ref nrfx_spim_end_event_get function can be used to detect end of transfer. Option can be used
+ *   together with @ref NRFX_SPIM_FLAG_REPEATED_XFER to prepare a sequence of SPI transfers
+ *   without interruptions.
+ * - @ref NRFX_SPIM_FLAG_REPEATED_XFER - Prepare for repeated transfers. You can set
+ *   up a number of transfers that will be triggered externally (for example by PPI). An example is
+ *   a TXRX transfer with the options @ref NRFX_SPIM_FLAG_RX_POSTINC,
+ *   @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER, and @ref NRFX_SPIM_FLAG_REPEATED_XFER. After the
+ *   transfer is set up, a set of transfers can be triggered by PPI that will read, for example,
+ *   the same register of an external component and put it into a RAM buffer without any interrupts.
+ *   @ref nrfx_spim_end_event_get can be used to get the address of the END event, which can be
+ *   used to count the number of transfers. If @ref NRFX_SPIM_FLAG_REPEATED_XFER is used,
+ *   the driver does not set the instance into busy state, so you must ensure that the next
+ *   transfers are set up when SPIM is not active.
+ *
+ * @note Peripherals using EasyDMA (including SPIM) require the transfer buffers
+ *       to be placed in the Data RAM region. If this condition is not met,
+ *       this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param p_instance  Pointer to the driver instance structure.
+ * @param p_xfer_desc Pointer to the transfer descriptor.
+ * @param flags       Transfer options (0 for default settings).
+ *
+ * @retval NRFX_SUCCESS             The procedure is successful.
+ * @retval NRFX_ERROR_BUSY          The driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
+ * @retval NRFX_ERROR_INVALID_ADDR  The provided buffers are not placed in the Data
+ *                                  RAM region.
+ */
+nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const *           p_instance,
+                          nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                          uint32_t                      flags);
+
+nrfx_err_t rtt_nrfx_spim_xfer(nrfx_spim_t const *         p_instance,
+                            nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                            uint32_t                      flags,
+                            struct rt_spi_message       * message,
+                            struct rt_spi_device        * dev);
+
+#if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) || defined(__NRFX_DOXYGEN__)
+/**
+ * @brief Function for starting the SPIM data transfer with DCX control.
+ *
+ * See @ref nrfx_spim_xfer for description of additional options of transfer
+ * provided by the @c flags parameter.
+ *
+ * @note Peripherals that use EasyDMA (including SPIM) require the transfer buffers
+ *       to be placed in the Data RAM region. If this condition is not met,
+ *       this function will fail with the error code NRFX_ERROR_INVALID_ADDR.
+ *
+ * @param p_instance  Pointer to the driver instance structure.
+ * @param p_xfer_desc Pointer to the transfer descriptor.
+ * @param flags       Transfer options (0 for default settings).
+ * @param cmd_length  Length of the command bytes preceding the data
+ *                    bytes. The DCX line will be low during transmission
+ *                    of command bytes and high during transmission of data bytes.
+ *                    Maximum value available for dividing the transmitted bytes
+ *                    into command bytes and data bytes is @ref NRF_SPIM_DCX_CNT_ALL_CMD - 1.
+ *                    The @ref NRF_SPIM_DCX_CNT_ALL_CMD value passed as the
+ *                    @c cmd_length parameter causes all transmitted bytes
+ *                    to be marked as command bytes.
+ *
+ * @retval NRFX_SUCCESS             The procedure is successful.
+ * @retval NRFX_ERROR_BUSY          The driver is not ready for a new transfer.
+ * @retval NRFX_ERROR_NOT_SUPPORTED The provided parameters are not supported.
+ * @retval NRFX_ERROR_INVALID_ADDR  The provided buffers are not placed in the Data
+ *                                  RAM region.
+ */
+nrfx_err_t nrfx_spim_xfer_dcx(nrfx_spim_t const *           p_instance,
+                              nrfx_spim_xfer_desc_t const * p_xfer_desc,
+                              uint32_t                      flags,
+                              uint8_t                       cmd_length);
+#endif
+
+/**
+ * @brief Function for returning the address of a SPIM start task.
+ *
+ * This function is to be used if @ref nrfx_spim_xfer was called with the flag @ref NRFX_SPIM_FLAG_HOLD_XFER.
+ * In that case, the transfer is not started by the driver, but it must be started externally by PPI.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return Start task address.
+ */
+uint32_t nrfx_spim_start_task_get(nrfx_spim_t const * p_instance);
+
+/**
+ * @brief Function for returning the address of a END SPIM event.
+ *
+ * The END event can be used to detect the end of a transfer
+ * if the @ref NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER option is used.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ *
+ * @return END event address.
+ */
+uint32_t nrfx_spim_end_event_get(nrfx_spim_t const * p_instance);
+
+/**
+ * @brief Function for aborting ongoing transfer.
+ *
+ * @param[in] p_instance Pointer to the driver instance structure.
+ */
+void nrfx_spim_abort(nrfx_spim_t const * p_instance);
+
+/** @} */
+
+
+void nrfx_spim_0_irq_handler(void);
+void nrfx_spim_1_irq_handler(void);
+void nrfx_spim_2_irq_handler(void);
+void nrfx_spim_3_irq_handler(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRFX_SPIM_H__ */
+

+ 4 - 0
bsp/nrf5x/nrf52840/.ci/attachconfig/ci.attachconfig.yml

@@ -19,6 +19,10 @@ devices.spi:
     kconfig:
       - CONFIG_RT_USING_SPI=y
       - CONFIG_BSP_USING_SPI=y
+devices.spim:
+    kconfig:
+      - CONFIG_RT_USING_SPIM=y
+      - CONFIG_BSP_USING_SPIM=y
 devices.uart:
     kconfig:
       - CONFIG_BSP_USING_UART=y

+ 119 - 20
bsp/nrf5x/nrf52840/board/Kconfig

@@ -53,27 +53,27 @@ menu "Onboard Peripheral Drivers"
             default 1
             config BSP_QSPI_SCK_PIN
                 int "QSPI SCK pin number"
-                range 0 31
+                range 0 48
                 default 19
             config BSP_QSPI_CSN_PIN
                 int "QSPI CSN pin number"
-                range 0 31
+                range 0 48
                 default 17
             config BSP_QSPI_IO0_PIN
                 int "QSPI IO0 pin number"
-                range 0 31
+                range 0 48
                 default 20
             config BSP_QSPI_IO1_PIN
                 int "QSPI IO1 pin number"
-                range 0 31
+                range 0 48
                 default 21
             config BSP_QSPI_IO2_PIN
                 int "QSPI IO2 pin number"
-                range 0 31
+                range 0 48
                 default 22
             config BSP_QSPI_IO3_PIN
                 int "QSPI IO3 pin number"
-                range 0 31
+                range 0 48
                 default 23
             config QSPI_FLASH_SIZE_KB
                 int "QSPI FLASH SIZE, DEFAULT size 8192 KB"
@@ -113,12 +113,12 @@ menu "On-chip Peripheral Drivers"
                 if BSP_USING_UART0
                     config BSP_UART0_RX_PIN
                         int "uart0 rx pin number"
-                        range 0 64
+                        range 0 48
                         default 8 if BSP_BOARD_PCA_10056
                         default 42 if BSP_BOARD_ARDUINO_NANO_33_BLE
                     config BSP_UART0_TX_PIN
                         int "uart0 tx pin number"
-                        range 0 64
+                        range 0 48
                         default 6 if BSP_BOARD_PCA_10056
                         default 35 if BSP_BOARD_ARDUINO_NANO_33_BLE
                 endif
@@ -137,11 +137,11 @@ menu "On-chip Peripheral Drivers"
                     default 1
                     config BSP_UART0_RX_PIN
                         int "uarte0 rx pin number"
-                        range 0 31
+                        range 0 48
                         default 8
                     config BSP_UART0_TX_PIN
                         int "uarte0 tx pin number"
-                        range 0 31
+                        range 0 48
                         default 6
                 endif
             config BSP_USING_UART1
@@ -153,11 +153,11 @@ menu "On-chip Peripheral Drivers"
                     default 1
                     config BSP_UART1_RX_PIN
                         int "uarte1 rx pin number"
-                        range 0 31
+                        range 0 48
                         default 7
                     config BSP_UART1_TX_PIN
                         int "uarte1 tx pin number"
-                        range 0 31
+                        range 0 48
                         default 5
                 endif
         endif
@@ -236,19 +236,19 @@ menu "On-chip Peripheral Drivers"
                 default n
             if BSP_USING_SPI1
                 config BSP_SPI1_SCK_PIN
-                    int "SPI0 sck pin number set"
+                    int "SPI1 sck pin number set"
                     range 0 47
                     default 28
                 config BSP_SPI1_MOSI_PIN
-                    int "SPI0 mosi pin number set"
+                    int "SPI1 mosi pin number set"
                     range 0 47
                     default 29
                 config BSP_SPI1_MISO_PIN
-                    int "SPI0 miso pin number set"
+                    int "SPI1 miso pin number set"
                     range 0 47
                     default 30
                 config BSP_SPI1_SS_PIN
-                    int "SPI0 ss pin number set"
+                    int "SPI1 ss pin number set"
                     range 0 47
                     default 31
             endif
@@ -258,23 +258,122 @@ menu "On-chip Peripheral Drivers"
                 default n
             if BSP_USING_SPI2
                 config BSP_SPI2_SCK_PIN
-                    int "SPI0 sck pin number set"
+                    int "SPI2 sck pin number set"
                     range 0 47
                     default 28
                 config BSP_SPI2_MOSI_PIN
-                    int "SPI0 mosi pin number set"
+                    int "SPI2 mosi pin number set"
                     range 0 47
                     default 29
                 config BSP_SPI2_MISO_PIN
-                    int "SPI0 miso pin number set"
+                    int "SPI2 miso pin number set"
                     range 0 47
                     default 30
                 config BSP_SPI2_SS_PIN
-                    int "SPI0 ss pin number set"
+                    int "SPI2 ss pin number set"
+                    range 0 47
+                    default 31
+            endif
+
+        endif
+
+    menuconfig BSP_USING_SPIM
+        bool "Enable SPIM"
+        select RT_USING_SPIM
+        default n
+
+        if BSP_USING_SPIM
+            config BSP_USING_SPIM0
+                bool "Enable SPIM0 bus"
+                default y
+            if BSP_USING_SPIM0
+                config NRFX_SPIM0_ENABLED
+                    int "Enable SPI0 instance"
+                    default 1
+                config BSP_SPIM0_SCK_PIN
+                    int "SPIM0 sck pin number set"
+                    range 0 47
+                    default 28
+                config BSP_SPIM0_MOSI_PIN
+                    int "SPIM0 mosi pin number set"
+                    range 0 47
+                    default 29
+                config BSP_SPIM0_MISO_PIN
+                    int "SPIM0 miso pin number set"
+                    range 0 47
+                    default 30
+                config BSP_SPIM0_SS_PIN
+                    int "SPIM0 ss pin number set"
                     range 0 47
                     default 31
             endif
 
+            config BSP_USING_SPIM1
+                bool "Enable SPIM1 bus"
+                default n
+            if BSP_USING_SPIM1
+                config BSP_SPIM1_SCK_PIN
+                    int "SPIM1 sck pin number set"
+                    range 0 47
+                    default 28
+                config BSP_SPIM1_MOSI_PIN
+                    int "SPIM1 mosi pin number set"
+                    range 0 47
+                    default 29
+                config BSP_SPIM1_MISO_PIN
+                    int "SPIM1 miso pin number set"
+                    range 0 47
+                    default 30
+                config BSP_SPIM1_SS_PIN
+                    int "SPIM1 ss pin number set"
+                    range 0 47
+                    default 31
+            endif
+
+            config BSP_USING_SPIM2
+                bool "Enable SPIM2 bus"
+                default n
+            if BSP_USING_SPIM2
+                config BSP_SPIM2_SCK_PIN
+                    int "SPIM2 sck pin number set"
+                    range 0 47
+                    default 28
+                config BSP_SPIM2_MOSI_PIN
+                    int "SPIM2 mosi pin number set"
+                    range 0 47
+                    default 29
+                config BSP_SPIM2_MISO_PIN
+                    int "SPIM2 miso pin number set"
+                    range 0 47
+                    default 30
+                config BSP_SPIM2_SS_PIN
+                    int "SPIM2 ss pin number set"
+                    range 0 47
+                    default 31
+            endif
+
+        config BSP_USING_SPIM3
+            bool "Enable SPIM3 bus"
+            default n
+        if BSP_USING_SPIM3
+            config BSP_SPIM3_SCK_PIN
+                int "SPIM3 sck pin number set"
+                range 0 47
+                default 28
+            config BSP_SPIM3_MOSI_PIN
+                int "SPIM3 mosi pin number set"
+                range 0 47
+                default 29
+            config BSP_SPIM3_MISO_PIN
+                int "SPIM3 miso pin number set"
+                range 0 47
+                default 30
+            config BSP_SPIM3_SS_PIN
+                int "SPIM3 ss pin number set"
+                range 0 47
+                default 31
+            endif
+
         endif
 
     menuconfig BSP_USING_PWM