diff --git a/bsp/nrf5x/libraries/drivers/drv_adc.c b/bsp/nrf5x/libraries/drivers/drv_adc.c index 03fd293113c..c3cd49f51ee 100644 --- a/bsp/nrf5x/libraries/drivers/drv_adc.c +++ b/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 -#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}; diff --git a/bsp/nrf5x/libraries/drivers/drv_adc.h b/bsp/nrf5x/libraries/drivers/drv_adc.h index 8200baa2f8e..f6a9e11cfbe 100644 --- a/bsp/nrf5x/libraries/drivers/drv_adc.h +++ b/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__ */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_flash.c b/bsp/nrf5x/libraries/drivers/drv_flash.c index 259ee09aa23..fde969cdcf5 100644 --- a/bsp/nrf5x/libraries/drivers/drv_flash.c +++ b/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 */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_gpio.c b/bsp/nrf5x/libraries/drivers/drv_gpio.c index 88385b561f6..1484744ef33 100644 --- a/bsp/nrf5x/libraries/drivers/drv_gpio.c +++ b/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 */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_gpio.h b/bsp/nrf5x/libraries/drivers/drv_gpio.h index 0341ad097ec..fca2f6d80ec 100644 --- a/bsp/nrf5x/libraries/drivers/drv_gpio.h +++ b/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; }; diff --git a/bsp/nrf5x/libraries/drivers/drv_hwtimer.c b/bsp/nrf5x/libraries/drivers/drv_hwtimer.c index 3a93a83b2e2..1e8d83f5500 100644 --- a/bsp/nrf5x/libraries/drivers/drv_hwtimer.c +++ b/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; } diff --git a/bsp/nrf5x/libraries/drivers/drv_i2c.c b/bsp/nrf5x/libraries/drivers/drv_i2c.c index c2efab809b9..db2465bcc26 100644 --- a/bsp/nrf5x/libraries/drivers/drv_i2c.c +++ b/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) */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_i2c.h b/bsp/nrf5x/libraries/drivers/drv_i2c.h index 8b3b71751ec..eda8766b820 100644 --- a/bsp/nrf5x/libraries/drivers/drv_i2c.h +++ b/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__ */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_pwm.c b/bsp/nrf5x/libraries/drivers/drv_pwm.c index 0a374ac2436..ed16deb0438 100644 --- a/bsp/nrf5x/libraries/drivers/drv_pwm.c +++ b/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 + diff --git a/bsp/nrf5x/libraries/drivers/drv_qspi_flash.c b/bsp/nrf5x/libraries/drivers/drv_qspi_flash.c index fb0b6c319dd..6c1d210d8c2 100644 --- a/bsp/nrf5x/libraries/drivers/drv_qspi_flash.c +++ b/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 -//log +/* log */ #include #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 + diff --git a/bsp/nrf5x/libraries/drivers/drv_rtc.c b/bsp/nrf5x/libraries/drivers/drv_rtc.c index 357f2e16111..366be3ccd64 100644 --- a/bsp/nrf5x/libraries/drivers/drv_rtc.c +++ b/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; diff --git a/bsp/nrf5x/libraries/drivers/drv_spi.c b/bsp/nrf5x/libraries/drivers/drv_spi.c index 547aed124e8..a6993fce5b0 100644 --- a/bsp/nrf5x/libraries/drivers/drv_spi.c +++ b/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*/ + diff --git a/bsp/nrf5x/libraries/drivers/drv_spi.h b/bsp/nrf5x/libraries/drivers/drv_spi.h index 0be8ff4c894..be3bc2f1ddd 100644 --- a/bsp/nrf5x/libraries/drivers/drv_spi.h +++ b/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_*/ + diff --git a/bsp/nrf5x/libraries/drivers/drv_spim.c b/bsp/nrf5x/libraries/drivers/drv_spim.c new file mode 100644 index 00000000000..3c6c4c9f93f --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_spim.c @@ -0,0 +1,337 @@ +#include +#include +#include "board.h" +#include "drv_spim.h" +#include "nrfx_spim.h" +#include "rtconfig.h" +#include +#include + +#define DBG_LEVEL DBG_LOG +#include +/* #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 */ + + #if USING_SPI_DMA + /* 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 */ + mess->cs_pin = device->cs_pin; + /* step 2 */ + mess->cs_take = 0; + mess->cs_release = 0; + /* step 3 */ + mess->use_hw_ss = config.use_hw_ss; + /* step 4 */ + mess->ss_active_high = config.ss_active_high; + /* step 6 */ + mess->cpt = cpt; + + context = (void*)mess; + handler = spim_handler[index]; + #endif + + 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*/ + diff --git a/bsp/nrf5x/libraries/drivers/drv_spim.h b/bsp/nrf5x/libraries/drivers/drv_spim.h new file mode 100644 index 00000000000..5ecf7c42cc1 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_spim.h @@ -0,0 +1,102 @@ +#include +#include +#include + +#ifndef __DRV_SPIM_H_ +#define __DRV_SPIM_H_ + +#ifdef BSP_USING_SPIM + +#include "nrfx_spim.h" +#include "nrf_spi.h" +#include "rtconfig.h" + +#define USING_SPI_DMA 1 + +#if USING_SPI_DMA + +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; + +}; + +#endif + +/** + * @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_ */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_uart.c b/bsp/nrf5x/libraries/drivers/drv_uart.c index 782f6844b15..9363472833b 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uart.c +++ b/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 */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_uarte.c b/bsp/nrf5x/libraries/drivers/drv_uarte.c index 1139b69de8b..4dd003c0906 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uarte.c +++ b/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 * @@ -267,6 +267,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]; @@ -325,3 +326,4 @@ int rt_hw_uart_init(void) } #endif /* defined(BSP_USING_UART0) || defined(BSP_USING_UART1) */ #endif /* BSP_USING_UART */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_uarte.h b/bsp/nrf5x/libraries/drivers/drv_uarte.h index f4bd2e14998..f08c975b1f4 100644 --- a/bsp/nrf5x/libraries/drivers/drv_uarte.h +++ b/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__ */ + diff --git a/bsp/nrf5x/libraries/drivers/drv_wdt.c b/bsp/nrf5x/libraries/drivers/drv_wdt.c index ccf6c88b5df..ff84c4f88aa 100644 --- a/bsp/nrf5x/libraries/drivers/drv_wdt.c +++ b/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 */ + diff --git a/bsp/nrf5x/libraries/drivers/nrfx_spim.c b/bsp/nrf5x/libraries/drivers/nrfx_spim.c new file mode 100644 index 00000000000..6597248db93 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.c @@ -0,0 +1,1090 @@ +/* + * 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 +#include + +#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 ." +#endif + +#include "drv_spim.h" + +#include +#include "prs/nrfx_prs.h" +#include + +#define NRFX_LOG_MODULE SPIM +#include + +#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) +{ + + #if USING_SPI_DMA + 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); + } + } + } + + #else + /* If Slave Select signal is used, this is the time to deactivate it. */ + 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); + } + } + } + #endif + + + /* 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); + + #if USING_SPI_DMA + spim_int_enable(mess->spim, ((mess->flags) & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)); + rt_completion_done(mess->cpt); + #endif +} + +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) +{ + #define DMA_TRANS_MIN_LEN (20) /* only buffer length >= DMA_TRANS_MIN_LEN will use DMA mode */ + + 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 USING_SPI_DMA + 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; + #endif + + 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<= DMA_TRANS_MIN_LEN && p_xfer_desc->tx_length<= DMA_TRANS_MIN_LEN)) + { + /* no cb func or lenth < DMA_TRANS_MIN_LEN, 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 + { + #if USING_SPI_DMA + 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; + } + #else + spim_int_enable(p_spim, !(flags & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)); + #endif + } + 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) */ + diff --git a/bsp/nrf5x/libraries/drivers/nrfx_spim.h b/bsp/nrf5x/libraries/drivers/nrfx_spim.h new file mode 100644 index 00000000000..ee75139b7ee --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.h @@ -0,0 +1,424 @@ +/* + * 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 +#include +#include "board.h" +#include "rtconfig.h" + +#include +#include +#include + +#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 signa;) + * - 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 Pin assignments 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__ */ + diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index a15d5800d3c..5c9b057b032 100644 --- a/bsp/nrf5x/nrf52840/board/Kconfig +++ b/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,123 @@ 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