Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bsp/novosns/ns800/libraries/HAL_Drivers/drivers/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ if GetDepend('BSP_USING_ECAP'):
if GetDepend('BSP_USING_TIM'):
src += ['drv_timer.c']

if GetDepend('BSP_USING_SPI'):
src += ['drv_spi.c']

group = DefineGroup('HAL_Drivers', src, depend = [''], CPPPATH = path)

Return('group')
328 changes: 328 additions & 0 deletions bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_spi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2026-05-12 lugl first version
*/

#include "board.h"
#include "drv_spi.h"
#include "drv_config.h"

#ifdef RT_USING_SPI

#define DRV_DEBUG
#define LOG_TAG "drv.spi"
#include <drv_log.h>

#if !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2) && !defined(BSP_USING_SPI3) && \
!defined(BSP_USING_SPI4)
#error "Please define at least one BSP_USING_SPIx"
#endif

enum
{
#ifdef BSP_USING_SPI1
SPI1_INDEX,
#endif
#ifdef BSP_USING_SPI2
SPI2_INDEX,
#endif
#ifdef BSP_USING_SPI3
SPI3_INDEX,
#endif
#ifdef BSP_USING_SPI4
SPI4_INDEX,
#endif
};

static struct ns800_spi_config spi_config[] =
{
#ifdef BSP_USING_SPI1
{
.name = "spi1",
.Instance = SPI1,
.rx_irq_type = SPI1_RX_IRQn,
.tx_irq_type = SPI1_TX_IRQn,
.sck_port = GPIOA,
.sck_pin = GPIO_PIN_18,
.sck_mux = ALT1_FUNCTION,
.mosi_port = GPIOA,
.mosi_pin = GPIO_PIN_16,
.mosi_mux = ALT1_FUNCTION,
.miso_port = GPIOA,
.miso_pin = GPIO_PIN_17,
.miso_mux = ALT1_FUNCTION,
},
#endif
#ifdef BSP_USING_SPI2
{
.name = "spi2",
.Instance = SPI2,
.rx_irq_type = SPI2_RX_IRQn,
.tx_irq_type = SPI2_TX_IRQn,
.sck_port = GPIOB,
.sck_pin = GPIO_PIN_0,
.sck_mux = ALT9_FUNCTION,
.mosi_port = GPIOB,
.mosi_pin = GPIO_PIN_1,
.mosi_mux = ALT9_FUNCTION,
.miso_port = GPIOB,
.miso_pin = GPIO_PIN_2,
.miso_mux = ALT9_FUNCTION,
},
#endif
#ifdef BSP_USING_SPI3
{
.name = "spi3",
.Instance = SPI3,
.rx_irq_type = SPI3_RX_IRQn,
.tx_irq_type = SPI3_TX_IRQn,
.sck_port = GPIOC,
.sck_pin = GPIO_PIN_0,
.sck_mux = ALT7_FUNCTION,
.mosi_port = GPIOC,
.mosi_pin = GPIO_PIN_1,
.mosi_mux = ALT7_FUNCTION,
.miso_port = GPIOC,
.miso_pin = GPIO_PIN_2,
.miso_mux = ALT7_FUNCTION,
},
#endif
#ifdef BSP_USING_SPI4
{
.name = "spi4",
.Instance = SPI4,
.rx_irq_type = SPI4_RX_IRQn,
.tx_irq_type = SPI4_TX_IRQn,
.sck_port = GPIOC,
.sck_pin = GPIO_PIN_4,
.sck_mux = ALT7_FUNCTION,
.mosi_port = GPIOC,
.mosi_pin = GPIO_PIN_5,
.mosi_mux = ALT7_FUNCTION,
.miso_port = GPIOC,
.miso_pin = GPIO_PIN_6,
.miso_mux = ALT7_FUNCTION,
},
#endif
};

static struct ns800_spi spi_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0};

static void ns800_spi_gpio_init(const struct ns800_spi_config *config)
{
RT_ASSERT(config != RT_NULL);

GPIO_setPinConfig(config->sck_port, config->sck_pin, config->sck_mux);
GPIO_setAnalogMode(config->sck_port, config->sck_pin, GPIO_ANALOG_DISABLED);
GPIO_setPadConfig(config->sck_port, config->sck_pin, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(config->sck_port, config->sck_pin, GPIO_QUAL_SYNC);
GPIO_setDirectionMode(config->sck_port, config->sck_pin, GPIO_DIR_MODE_OUT);

GPIO_setPinConfig(config->mosi_port, config->mosi_pin, config->mosi_mux);
GPIO_setAnalogMode(config->mosi_port, config->mosi_pin, GPIO_ANALOG_DISABLED);
GPIO_setPadConfig(config->mosi_port, config->mosi_pin, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(config->mosi_port, config->mosi_pin, GPIO_QUAL_SYNC);
GPIO_setDirectionMode(config->mosi_port, config->mosi_pin, GPIO_DIR_MODE_OUT);

GPIO_setPinConfig(config->miso_port, config->miso_pin, config->miso_mux);
GPIO_setAnalogMode(config->miso_port, config->miso_pin, GPIO_ANALOG_DISABLED);
GPIO_setPadConfig(config->miso_port, config->miso_pin, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(config->miso_port, config->miso_pin, GPIO_QUAL_SYNC);
GPIO_setDirectionMode(config->miso_port, config->miso_pin, GPIO_DIR_MODE_IN);
}

static rt_err_t ns800_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
{
struct ns800_spi *spi;
SPI_TransferProtocol protocol;
SPI_BitWidth data_width;

RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);

spi = rt_container_of(device->bus, struct ns800_spi, spi_bus);

ns800_spi_gpio_init(spi->config);

switch (configuration->mode & RT_SPI_MODE_3)
{
case RT_SPI_MODE_0:
protocol = SPI_PROT_POL0PHA0;
break;
case RT_SPI_MODE_1:
protocol = SPI_PROT_POL0PHA1;
break;
case RT_SPI_MODE_2:
protocol = SPI_PROT_POL1PHA0;
break;
case RT_SPI_MODE_3:
protocol = SPI_PROT_POL1PHA1;
break;
default:
protocol = SPI_PROT_POL0PHA0;
break;
}

switch (configuration->data_width)
{
case 8:
data_width = SPI_BIT_WIDTH_8_BITS;
break;
case 16:
data_width = SPI_BIT_WIDTH_16_BITS;
break;
default:
data_width = SPI_BIT_WIDTH_8_BITS;
break;
}

SPI_disableModule(spi->config->Instance);

SPI_setConfig(spi->config->Instance,
protocol,
SPI_MASTER_MODE,
SPI_FULL_DUPLEX_COMM_MODE,
configuration->max_hz,
data_width);

SPI_resetFifo(spi->config->Instance);
SPI_enableModule(spi->config->Instance);

return RT_EOK;
}

static rt_ssize_t ns800_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
struct ns800_spi *spi;
SPI_TypeDef *instance;
const rt_uint8_t *send_buf;
rt_uint8_t *recv_buf;
rt_size_t length;

RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);

spi = rt_container_of(device->bus, struct ns800_spi, spi_bus);
instance = spi->config->Instance;
length = message->length;
send_buf = message->send_buf;
recv_buf = message->recv_buf;

if (message->cs_take)
{
rt_pin_write(device->cs_pin, PIN_LOW);
}

while (length)
{
if (send_buf)
{
if (recv_buf)
{
recv_buf[0] = SPI_transmitReceive(instance, send_buf[0]);
recv_buf++;
}
else
{
SPI_transmitReceive(instance, send_buf[0]);
}
send_buf++;
}
else
{
if (recv_buf)
{
recv_buf[0] = SPI_transmitReceive(instance, 0xFF);
recv_buf++;
}
else
{
SPI_transmitReceive(instance, 0xFF);
}
}
length--;
}

if (message->cs_release)
{
rt_pin_write(device->cs_pin, PIN_HIGH);
}

return message->length;
}

static const struct rt_spi_ops ns800_spi_ops =
{
.configure = ns800_spi_configure,
.xfer = ns800_spi_xfer,
};

static void ns800_spi_clock_init(SPI_TypeDef *Instance)
{
#ifdef BSP_USING_SPI1
if (Instance == SPI1)
{
RCC_enableSpi1Clock();
RCC_resetSpi1Module();
RCC_releaseSpi1Module();
}
#endif
#ifdef BSP_USING_SPI2
if (Instance == SPI2)
{
RCC_enableSpi2Clock();
RCC_resetSpi2Module();
RCC_releaseSpi2Module();
}
#endif
#ifdef BSP_USING_SPI3
if (Instance == SPI3)
{
RCC_enableSpi3Clock();
RCC_resetSpi3Module();
RCC_releaseSpi3Module();
}
#endif
#ifdef BSP_USING_SPI4
if (Instance == SPI4)
{
RCC_enableSpi4Clock();
RCC_resetSpi4Module();
RCC_releaseSpi4Module();
}
#endif
}

int rt_hw_spi_init(void)
{
rt_size_t i;
rt_err_t result;

for (i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
{
ns800_spi_clock_init(spi_config[i].Instance);

spi_obj[i].config = &spi_config[i];
spi_obj[i].spi_bus.parent.user_data = &spi_config[i];

result = rt_spi_bus_register(&spi_obj[i].spi_bus,
spi_config[i].name,
&ns800_spi_ops);
if (result != RT_EOK)
{
LOG_E("rt_spi_bus_register(%s) failed: %d", spi_config[i].name, result);
}
}

return RT_EOK;
}

INIT_BOARD_EXPORT(rt_hw_spi_init);

#endif

50 changes: 50 additions & 0 deletions bsp/novosns/ns800/libraries/HAL_Drivers/drivers/drv_spi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2026-05-12 lugl first version
*/

#ifndef __DRV_SPI_H__
#define __DRV_SPI_H__

#include <rtthread.h>
#include "rtdevice.h"
#include <rthw.h>
#include <drv_common.h>

#ifdef RT_USING_SPI

struct ns800_spi_config
{
const char *name;
SPI_TypeDef *Instance;
IRQn_Type rx_irq_type;
IRQn_Type tx_irq_type;
GPIO_TypeDef *sck_port;
GPIO_PinNum sck_pin;
GPIO_AltFunc sck_mux;
GPIO_TypeDef *mosi_port;
GPIO_PinNum mosi_pin;
GPIO_AltFunc mosi_mux;
GPIO_TypeDef *miso_port;
GPIO_PinNum miso_pin;
GPIO_AltFunc miso_mux;
};

struct ns800_spi
{
SPI_TypeDef *Instance;
struct rt_spi_bus spi_bus;
struct ns800_spi_config *config;
};

int rt_hw_spi_init(void);

#endif

#endif /* __DRV_SPI_H__ */

Loading
Loading