From 0b6c5f690db2fe53ad02349bfdd81d9d1b223851 Mon Sep 17 00:00:00 2001 From: Zght <14912335+VisionBoard@user.noreply.gitee.com> Date: Sun, 7 Jun 2026 20:08:02 +0800 Subject: [PATCH] add: Add QSPI driver for NS800RT7xxx --- .../libraries/HAL_Drivers/drivers/SConscript | 2 + .../libraries/HAL_Drivers/drivers/drv_qspi.c | 185 ++++++++++++++++++ .../libraries/HAL_Drivers/drivers/drv_qspi.h | 21 ++ .../ns800/ns800rt7p65-nssinepad/board/Kconfig | 5 + .../ns800/ns800rt7p65-nssinepad/rtconfig.h | 1 + 5 files changed, 214 insertions(+) create mode 100644 bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.c create mode 100644 bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.h diff --git a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript index 9c90f5f9c1..e78ae25b13 100644 --- a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript +++ b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript @@ -24,6 +24,8 @@ if GetDepend('BSP_USING_TIM'): if GetDepend('BSP_USING_SPI'): src += ['drv_spi.c'] +if GetDepend('BSP_USING_QSPI'): + src += ['drv_qspi.c'] group = DefineGroup('HAL_Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.c b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.c new file mode 100644 index 0000000000..ff27771bb5 --- /dev/null +++ b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.c @@ -0,0 +1,185 @@ +/* + * QSPI driver for NS800RT7xxx + W25Q128 + * Fully supports RT-Thread QSPI (rt_qspi_transfer_message) + * All transfers use QSPI_writeDirect / QSPI_readDirect (same as working direct API) + */ + + +#include +#include +#include "qspi.h" +#include "board.h" + + + +#ifdef RT_USING_QSPI + +/*=========================================================================== + * GPIO initialization + *===========================================================================*/ +static void qspi_pin_init(void) +{ + GPIO_setPinConfig(GPIO_15_QSPI_NCS); + GPIO_setAnalogMode(GPIO_15, GPIO_ANALOG_DISABLED); + GPIO_setPadConfig(GPIO_15, GPIO_PIN_TYPE_PULLUP); + GPIO_setQualificationMode(GPIO_15, GPIO_QUAL_ASYNC); + + GPIO_setPinConfig(GPIO_16_QSPI_D0); + GPIO_setAnalogMode(GPIO_16, GPIO_ANALOG_DISABLED); + GPIO_setPadConfig(GPIO_16, GPIO_PIN_TYPE_PULLUP); + GPIO_setQualificationMode(GPIO_16, GPIO_QUAL_ASYNC); + GPIO_setDirectionMode(GPIO_16, GPIO_DIR_MODE_OUT); + + GPIO_setPinConfig(GPIO_17_QSPI_D1); + GPIO_setAnalogMode(GPIO_17, GPIO_ANALOG_DISABLED); + GPIO_setPadConfig(GPIO_17, GPIO_PIN_TYPE_PULLUP); + GPIO_setQualificationMode(GPIO_17, GPIO_QUAL_ASYNC); + GPIO_setDirectionMode(GPIO_17, GPIO_DIR_MODE_IN); + + GPIO_setPinConfig(GPIO_18_QSPI_D2); + GPIO_setAnalogMode(GPIO_18, GPIO_ANALOG_DISABLED); + GPIO_setPadConfig(GPIO_18, GPIO_PIN_TYPE_PULLUP); + GPIO_setQualificationMode(GPIO_18, GPIO_QUAL_ASYNC); + GPIO_setDirectionMode(GPIO_18, GPIO_DIR_MODE_IN); + + GPIO_setPinConfig(GPIO_20_QSPI_D3); + GPIO_setAnalogMode(GPIO_20, GPIO_ANALOG_DISABLED); + GPIO_setPadConfig(GPIO_20, GPIO_PIN_TYPE_PULLUP); + GPIO_setQualificationMode(GPIO_20, GPIO_QUAL_ASYNC); + GPIO_setDirectionMode(GPIO_20, GPIO_DIR_MODE_IN); + + GPIO_setPinConfig(GPIO_21_QSPI_SCLK); + GPIO_setAnalogMode(GPIO_21, GPIO_ANALOG_DISABLED); + GPIO_setPadConfig(GPIO_21, GPIO_PIN_TYPE_PULLUP); + GPIO_setQualificationMode(GPIO_21, GPIO_QUAL_ASYNC); +} + +/*=========================================================================== + * QSPI clock & controller initialization + *===========================================================================*/ +static void qspi_clock_enable(void) +{ + RCC_unlockRccRegister(); + RCC_enableQspiClock(); + RCC_resetQspiModule(); + RCC_releaseQspiModule(); + RCC_lockRccRegister(); +} + +static void qspi_controller_init(void) +{ + QSPI_open(EXTENDED_SPI_PROTOCOL, + HLCK_DIV_48, + ADDRESS_3_BYTES, + DEFAULT_DUMMY_CYCLE, + HIGH_LVL_4_QSCK, + FAST_READ_QUAD_IN_OUT); +} + +/*=========================================================================== + * RT-Thread QSPI device interface + *===========================================================================*/ +static struct rt_spi_bus qspi_bus; +static struct rt_qspi_device qspi_dev; +static struct rt_qspi_configuration qspi_cfg; + +static rt_err_t qspi_configure(struct rt_spi_device *device, + struct rt_spi_configuration *cfg) +{ + device->config = *cfg; + return RT_EOK; +} + +static rt_ssize_t qspi_xfer(struct rt_spi_device *device, + struct rt_spi_message *message) +{ + struct rt_qspi_message *qspi_msg = rt_container_of(message, struct rt_qspi_message, parent); + uint8_t *send_buf = (uint8_t *)message->send_buf; + uint8_t *recv_buf = (uint8_t *)message->recv_buf; + uint32_t send_len = (send_buf != NULL) ? message->length : 0; + uint32_t recv_len = (recv_buf != NULL) ? message->length : 0; + + /* Build command buffer (instruction + address + dummy) */ + uint8_t cmd_buf[260]; + uint8_t *ptr = cmd_buf; + + if (qspi_msg->instruction.content) + *ptr++ = qspi_msg->instruction.content; + + if (qspi_msg->address.size) { + uint32_t addr = qspi_msg->address.content; + uint8_t addr_bytes = qspi_msg->address.size / 8; + for (uint8_t i = addr_bytes; i > 0; i--) + *ptr++ = (addr >> (8*(i-1))) & 0xFF; + } + + if (qspi_msg->dummy_cycles) { + uint8_t dummy_bytes = qspi_msg->dummy_cycles / 8; + for (uint8_t i = 0; i < dummy_bytes; i++) + *ptr++ = 0xFF; + } + + uint32_t cmd_len = ptr - cmd_buf; + + /* Execute transfer using direct API */ + if (send_len && recv_len) { + /* Half-duplex not supported in this driver */ + return 0; + } + + if (send_len) { + /* Append send data to command buffer */ + if (cmd_len + send_len <= sizeof(cmd_buf)) { + rt_memcpy(ptr, send_buf, send_len); + QSPI_writeDirect(cmd_buf, cmd_len + send_len, 0); + } else { + /* Not enough buffer, split into two writes? Not needed for normal use */ + return 0; + } + } else if (recv_len) { + /* Write command, keep CS active, then read data */ + QSPI_writeDirect(cmd_buf, cmd_len, 1); + QSPI_readDirect(recv_buf, recv_len); + } else { + /* No data phase, just send command */ + QSPI_writeDirect(cmd_buf, cmd_len, 0); + } + + return message->length; +} + +static const struct rt_spi_ops qspi_ops = { + .configure = qspi_configure, + .xfer = qspi_xfer, +}; + +/*=========================================================================== + * Initialization + *===========================================================================*/ +int rt_hw_qspi_init(void) +{ + rt_kprintf("Initializing QSPI...\n"); + qspi_clock_enable(); + qspi_pin_init(); + qspi_controller_init(); + + qspi_cfg.parent.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB; + qspi_cfg.parent.max_hz = 25000000; + qspi_cfg.parent.data_width = 8; + qspi_cfg.medium_size = 0x1000000; + qspi_cfg.ddr_mode = 0; + qspi_cfg.qspi_dl_width = 0; + + rt_qspi_bus_register(&qspi_bus, "qspi0", &qspi_ops); + + qspi_dev.parent.bus = &qspi_bus; + qspi_dev.parent.config = qspi_cfg.parent; + qspi_dev.config = qspi_cfg; + rt_spi_bus_attach_device(&qspi_dev.parent, "qspi_dev", "qspi0", NULL); + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_qspi_init); + +#endif \ No newline at end of file diff --git a/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.h b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.h new file mode 100644 index 0000000000..50a0ec6833 --- /dev/null +++ b/bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_qspi.h @@ -0,0 +1,21 @@ +#ifndef __DRV_QSPI_H__ +#define __DRV_QSPI_H__ + +#ifdef RT_USING_QSPI + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int rt_hw_qspi_init(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* __DRV_QSPI_H__ */ \ No newline at end of file diff --git a/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig b/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig index fa348a7a18..b11c36a4ee 100644 --- a/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig +++ b/bsp/novosns/ns800/ns800rt7p65-nssinepad/board/Kconfig @@ -200,5 +200,10 @@ menu "On-chip Peripheral Drivers" bool "Enable SPI4" default n endif + + menuconfig BSP_USING_QSPI + bool "Enable QSPI" + select RT_USING_QSPI + default n endmenu diff --git a/bsp/novosns/ns800/ns800rt7p65-nssinepad/rtconfig.h b/bsp/novosns/ns800/ns800rt7p65-nssinepad/rtconfig.h index 9300af36c6..d2df0f5aee 100644 --- a/bsp/novosns/ns800/ns800rt7p65-nssinepad/rtconfig.h +++ b/bsp/novosns/ns800/ns800rt7p65-nssinepad/rtconfig.h @@ -423,6 +423,7 @@ #define BSP_USING_UART1 #define BSP_USING_CAN #define BSP_USING_CANFD1 +#define BSP_USING_QSPI /* end of On-chip Peripheral Drivers */ #endif -- Gitee