From 464ea7c319df9f13577f763d5917d903fa6504be Mon Sep 17 00:00:00 2001 From: Core0349 <2578307863@qq.com> Date: Sat, 2 Aug 2025 20:07:14 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86spim=E7=9A=84?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E9=A9=B1=E5=8A=A8=E5=92=8C=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/nrf5x/libraries/drivers/drv_spim.c | 337 +++++++ bsp/nrf5x/libraries/drivers/drv_spim.h | 101 +++ bsp/nrf5x/libraries/drivers/nrfx_spim.c | 1101 +++++++++++++++++++++++ bsp/nrf5x/libraries/drivers/nrfx_spim.h | 426 +++++++++ 4 files changed, 1965 insertions(+) create mode 100644 bsp/nrf5x/libraries/drivers/drv_spim.c create mode 100644 bsp/nrf5x/libraries/drivers/drv_spim.h create mode 100644 bsp/nrf5x/libraries/drivers/nrfx_spim.c create mode 100644 bsp/nrf5x/libraries/drivers/nrfx_spim.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..e2121bd30b5 --- /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 + /* 创造、初始化完成量 */ + struct rt_completion *cpt = (struct rt_completion*)rt_malloc(sizeof(struct rt_completion)); + rt_completion_init(cpt); + + /* 创造、初始化spi关于dma的信息体 */ + 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..3fba0d012a0 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/drv_spim.h @@ -0,0 +1,101 @@ +#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/nrfx_spim.c b/bsp/nrf5x/libraries/drivers/nrfx_spim.c new file mode 100644 index 00000000000..cd1e1149ab6 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.c @@ -0,0 +1,1101 @@ +/* + * 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); +} + +/************************************************************** +* +* 改写的spim_xfer +* +***************************************************************/ +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 + /* 赋值给spim_control_block_t的void *context */ + 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)) + { + //没有回调函数进入死循环 + //或者接受/发送字节小于最小的数量 +// 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_spim_xfer +* +***************************************************************/ + +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..e43e92246df --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.h @@ -0,0 +1,426 @@ +/* + * 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 +#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__ From 5ac903bda456fa2a322e717219cb519c7d2d887a Mon Sep 17 00:00:00 2001 From: Core0349 <2578307863@qq.com> Date: Sat, 2 Aug 2025 20:10:25 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86nrf52840=20?= =?UTF-8?q?=E7=9A=84spim=E5=BA=95=E5=B1=82=E9=A9=B1=E5=8A=A8=E5=92=8C?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/nrf5x/libraries/drivers/nrfx_spim.c | 1101 ----------------------- 1 file changed, 1101 deletions(-) delete mode 100644 bsp/nrf5x/libraries/drivers/nrfx_spim.c diff --git a/bsp/nrf5x/libraries/drivers/nrfx_spim.c b/bsp/nrf5x/libraries/drivers/nrfx_spim.c deleted file mode 100644 index cd1e1149ab6..00000000000 --- a/bsp/nrf5x/libraries/drivers/nrfx_spim.c +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * 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); -} - -/************************************************************** -* -* 改写的spim_xfer -* -***************************************************************/ -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 - /* 赋值给spim_control_block_t的void *context */ - 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)) - { - //没有回调函数进入死循环 - //或者接受/发送字节小于最小的数量 -// 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_spim_xfer -* -***************************************************************/ - -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) From 22d94ed9c27257497a43d73acb5f1bd902161279 Mon Sep 17 00:00:00 2001 From: Core0349 <2578307863@qq.com> Date: Sat, 2 Aug 2025 20:11:47 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86spim=E7=9A=84?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E9=A9=B1=E5=8A=A8=E5=92=8C=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/nrf5x/libraries/drivers/nrfx_spim.c | 1101 +++++++++++++++++++++++ 1 file changed, 1101 insertions(+) create mode 100644 bsp/nrf5x/libraries/drivers/nrfx_spim.c diff --git a/bsp/nrf5x/libraries/drivers/nrfx_spim.c b/bsp/nrf5x/libraries/drivers/nrfx_spim.c new file mode 100644 index 00000000000..cd1e1149ab6 --- /dev/null +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.c @@ -0,0 +1,1101 @@ +/* + * 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); +} + +/************************************************************** +* +* 改写的spim_xfer +* +***************************************************************/ +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 + /* 赋值给spim_control_block_t的void *context */ + 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)) + { + //没有回调函数进入死循环 + //或者接受/发送字节小于最小的数量 +// 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_spim_xfer +* +***************************************************************/ + +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) From 1aeeda0ef14be70a3007212a079b7de5ec1e2778 Mon Sep 17 00:00:00 2001 From: Core0349 <2578307863@qq.com> Date: Sat, 2 Aug 2025 20:27:36 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86spim=E7=9A=84?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E9=A9=B1=E5=8A=A8=E5=92=8C=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/nrf5x/nrf52840/board/Kconfig | 140 ++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 20 deletions(-) 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 From c8d05410373b1fbc2173adfafcbd015bfa472cab Mon Sep 17 00:00:00 2001 From: Core0349 <2578307863@qq.com> Date: Sun, 3 Aug 2025 13:54:46 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/nrf5x/libraries/drivers/drv_adc.c | 17 +- bsp/nrf5x/libraries/drivers/drv_adc.h | 11 +- bsp/nrf5x/libraries/drivers/drv_flash.c | 8 +- bsp/nrf5x/libraries/drivers/drv_gpio.c | 16 +- bsp/nrf5x/libraries/drivers/drv_gpio.h | 4 +- bsp/nrf5x/libraries/drivers/drv_hwtimer.c | 14 +- bsp/nrf5x/libraries/drivers/drv_i2c.c | 3 +- bsp/nrf5x/libraries/drivers/drv_i2c.h | 3 +- bsp/nrf5x/libraries/drivers/drv_pwm.c | 9 +- bsp/nrf5x/libraries/drivers/drv_qspi_flash.c | 12 +- bsp/nrf5x/libraries/drivers/drv_rtc.c | 8 +- bsp/nrf5x/libraries/drivers/drv_spi.c | 25 +- bsp/nrf5x/libraries/drivers/drv_spi.h | 7 +- bsp/nrf5x/libraries/drivers/drv_spim.c | 102 +++--- bsp/nrf5x/libraries/drivers/drv_spim.h | 25 +- bsp/nrf5x/libraries/drivers/drv_uart.c | 11 +- bsp/nrf5x/libraries/drivers/drv_uarte.c | 4 +- bsp/nrf5x/libraries/drivers/drv_uarte.h | 3 +- bsp/nrf5x/libraries/drivers/drv_wdt.c | 3 +- bsp/nrf5x/libraries/drivers/nrfx_spim.c | 347 +++++++++---------- bsp/nrf5x/libraries/drivers/nrfx_spim.h | 62 ++-- 21 files changed, 358 insertions(+), 336 deletions(-) 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 index e2121bd30b5..3c6c4c9f93f 100644 --- a/bsp/nrf5x/libraries/drivers/drv_spim.c +++ b/bsp/nrf5x/libraries/drivers/drv_spim.c @@ -9,7 +9,7 @@ #define DBG_LEVEL DBG_LOG #include -//#define LOG_TAG "drv.spim" +/* #define LOG_TAG "drv.spim" */ #ifdef BSP_USING_SPIM @@ -37,8 +37,8 @@ static struct nrfx_drv_spim_config spim_config[] = 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[] = +/* Configure SPIM bus pins using the menuconfig */ +static struct nrfx_drv_spim_pin_config bsp_spim_pin[] = { #ifdef BSP_USING_SPIM0 { @@ -108,7 +108,7 @@ static void spim1_handler(const nrfx_spim_evt_t *p_event, void *p_context) #ifdef BSP_USING_SPIM2 static void spim2_handler(const nrfx_spim_evt_t *p_event, void *p_context) { - return; + return; } #endif @@ -121,19 +121,19 @@ static void spim3_handler(const nrfx_spim_evt_t *p_event, void *p_context) nrfx_spim_evt_handler_t spim_handler[] = { #ifdef BSP_USING_SPIM0 - spim0_handler, + spim0_handler, #endif #ifdef BSP_USING_SPIM1 - spim1_handler, + spim1_handler, #endif #ifdef BSP_USING_SPIM2 - spim2_handler, + spim2_handler, #endif - + #ifdef BSP_USING_SPIM3 - spim3_handler, + spim3_handler, #endif }; @@ -157,13 +157,13 @@ static rt_err_t spim_configure(struct rt_spi_device *device, 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; + 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) { @@ -222,46 +222,45 @@ static rt_err_t spim_configure(struct rt_spi_device *device, 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 - /* 创造、初始化完成量 */ - struct rt_completion *cpt = (struct rt_completion*)rt_malloc(sizeof(struct rt_completion)); - rt_completion_init(cpt); - - /* 创造、初始化spi关于dma的信息体 */ - 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 - + + 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); + else + LOG_E("spim configure fail. %x", nrf_ret); return -RT_ERROR; } @@ -278,23 +277,24 @@ static rt_ssize_t spimxfer(struct rt_spi_device *device, struct rt_spi_message * 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); + LOG_E("SPIM data transfer fail. %x", nrf_ret); return 0; } else @@ -318,7 +318,7 @@ static int rt_hw_spim_bus_init(void) 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 + 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); } diff --git a/bsp/nrf5x/libraries/drivers/drv_spim.h b/bsp/nrf5x/libraries/drivers/drv_spim.h index 3fba0d012a0..5ecf7c42cc1 100644 --- a/bsp/nrf5x/libraries/drivers/drv_spim.h +++ b/bsp/nrf5x/libraries/drivers/drv_spim.h @@ -17,17 +17,17 @@ 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; - + 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 @@ -41,7 +41,7 @@ struct spi_dma_message */ rt_err_t rt_hw_spim_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin); -//SPIM bus config +/* SPIM bus config */ #ifdef BSP_USING_SPIM0 #define NRFX_SPIM0_CONFIG \ { \ @@ -99,3 +99,4 @@ struct nrfx_drv_spim_pin_config #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 index cd1e1149ab6..6597248db93 100644 --- a/bsp/nrf5x/libraries/drivers/nrfx_spim.c +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.c @@ -166,23 +166,23 @@ 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. +/* 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). +/* 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. +/* 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_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; @@ -190,8 +190,8 @@ typedef struct 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] + /* [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; @@ -205,7 +205,7 @@ 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. +/* Workaround for nRF52840 anomaly 198: SPIM3 transmit data might be corrupted. */ static uint32_t m_anomaly_198_preserved_value; @@ -242,7 +242,7 @@ 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) +#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) { @@ -275,7 +275,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, } #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) - // Check if SPIM instance supports the extended features. + /* 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) && @@ -295,7 +295,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, 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. + /* Check if dedicated SPIM pins are used. */ if ((p_spim == NRF_SPIM4) && (p_config->frequency == NRF_SPIM_FREQ_32M)) { enum { @@ -350,18 +350,18 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } -#endif // NRFX_CHECK(NRFX_PRS_ENABLED) +#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. + /* 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); @@ -372,7 +372,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, } nrf_gpio_pin_drive_t pin_drive; - // Configure pin drive - high drive for 32 MHz clock frequency. + /* 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 @@ -385,7 +385,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, NRF_GPIO_PIN_NOPULL, pin_drive, NRF_GPIO_PIN_NOSENSE); - // - MOSI (optional) - output with initial value 0, + /* - MOSI (optional) - output with initial value 0, */ if (p_config->mosi_pin != NRFX_SPIM_PIN_NOT_USED) { mosi_pin = p_config->mosi_pin; @@ -401,7 +401,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, { mosi_pin = NRF_SPIM_PIN_NOT_CONNECTED; } - // - MISO (optional) - input, + /* - MISO (optional) - input, */ if (p_config->miso_pin != NRFX_SPIM_PIN_NOT_USED) { miso_pin = p_config->miso_pin; @@ -416,10 +416,10 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, { miso_pin = NRF_SPIM_PIN_NOT_CONNECTED; } - // - Slave Select (optional) - output with initial value 1 (inactive). + /* - 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' 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) @@ -453,7 +453,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, } #if NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) - // - DCX (optional) - output. + /* - DCX (optional) - output. */ if (p_config->dcx_pin != NRFX_SPIM_PIN_NOT_USED) { nrf_gpio_pin_set(p_config->dcx_pin); @@ -466,7 +466,7 @@ nrfx_err_t nrfx_spim_init(nrfx_spim_t const * p_instance, nrf_spim_dcx_pin_set(p_spim, p_config->dcx_pin); } - // Change rx delay + /* Change rx delay */ nrf_spim_iftiming_set(p_spim, p_config->rx_delay); #endif @@ -515,7 +515,7 @@ void nrfx_spim_uninit(nrfx_spim_t const * p_instance) 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. + /* Ensure that SPI is not performing any transfer. */ spim_abort(p_spim, p_cb); } } @@ -569,58 +569,58 @@ 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. + + #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 + + #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) @@ -662,8 +662,8 @@ static nrfx_err_t spim_xfer(NRF_SPIM_Type * p_spim, 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. + /* 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))) { @@ -679,9 +679,9 @@ static nrfx_err_t spim_xfer(NRF_SPIM_Type * p_spim, 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); + + 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) @@ -724,22 +724,22 @@ static nrfx_err_t spim_xfer(NRF_SPIM_Type * p_spim, 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); - } - } - } + 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 { @@ -805,23 +805,19 @@ nrfx_err_t nrfx_spim_xfer(nrfx_spim_t const * p_instance, return spim_xfer(p_instance->p_reg, p_cb, p_xfer_desc, flags); } -/************************************************************** -* -* 改写的spim_xfer -* -***************************************************************/ + 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_message * message, struct rt_spi_device * dev) { - #define DMA_TRANS_MIN_LEN (20) /* only buffer length >= DMA_TRANS_MIN_LEN will use DMA mode */ - + #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. + /* 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))) { @@ -833,38 +829,37 @@ static nrfx_err_t rtt_spim_xfer(NRF_SPIM_Type * p_spim, return err_code; } - #if USING_SPI_DMA - /* 赋值给spim_control_block_t的void *context */ - 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 - + #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"); +/* rt_kprintf("SPIM task started.\n"); */ } #if NRFX_CHECK(NRFX_SPIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) if (flags & NRFX_SPIM_FLAG_HOLD_XFER) @@ -880,17 +875,16 @@ static nrfx_err_t rtt_spim_xfer(NRF_SPIM_Type * p_spim, if (p_cb->handler == RT_NULL || (p_xfer_desc->rx_length<= DMA_TRANS_MIN_LEN && p_xfer_desc->tx_length<= DMA_TRANS_MIN_LEN)) { - //没有回调函数进入死循环 - //或者接受/发送字节小于最小的数量 -// spim_int_enable(p_spim, ((mess->flags) & NRFX_SPIM_FLAG_NO_XFER_EVT_HANDLER)); + /* 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; + + } +/* rt_kprintf("SPIM transfer end.\n"); */ + p_cb->transfer_in_progress = false; } #if NRFX_CHECK(NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED) @@ -900,48 +894,42 @@ static nrfx_err_t rtt_spim_xfer(NRF_SPIM_Type * p_spim, } #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); - } - } + 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 + #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_spim_xfer -* -***************************************************************/ - 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, + 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]; @@ -1065,37 +1053,38 @@ void nrfx_spim_0_irq_handler(void) #if NRFX_CHECK(NRFX_SPIM1_ENABLED) void nrfx_spim_1_irq_handler(void) { - rt_interrupt_enter(); + rt_interrupt_enter(); irq_handler(NRF_SPIM1, &m_cb[NRFX_SPIM1_INST_IDX]); - rt_interrupt_leave(); + rt_interrupt_leave(); } #endif #if NRFX_CHECK(NRFX_SPIM2_ENABLED) void nrfx_spim_2_irq_handler(void) { - rt_interrupt_enter(); + rt_interrupt_enter(); irq_handler(NRF_SPIM2, &m_cb[NRFX_SPIM2_INST_IDX]); - rt_interrupt_leave(); + rt_interrupt_leave(); } #endif #if NRFX_CHECK(NRFX_SPIM3_ENABLED) void nrfx_spim_3_irq_handler(void) { - rt_interrupt_enter(); + rt_interrupt_enter(); irq_handler(NRF_SPIM3, &m_cb[NRFX_SPIM3_INST_IDX]); - rt_interrupt_leave(); + rt_interrupt_leave(); } #endif #if NRFX_CHECK(NRFX_SPIM4_ENABLED) void nrfx_spim_4_irq_handler(void) { - rt_interrupt_enter(); + rt_interrupt_enter(); irq_handler(NRF_SPIM4, &m_cb[NRFX_SPIM4_INST_IDX]); - rt_interrupt_leave(); + rt_interrupt_leave(); } #endif -#endif // NRFX_CHECK(NRFX_SPIM_ENABLED) +#endif /* NRFX_CHECK(NRFX_SPIM_ENABLED) */ + diff --git a/bsp/nrf5x/libraries/drivers/nrfx_spim.h b/bsp/nrf5x/libraries/drivers/nrfx_spim.h index e43e92246df..ee75139b7ee 100644 --- a/bsp/nrf5x/libraries/drivers/nrfx_spim.h +++ b/bsp/nrf5x/libraries/drivers/nrfx_spim.h @@ -38,7 +38,6 @@ #include #include "board.h" #include "rtconfig.h" -#include #include #include @@ -58,8 +57,8 @@ extern "C" { /** @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. + 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__ @@ -100,34 +99,34 @@ enum { /** @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). + 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). + 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). + 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. + 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. + 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. + 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. + 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). @@ -200,10 +199,10 @@ typedef struct /** @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. + 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; /** @@ -237,14 +236,14 @@ typedef struct */ typedef enum { - NRFX_SPIM_EVENT_DONE, ///< Transfer done. + 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_type_t type; /* /< Event type. */ + nrfx_spim_xfer_desc_t xfer_desc; /* /< Transfer details. */ } nrfx_spim_evt_t; /** @brief SPIM driver event handler type. */ @@ -335,13 +334,11 @@ 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, + 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__) @@ -423,4 +420,5 @@ void nrfx_spim_3_irq_handler(void); } #endif -#endif // NRFX_SPIM_H__ +#endif /* NRFX_SPIM_H__ */ +