summaryrefslogtreecommitdiff
path: root/bsp
diff options
context:
space:
mode:
author来一颗糖 <[email protected]>2022-03-07 12:05:53 +0800
committerGitHub <[email protected]>2022-03-07 12:05:53 +0800
commit532d898e71adf13eb880e7bfb598c35cc7b0f92a (patch)
tree3a3b3bbc16683a981998dfb71a23c1b3abe62674 /bsp
parent52d0dc691cf49828d49f835f2289424402aca8f1 (diff)
[bsp/n32g452xx] add drv_spi.c (#5640)
Diffstat (limited to 'bsp')
-rw-r--r--bsp/n32g452xx/Libraries/rt_drivers/drv_spi.c370
-rw-r--r--bsp/n32g452xx/Libraries/rt_drivers/drv_spi.h34
2 files changed, 404 insertions, 0 deletions
diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_spi.c b/bsp/n32g452xx/Libraries/rt_drivers/drv_spi.c
new file mode 100644
index 0000000000..237b457668
--- /dev/null
+++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_spi.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-03-06 BalanceTWK first version
+ */
+
+#include <board.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#ifdef RT_USING_SPI
+#ifdef BSP_USING_SPI
+
+#if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) || defined(BSP_USING_SPI4) || defined(BSP_USING_SPI5) || defined(BSP_USING_SPI6)
+
+#include "drv_spi.h"
+#define DRV_DEBUG
+#define LOG_TAG "drv.spi"
+#include <drv_log.h>
+
+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
+#ifdef BSP_USING_SPI5
+ SPI5_INDEX,
+#endif
+#ifdef BSP_USING_SPI6
+ SPI6_INDEX,
+#endif
+};
+
+struct n32_spi_config
+{
+ SPI_Module *module;
+ char *bus_name;
+};
+/* n32 spi dirver class */
+struct n32_spi
+{
+ SPI_InitType SPI_InitStructure;
+ struct n32_spi_config *config;
+ struct rt_spi_configuration *cfg;
+
+ struct rt_spi_bus spi_bus;
+};
+
+static struct n32_spi_config spi_config[] =
+{
+#ifdef BSP_USING_SPI1
+ {
+ .module = SPI1,
+ .bus_name = "spi1",
+ },
+#endif
+
+#ifdef BSP_USING_SPI2
+ {
+ .module = SPI2,
+ .bus_name = "spi2",
+ },
+#endif
+
+#ifdef BSP_USING_SPI3
+ {
+ .module = SPI3,
+ .bus_name = "spi3",
+ },
+#endif
+
+};
+
+static struct n32_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0};
+
+static rt_err_t n32_spi_init(struct n32_spi *spi_drv, struct rt_spi_configuration *cfg)
+{
+ RT_ASSERT(spi_drv != RT_NULL);
+ RT_ASSERT(cfg != RT_NULL);
+
+ SPI_InitType *SPI_InitStructure = &spi_drv->SPI_InitStructure;
+
+ /* GPIO configuration ------------------------------------------------------*/
+ n32_msp_spi_init(spi_drv->config->module);
+
+ if (cfg->mode & RT_SPI_SLAVE)
+ {
+ /* SPI_InitStructure->SpiMode = SPI_MODE_SLAVE; */
+ return RT_ERROR;
+ }
+ else
+ {
+ SPI_InitStructure->SpiMode = SPI_MODE_MASTER;
+ }
+
+ if (cfg->mode & RT_SPI_3WIRE)
+ {
+ SPI_InitStructure->DataDirection = SPI_DIR_SINGLELINE_TX;
+ }
+ else
+ {
+ SPI_InitStructure->DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
+ }
+
+ if (cfg->data_width == 8)
+ {
+ SPI_InitStructure->DataLen = SPI_DATA_SIZE_8BITS;
+ }
+ else if (cfg->data_width == 16)
+ {
+ SPI_InitStructure->DataLen = SPI_DATA_SIZE_16BITS;
+ }
+ else
+ {
+ return RT_EIO;
+ }
+
+ if (cfg->mode & RT_SPI_CPHA)
+ {
+ SPI_InitStructure->CLKPHA = SPI_CLKPHA_SECOND_EDGE;
+ }
+ else
+ {
+ SPI_InitStructure->CLKPHA = SPI_CLKPHA_FIRST_EDGE;
+ }
+
+ if (cfg->mode & RT_SPI_CPOL)
+ {
+ SPI_InitStructure->CLKPOL = SPI_CLKPOL_HIGH;
+ }
+ else
+ {
+ SPI_InitStructure->CLKPOL = SPI_CLKPOL_LOW;
+ }
+
+ if (cfg->mode & RT_SPI_NO_CS)
+ {
+ SPI_InitStructure->NSS = SPI_NSS_HARD;
+ }
+ else
+ {
+ SPI_InitStructure->NSS = SPI_NSS_SOFT;
+ }
+
+ /* TODO */
+ /*
+ uint32_t SPI_APB_CLOCK;
+ if (cfg->max_hz >= SPI_APB_CLOCK / 2)
+ {
+ SPI_InitStructure->BaudRatePres = SPI_BAUDRATEPRESCALER_2;
+ }
+ */
+ SPI_InitStructure->BaudRatePres = SPI_BR_PRESCALER_4;
+
+
+ if (cfg->mode & RT_SPI_MSB)
+ {
+ SPI_InitStructure->FirstBit = SPI_FB_MSB;
+ }
+ else
+ {
+ SPI_InitStructure->FirstBit = SPI_FB_LSB;
+ }
+
+ SPI_InitStructure->CRCPoly = 7;
+
+ SPI_Init(spi_drv->config->module, SPI_InitStructure);
+ /* Enable SPI_MASTER TXE interrupt */
+ SPI_I2S_EnableInt(spi_drv->config->module, SPI_I2S_INT_TE, ENABLE);
+
+ /* Enable SPI_MASTER */
+ SPI_Enable(spi_drv->config->module, ENABLE);
+
+ return RT_EOK;
+}
+
+static rt_err_t spi_configure(struct rt_spi_device *device,
+ struct rt_spi_configuration *configuration)
+{
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(configuration != RT_NULL);
+
+ struct n32_spi *spi_drv = rt_container_of(device->bus, struct n32_spi, spi_bus);
+ spi_drv->cfg = configuration;
+
+ return n32_spi_init(spi_drv, configuration);
+}
+
+static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
+{
+ rt_size_t message_length, already_length;
+ rt_uint8_t *recv_buf;
+ const rt_uint8_t *send_buf;
+
+ RT_ASSERT(device != RT_NULL);
+ RT_ASSERT(device->bus != RT_NULL);
+ RT_ASSERT(device->bus->parent.user_data != RT_NULL);
+ RT_ASSERT(message != RT_NULL);
+
+ struct n32_spi *spi_drv = rt_container_of(device->bus, struct n32_spi, spi_bus);
+ struct n32_hw_spi_cs *cs = device->parent.user_data;
+
+ if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS))
+ {
+ if (device->config.mode & RT_SPI_CS_HIGH)
+ GPIO_SetBits(cs->module, cs->pin);
+ else
+ GPIO_ResetBits(cs->module, cs->pin);
+ }
+
+ message_length = message->length;
+ recv_buf = message->recv_buf;
+ send_buf = message->send_buf;
+ for (already_length = 0; already_length < message_length; )
+ {
+ /* start once data exchange in DMA mode */
+ if (message->send_buf && message->recv_buf)
+ {
+ LOG_D("%s:%d",__FUNCTION__,__LINE__);
+ }
+ else if (message->send_buf)
+ {
+ /* Wait for SPIy Tx buffer empty */
+ while (SPI_I2S_GetStatus(spi_drv->config->module, SPI_I2S_TE_FLAG) == RESET);
+
+ SPI_I2S_TransmitData(spi_drv->config->module, (send_buf[already_length]));
+ }
+ else
+ {
+ /* Wait for SPIy data reception */
+ while (SPI_I2S_GetStatus(spi_drv->config->module, SPI_I2S_RNE_FLAG) == RESET);
+ /* Read SPIy received data */
+ recv_buf[already_length] = (rt_uint8_t)SPI_I2S_ReceiveData(spi_drv->config->module);
+ }
+ already_length ++;
+ }
+
+ if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS))
+ {
+ if (device->config.mode & RT_SPI_CS_HIGH)
+ GPIO_ResetBits(cs->module, cs->pin);
+ else
+ GPIO_SetBits(cs->module, cs->pin);
+ }
+
+ return message->length;
+}
+
+static const struct rt_spi_ops n32_spi_ops =
+{
+ .configure = spi_configure,
+ .xfer = spixfer,
+};
+
+static int rt_hw_spi_bus_init(void)
+{
+ rt_err_t result;
+ for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++)
+ {
+ spi_bus_obj[i].config = &spi_config[i];
+ spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i];
+ result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &n32_spi_ops);
+ RT_ASSERT(result == RT_EOK);
+
+ LOG_D("%s bus init done", spi_config[i].bus_name);
+ }
+
+ return result;
+}
+int rt_hw_spi_init(void)
+{
+ /* TODO: n32_get_dma_info(); */
+ return rt_hw_spi_bus_init();
+}
+INIT_BOARD_EXPORT(rt_hw_spi_init);
+
+
+/**
+ * Attach the spi device to SPI bus, this function must be used after initialization.
+ */
+rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_Module *cs_gpiox, uint32_t cs_gpio_pin)
+{
+ rt_err_t result;
+ struct rt_spi_device *spi_device;
+ struct n32_hw_spi_cs *cs_pin;
+ GPIO_InitType GPIO_InitStructure;
+
+ RT_ASSERT(bus_name != RT_NULL);
+ RT_ASSERT(device_name != RT_NULL);
+
+
+ /* Enable the GPIO Clock */
+ if (cs_gpiox == GPIOA)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
+ }
+ else if (cs_gpiox == GPIOB)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
+ }
+ else if (cs_gpiox == GPIOC)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
+ }
+ else if (cs_gpiox == GPIOD)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE);
+ }
+ else if (cs_gpiox == GPIOE)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE);
+ }
+ else if (cs_gpiox == GPIOF)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF, ENABLE);
+ }
+ else if (cs_gpiox == GPIOG)
+ {
+ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOG, ENABLE);
+ }
+
+ /* Configure the GPIO pin */
+ if (cs_gpio_pin <= GPIO_PIN_ALL)
+ {
+ GPIO_InitStructure.Pin = cs_gpio_pin;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitPeripheral(cs_gpiox, &GPIO_InitStructure);
+ }
+
+ /* attach the device to spi bus*/
+ spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
+ RT_ASSERT(spi_device != RT_NULL);
+ cs_pin = (struct n32_hw_spi_cs *)rt_malloc(sizeof(struct n32_hw_spi_cs));
+ RT_ASSERT(cs_pin != RT_NULL);
+ cs_pin->module = cs_gpiox;
+ cs_pin->pin = cs_gpio_pin;
+
+ result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
+
+ if (result != RT_EOK)
+ {
+ LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
+ }
+
+ RT_ASSERT(result == RT_EOK);
+
+ LOG_D("%s attach to %s done", device_name, bus_name);
+
+ return result;
+}
+
+#endif /* BSP_USING_SPIx */
+
+#endif /* BSP_USING_SPI */
+#endif /* RT_USING_SPI */
+
diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_spi.h b/bsp/n32g452xx/Libraries/rt_drivers/drv_spi.h
new file mode 100644
index 0000000000..50a34cbec7
--- /dev/null
+++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_spi.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-03-06 BalanceTWK first version
+ */
+
+#ifndef __SPI_CONFIG_H__
+#define __SPI_CONFIG_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <n32g45x.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct n32_hw_spi_cs
+{
+ GPIO_Module* module;
+ uint32_t pin;
+};
+
+rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_Module *cs_gpiox, uint32_t cs_gpio_pin);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SPI_CONFIG_H__ */