|
@@ -1,217 +1,231 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2006-2023, RT-Thread Development Team
|
|
|
+ * Copyright (c) 2006-2024, RT-Thread Development Team
|
|
|
*
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
*
|
|
|
* Change Logs:
|
|
|
* Date Author Notes
|
|
|
- * 2024-03-28 qiujingbao first version
|
|
|
+ * 2024-03-28 qiujingbao first version
|
|
|
+ * 2024/06/08 flyingcys fix transmission failure
|
|
|
*/
|
|
|
|
|
|
+#include <rtthread.h>
|
|
|
+#include <rthw.h>
|
|
|
+#include <rtdevice.h>
|
|
|
+
|
|
|
+#include "board.h"
|
|
|
#include "drv_spi.h"
|
|
|
+
|
|
|
#include "drv_pinmux.h"
|
|
|
|
|
|
-#define DBG_TAG "drv.spi"
|
|
|
-#define DBG_LVL DBG_INFO
|
|
|
+#define DBG_LEVEL DBG_LOG
|
|
|
#include <rtdbg.h>
|
|
|
+#define LOG_TAG "drv.spi"
|
|
|
+
|
|
|
+struct _device_spi
|
|
|
+{
|
|
|
+ struct rt_spi_bus spi_bus;
|
|
|
+ struct dw_spi dws;
|
|
|
+ char *device_name;
|
|
|
+};
|
|
|
|
|
|
-static struct cv1800_spi cv1800_spi_obj[] =
|
|
|
+static struct _device_spi _spi_obj[] =
|
|
|
{
|
|
|
-#ifdef BSP_USING_SPI
|
|
|
+#ifdef BSP_USING_SPI0
|
|
|
{
|
|
|
- .spi_id = SPI2,
|
|
|
+ .dws.regs = (void *)DW_SPI0_BASE,
|
|
|
+ .dws.irq = DW_SPI0_IRQn,
|
|
|
+ .dws.index = 0,
|
|
|
+ .device_name = "spi0",
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_SPI0 */
|
|
|
+#ifdef BSP_USING_SPI1
|
|
|
+ {
|
|
|
+ .dws.regs = (void *)DW_SPI1_BASE,
|
|
|
+ .dws.irq = DW_SPI1_IRQn,
|
|
|
+ .dws.index = 0,
|
|
|
+ .device_name = "spi1",
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_SPI1 */
|
|
|
+#ifdef BSP_USING_SPI2
|
|
|
+ {
|
|
|
+ .dws.regs = (void *)DW_SPI2_BASE,
|
|
|
+ .dws.irq = DW_SPI2_IRQn,
|
|
|
+ .dws.index = 0,
|
|
|
.device_name = "spi2",
|
|
|
- .fifo_len = SPI_TXFTLR,
|
|
|
},
|
|
|
-#endif
|
|
|
+#endif /* BSP_USING_SPI2 */
|
|
|
+#ifdef BSP_USING_SPI3
|
|
|
+ {
|
|
|
+ .dws.regs = (void *)DW_SPI3_BASE,
|
|
|
+ .dws.irq = DW_SPI3_IRQn,
|
|
|
+ .dws.index = 0,
|
|
|
+ .device_name = "spi3",
|
|
|
+ },
|
|
|
+#endif /* BSP_USING_SPI3 */
|
|
|
};
|
|
|
|
|
|
-static struct spi_regs *get_spi_base(uint8_t spi_id)
|
|
|
+static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
|
|
|
{
|
|
|
- struct spi_regs *spi_base = NULL;
|
|
|
+ RT_ASSERT(device != RT_NULL);
|
|
|
+ RT_ASSERT(device->bus != RT_NULL);
|
|
|
+ RT_ASSERT(device->bus->parent.user_data != RT_NULL);
|
|
|
+ RT_ASSERT(cfg != RT_NULL);
|
|
|
+
|
|
|
+ rt_err_t ret = RT_EOK;
|
|
|
+ struct _device_spi *spi = (struct _device_spi *)device->bus->parent.user_data;
|
|
|
+ struct dw_spi *dws = &spi->dws;
|
|
|
+
|
|
|
+ rt_uint8_t mode;
|
|
|
|
|
|
- switch (spi_id)
|
|
|
+ LOG_D("spi_configure input");
|
|
|
+
|
|
|
+ /* set cs low when spi idle */
|
|
|
+ writel(0, (void *)0x030001d0);
|
|
|
+
|
|
|
+ if (cfg->mode & RT_SPI_SLAVE)
|
|
|
{
|
|
|
- case SPI0:
|
|
|
- spi_base = (struct spi_regs *)SPI0_BASE;
|
|
|
- break;
|
|
|
- case SPI1:
|
|
|
- spi_base = (struct spi_regs *)SPI1_BASE;
|
|
|
- break;
|
|
|
- case SPI2:
|
|
|
- spi_base = (struct spi_regs *)SPI2_BASE;
|
|
|
- break;
|
|
|
- case SPI3:
|
|
|
- spi_base = (struct spi_regs *)SPI3_BASE;
|
|
|
- break;
|
|
|
+ LOG_E("invalid mode: %d", cfg->mode);
|
|
|
+ return -RT_EINVAL;
|
|
|
}
|
|
|
|
|
|
- return spi_base;
|
|
|
-}
|
|
|
-
|
|
|
-static rt_err_t drv_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
|
|
|
-{
|
|
|
- rt_err_t ret = RT_EOK;
|
|
|
- struct cv1800_spi *spi_dev = RT_NULL;
|
|
|
- uint32_t mode;
|
|
|
+ spi_reset_chip(dws);
|
|
|
+ spi_hw_init(dws);
|
|
|
+ spi_enable_chip(dws, 0);
|
|
|
|
|
|
- spi_dev = (struct cv1800_spi *)(device->bus->parent.user_data);
|
|
|
+ LOG_D("cfg->max_hz: %d", cfg->max_hz);
|
|
|
+ dw_spi_set_clock(dws, SPI_REF_CLK, cfg->max_hz);
|
|
|
|
|
|
- spi_dev->data_width = configuration->data_width;
|
|
|
+ LOG_D("cfg->data_width: %d", cfg->data_width);
|
|
|
+ if (dw_spi_set_data_frame_len(dws, (uint32_t)cfg->data_width) < 0)
|
|
|
+ {
|
|
|
+ LOG_E("dw_spi_set_data_frame_len failed...\n");
|
|
|
+ return -RT_ERROR;
|
|
|
+ }
|
|
|
|
|
|
- /* disable spi */
|
|
|
- spi_enable(spi_dev->reg, 0);
|
|
|
+ LOG_D("cfg->mode: %08x", cfg->mode);
|
|
|
+ switch (cfg->mode & RT_SPI_MODE_3)
|
|
|
+ {
|
|
|
+ case RT_SPI_MODE_0:
|
|
|
+ mode = SPI_FORMAT_CPOL0_CPHA0;
|
|
|
+ break;
|
|
|
|
|
|
- /* clear irq */
|
|
|
- spi_clear_irq(spi_dev->reg, SPI_IRQ_MSAK);
|
|
|
+ case RT_SPI_MODE_1:
|
|
|
+ mode = SPI_FORMAT_CPOL0_CPHA1;
|
|
|
+ break;
|
|
|
|
|
|
- /* set clk */
|
|
|
- ret = spi_set_frequency(spi_dev->reg, configuration->max_hz);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ case RT_SPI_MODE_2:
|
|
|
+ mode = SPI_FORMAT_CPOL1_CPHA0;
|
|
|
+ break;
|
|
|
|
|
|
- /* set mode */
|
|
|
- ret = gen_spi_mode(configuration, &mode);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ case RT_SPI_MODE_3:
|
|
|
+ mode = SPI_FORMAT_CPOL1_CPHA1;
|
|
|
+ break;
|
|
|
|
|
|
- spi_set_mode(spi_dev->reg, mode);
|
|
|
+ default:
|
|
|
+ LOG_E("spi configure mode error %x\n", cfg->mode);
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- /* set cs */
|
|
|
- spi_enable_cs(spi_dev->reg, 0x1);
|
|
|
+ dw_spi_set_polarity_and_phase(dws, mode);
|
|
|
|
|
|
- spi_enable(spi_dev->reg, 0x1);
|
|
|
+ dw_spi_set_cs(dws, 1, 0);
|
|
|
|
|
|
- mode = mmio_read_32((uintptr_t)&spi_dev->reg->spi_ctrl0);
|
|
|
- LOG_D("mode: %x", mode);
|
|
|
- mode = mmio_read_32((uintptr_t)&spi_dev->reg->spi_baudr);
|
|
|
- LOG_D("spi_baudr: %x", mode);
|
|
|
+ spi_enable_chip(dws, 1);
|
|
|
|
|
|
- return ret;
|
|
|
+ return RT_EOK;
|
|
|
}
|
|
|
|
|
|
-int hw_spi_recv(struct cv1800_spi *dev) {
|
|
|
- uint32_t rever;
|
|
|
- uint32_t tem;
|
|
|
- int ret;
|
|
|
+static rt_err_t dw_spi_transfer_one(struct dw_spi *dws, const void *tx_buf, void *rx_buf, uint32_t len, enum transfer_type tran_type)
|
|
|
+{
|
|
|
+ uint8_t imask = 0;
|
|
|
+ uint16_t txlevel = 0;
|
|
|
|
|
|
- rever = mmio_read_32((uintptr_t)&dev->reg->spi_rxflr);
|
|
|
- ret = (int)rever;
|
|
|
+ dws->tx = NULL;
|
|
|
+ dws->tx_end = NULL;
|
|
|
+ dws->rx = NULL;
|
|
|
+ dws->rx_end = NULL;
|
|
|
|
|
|
- while (rever)
|
|
|
- {
|
|
|
- tem = mmio_read_32((uintptr_t)&dev->reg->spi_dr);
|
|
|
-
|
|
|
- if (dev->recv_buf < dev->recv_end)
|
|
|
- {
|
|
|
- if (dev->data_width == 8)
|
|
|
- *(uint8_t *)(dev->recv_buf) = tem;
|
|
|
- else
|
|
|
- *(uint16_t *)(dev->recv_buf) = tem;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- rever--;
|
|
|
- dev->recv_buf += dev->data_width >> 3;
|
|
|
+ if (tx_buf != NULL) {
|
|
|
+ dws->tx = tx_buf;
|
|
|
+ dws->tx_end = dws->tx + len;
|
|
|
}
|
|
|
- return ret;
|
|
|
-}
|
|
|
|
|
|
-int hw_spi_send(struct cv1800_spi *dev) {
|
|
|
- uint32_t txflr;
|
|
|
- uint32_t max;
|
|
|
- uint16_t value;
|
|
|
+ if (rx_buf != NULL) {
|
|
|
+ dws->rx = rx_buf;
|
|
|
+ dws->rx_end = dws->rx + len;
|
|
|
+ }
|
|
|
+
|
|
|
+ dws->rx_len = len / dws->n_bytes;
|
|
|
+ dws->tx_len = len / dws->n_bytes;
|
|
|
+
|
|
|
+ spi_enable_chip(dws, 0);
|
|
|
+
|
|
|
+ /* For poll mode just disable all interrupts */
|
|
|
+ spi_mask_intr(dws, 0xff);
|
|
|
+
|
|
|
+ /* set tran mode */
|
|
|
+ set_tran_mode(dws);
|
|
|
|
|
|
- txflr = mmio_read_32((uintptr_t)&dev->reg->spi_txflr);
|
|
|
- max = dev->fifo_len - txflr;
|
|
|
+ /* cs0 */
|
|
|
+ dw_spi_set_cs(dws, true, 0);
|
|
|
|
|
|
- while (max)
|
|
|
+ /* enable spi */
|
|
|
+ spi_enable_chip(dws, 1);
|
|
|
+
|
|
|
+ rt_hw_us_delay(10);
|
|
|
+
|
|
|
+ if (tran_type == POLL_TRAN)
|
|
|
+ {
|
|
|
+ if (poll_transfer(dws) < 0)
|
|
|
+ return -RT_ERROR;
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- if (dev->send_end - dev->send_buf)
|
|
|
- {
|
|
|
- if (dev->data_width == 8)
|
|
|
- value = *(uint8_t *)(dev->send_buf);
|
|
|
- else
|
|
|
- value = *(uint16_t *)(dev->send_buf);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- mmio_write_32((uintptr_t)&dev->reg->spi_dr, value);
|
|
|
- dev->send_buf += dev->data_width >> 3;
|
|
|
- max--;
|
|
|
+ return -RT_ENOSYS;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ return RT_EOK;
|
|
|
}
|
|
|
-static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) {
|
|
|
- int ret = 0;
|
|
|
- struct cv1800_spi *spi_dev;
|
|
|
|
|
|
+static rt_ssize_t spi_xfer(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_ASSERT(message != RT_NULL);
|
|
|
|
|
|
- spi_dev = (struct cv1800_spi *)(device->bus->parent.user_data);
|
|
|
+ struct _device_spi *spi = (struct _device_spi *)device->bus->parent.user_data;
|
|
|
+ struct dw_spi *dws = &spi->dws;
|
|
|
+ int32_t ret = 0;
|
|
|
|
|
|
- if (message->send_buf != RT_NULL)
|
|
|
+ if (message->send_buf && message->recv_buf)
|
|
|
{
|
|
|
- spi_dev->send_buf = message->send_buf;
|
|
|
- spi_dev->send_end = (void *)((uint8_t *)spi_dev->send_buf + message->length);
|
|
|
- }
|
|
|
+ ret = dw_spi_transfer_one(dws, message->send_buf, message->recv_buf, message->length, POLL_TRAN);
|
|
|
|
|
|
- if (message->recv_buf != RT_NULL)
|
|
|
- {
|
|
|
- spi_dev->recv_buf = message->recv_buf;
|
|
|
- spi_dev->recv_end = (void *)((uint8_t *)spi_dev->recv_buf + message->length);
|
|
|
}
|
|
|
-
|
|
|
- /* if user use their cs */
|
|
|
- if (message->cs_take && device->cs_pin != PIN_NONE)
|
|
|
- rt_pin_write(device->cs_pin, PIN_LOW);
|
|
|
-
|
|
|
- if (message->send_buf)
|
|
|
+ else if (message->send_buf)
|
|
|
{
|
|
|
- while (spi_dev->send_buf != spi_dev->send_end)
|
|
|
- {
|
|
|
- hw_spi_send(spi_dev);
|
|
|
- }
|
|
|
+ ret = dw_spi_transfer_one(dws, message->send_buf, RT_NULL, message->length, POLL_TRAN);
|
|
|
|
|
|
- /* wait for complete */
|
|
|
- while (mmio_read_32((uintptr_t)&spi_dev->reg->spi_txflr)) {}
|
|
|
-
|
|
|
- ret = message->length;
|
|
|
}
|
|
|
-
|
|
|
- if (message->recv_buf)
|
|
|
+ else if (message->recv_buf)
|
|
|
{
|
|
|
- while (spi_dev->recv_buf != spi_dev->recv_end)
|
|
|
- {
|
|
|
- hw_spi_recv(spi_dev);
|
|
|
- }
|
|
|
+ ret = dw_spi_transfer_one(dws, RT_NULL, message->recv_buf, message->length, POLL_TRAN);
|
|
|
|
|
|
- ret = message->length;
|
|
|
}
|
|
|
|
|
|
- if (message->cs_release && device->cs_pin != PIN_NONE)
|
|
|
- rt_pin_write(device->cs_pin, PIN_HIGH);
|
|
|
-
|
|
|
- return ret;
|
|
|
+ return message->length;
|
|
|
}
|
|
|
|
|
|
-const static struct rt_spi_ops drv_spi_ops =
|
|
|
+static const struct rt_spi_ops _spi_ops =
|
|
|
{
|
|
|
- drv_spi_configure,
|
|
|
- spixfer,
|
|
|
+ .configure = spi_configure,
|
|
|
+ .xfer = spi_xfer,
|
|
|
};
|
|
|
|
|
|
#if defined(BOARD_TYPE_MILKV_DUO) || defined(BOARD_TYPE_MILKV_DUO_SPINOR) || defined(BOARD_TYPE_MILKV_DUO256M) || defined(BOARD_TYPE_MILKV_DUO256M_SPINOR)
|
|
|
-
|
|
|
+// For Duo / Duo 256m, only SPI2 are exported on board.
|
|
|
#ifdef BSP_USING_SPI0
|
|
|
static const char *pinname_whitelist_spi0_sck[] = {
|
|
|
NULL,
|
|
@@ -283,54 +297,49 @@ static const char *pinname_whitelist_spi3_cs[] = {
|
|
|
static void rt_hw_spi_pinmux_config()
|
|
|
{
|
|
|
#ifdef BSP_USING_SPI0
|
|
|
- pinmux_config(BSP_SPI0_SCK_PINNAME, SPI0_SCK, pinname_whitelist_spi0_sck);
|
|
|
- pinmux_config(BSP_SPI0_SDO_PINNAME, SPI0_SDO, pinname_whitelist_spi0_sdo);
|
|
|
- pinmux_config(BSP_SPI0_SDI_PINNAME, SPI0_SDI, pinname_whitelist_spi0_sdi);
|
|
|
- pinmux_config(BSP_SPI0_CS_PINNAME, SPI0_CS_X, pinname_whitelist_spi0_cs);
|
|
|
+ pinmux_config(BSP_SPI0_SCK_PINNAME, SPI0_SCK, pinname_whitelist_spi0_sck);
|
|
|
+ pinmux_config(BSP_SPI0_SDO_PINNAME, SPI0_SDO, pinname_whitelist_spi0_sdo);
|
|
|
+ pinmux_config(BSP_SPI0_SDI_PINNAME, SPI0_SDI, pinname_whitelist_spi0_sdi);
|
|
|
+ pinmux_config(BSP_SPI0_CS_PINNAME, SPI0_CS_X, pinname_whitelist_spi0_cs);
|
|
|
#endif /* BSP_USING_SPI0 */
|
|
|
|
|
|
#ifdef BSP_USING_SPI1
|
|
|
- pinmux_config(BSP_SPI1_SCK_PINNAME, SPI1_SCK, pinname_whitelist_spi1_sck);
|
|
|
- pinmux_config(BSP_SPI1_SDO_PINNAME, SPI1_SDO, pinname_whitelist_spi1_sdo);
|
|
|
- pinmux_config(BSP_SPI1_SDI_PINNAME, SPI1_SDI, pinname_whitelist_spi1_sdi);
|
|
|
- pinmux_config(BSP_SPI1_CS_PINNAME, SPI1_CS_X, pinname_whitelist_spi1_cs);
|
|
|
+ pinmux_config(BSP_SPI1_SCK_PINNAME, SPI1_SCK, pinname_whitelist_spi1_sck);
|
|
|
+ pinmux_config(BSP_SPI1_SDO_PINNAME, SPI1_SDO, pinname_whitelist_spi1_sdo);
|
|
|
+ pinmux_config(BSP_SPI1_SDI_PINNAME, SPI1_SDI, pinname_whitelist_spi1_sdi);
|
|
|
+ pinmux_config(BSP_SPI1_CS_PINNAME, SPI1_CS_X, pinname_whitelist_spi1_cs);
|
|
|
#endif /* BSP_USING_SPI1 */
|
|
|
|
|
|
#ifdef BSP_USING_SPI2
|
|
|
- pinmux_config(BSP_SPI2_SCK_PINNAME, SPI2_SCK, pinname_whitelist_spi2_sck);
|
|
|
- pinmux_config(BSP_SPI2_SDO_PINNAME, SPI2_SDO, pinname_whitelist_spi2_sdo);
|
|
|
- pinmux_config(BSP_SPI2_SDI_PINNAME, SPI2_SDI, pinname_whitelist_spi2_sdi);
|
|
|
- pinmux_config(BSP_SPI2_CS_PINNAME, SPI2_CS_X, pinname_whitelist_spi2_cs);
|
|
|
+ pinmux_config(BSP_SPI2_SCK_PINNAME, SPI2_SCK, pinname_whitelist_spi2_sck);
|
|
|
+ pinmux_config(BSP_SPI2_SDO_PINNAME, SPI2_SDO, pinname_whitelist_spi2_sdo);
|
|
|
+ pinmux_config(BSP_SPI2_SDI_PINNAME, SPI2_SDI, pinname_whitelist_spi2_sdi);
|
|
|
+ pinmux_config(BSP_SPI2_CS_PINNAME, SPI2_CS_X, pinname_whitelist_spi2_cs);
|
|
|
#endif /* BSP_USING_SPI2 */
|
|
|
|
|
|
#ifdef BSP_USING_SPI3
|
|
|
- pinmux_config(BSP_SPI3_SCK_PINNAME, SPI3_SCK, pinname_whitelist_spi3_sck);
|
|
|
- pinmux_config(BSP_SPI3_SDO_PINNAME, SPI3_SDO, pinname_whitelist_spi3_sdo);
|
|
|
- pinmux_config(BSP_SPI3_SDI_PINNAME, SPI3_SDI, pinname_whitelist_spi3_sdi);
|
|
|
- pinmux_config(BSP_SPI3_CS_PINNAME, SPI3_CS_X, pinname_whitelist_spi3_cs);
|
|
|
+ pinmux_config(BSP_SPI3_SCK_PINNAME, SPI3_SCK, pinname_whitelist_spi3_sck);
|
|
|
+ pinmux_config(BSP_SPI3_SDO_PINNAME, SPI3_SDO, pinname_whitelist_spi3_sdo);
|
|
|
+ pinmux_config(BSP_SPI3_SDI_PINNAME, SPI3_SDI, pinname_whitelist_spi3_sdi);
|
|
|
+ pinmux_config(BSP_SPI3_CS_PINNAME, SPI3_CS_X, pinname_whitelist_spi3_cs);
|
|
|
#endif /* BSP_USING_SPI3 */
|
|
|
}
|
|
|
|
|
|
int rt_hw_spi_init(void)
|
|
|
{
|
|
|
rt_err_t ret = RT_EOK;
|
|
|
- struct spi_regs *reg = NULL;
|
|
|
+ struct dw_spi *dws;
|
|
|
|
|
|
rt_hw_spi_pinmux_config();
|
|
|
|
|
|
- for (rt_size_t i = 0; i < sizeof(cv1800_spi_obj) / sizeof(struct cv1800_spi); i++) {
|
|
|
- /* set reg base addr */
|
|
|
- reg = get_spi_base(cv1800_spi_obj[i].spi_id);
|
|
|
- if (!reg)
|
|
|
- return -RT_ERROR;
|
|
|
-
|
|
|
- cv1800_spi_obj[i].reg = reg;
|
|
|
- cv1800_spi_obj[i].spi_bus.parent.user_data = &cv1800_spi_obj[i];
|
|
|
-
|
|
|
- /* register spix bus */
|
|
|
- ret = rt_spi_bus_register(&cv1800_spi_obj[i].spi_bus, cv1800_spi_obj[i].device_name, &drv_spi_ops);
|
|
|
+ for (rt_size_t i = 0; i < sizeof(_spi_obj) / sizeof(struct _device_spi); i++)
|
|
|
+ {
|
|
|
+ _spi_obj[i].spi_bus.parent.user_data = (void *)&_spi_obj[i];
|
|
|
+ ret = rt_spi_bus_register(&_spi_obj[i].spi_bus, _spi_obj[i].device_name, &_spi_ops);
|
|
|
}
|
|
|
|
|
|
+ RT_ASSERT(ret == RT_EOK);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
INIT_BOARD_EXPORT(rt_hw_spi_init);
|