[BSP][NS800RT7P65] Add QSPI driver for NS800RT7xxx#11449

This commit is contained in:
rcitach
2026-06-11 11:29:05 +08:00
committed by GitHub
parent 9ed61540ac
commit c9926502b0
5 changed files with 229 additions and 3 deletions
@@ -27,6 +27,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)
@@ -0,0 +1,193 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2026-05-17 lugl first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#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
@@ -0,0 +1,22 @@
#ifndef __DRV_QSPI_H__
#define __DRV_QSPI_H__
#ifdef RT_USING_QSPI
#include <rtthread.h>
#include <rtdevice.h>
#ifdef __cplusplus
extern "C" {
#endif
int rt_hw_qspi_init(void);
#ifdef __cplusplus
}
#endif
#endif
#endif /* __DRV_QSPI_H__ */
@@ -6,9 +6,13 @@ devices.ecap:
kconfig:
- CONFIG_BSP_USING_ECAP=y
- CONFIG_BSP_USING_ECAP1=y
- CONFIG_BSP_USING_SPI=y
- CONFIG_BSP_USING_SPI1=y
devices.adc:
<<: *scons
kconfig:
- CONFIG_BSP_USING_ADC=y
- CONFIG_BSP_USING_ADC=y
devices.spi:
<<: *scons
kconfig:
- CONFIG_BSP_USING_SPI=y
- CONFIG_BSP_USING_SPI1=y
- CONFIG_BSP_USING_QSPI=y
@@ -205,5 +205,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