123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- /*
- * Copyright (c) 2006-2018, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-3-30 bluebear233 first version
- */
- #include "NuMicro.h"
- #include <rtdevice.h>
- #ifdef RT_USING_SPI
- /* Private Define ---------------------------------------------------------------*/
- #define USEING_QSPI0
- /* Private Typedef --------------------------------------------------------------*/
- struct m487_qspi
- {
- struct rt_spi_bus dev;
- struct rt_spi_configuration configuration;
- QSPI_T *spi_base;
- rt_uint8_t init_gpio:1;
- };
- /* Private functions ------------------------------------------------------------*/
- static rt_err_t m487_qspi_bus_configure(struct rt_spi_device *device,
- struct rt_spi_configuration *configuration);
- static rt_uint32_t m487_qspi_bus_xfer(struct rt_spi_device *device,
- struct rt_spi_message *message);
- /* Private Variables ------------------------------------------------------------*/
- struct rt_spi_ops m487_spi_poll_ops =
- {
- .configure = m487_qspi_bus_configure,
- .xfer = m487_qspi_bus_xfer,
- };
- #ifdef USEING_QSPI0
- static struct m487_qspi qspi0 =
- {
- .spi_base = QSPI0,
- };
- #endif
- static rt_err_t m487_qspi_bus_configure(struct rt_spi_device *device,
- struct rt_spi_configuration *configuration) {
- struct m487_qspi *spi;
- uint32_t u32QSPIMode;
- uint32_t u32BusClock;
- rt_uint8_t init_bus;
- spi = (struct m487_qspi *) device->bus;
- init_bus = 0;
- if (!spi->init_gpio)
- {
- spi->init_gpio = 1;
- init_bus = 1;
- if(spi->spi_base == QSPI0)
- {
- /* Select PCLK0 as the clock source of QSPI0 */
- CLK_SetModuleClock(QSPI0_MODULE, CLK_CLKSEL2_QSPI0SEL_PLL,
- MODULE_NoMsk);
- /* Enable QSPI0 peripheral clock */
- CLK_EnableModuleClock(QSPI0_MODULE);
- /* Setup QSPI0 multi-function pins */
- SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk
- | SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk);
- SYS->GPC_MFPL |= SYS_GPC_MFPL_PC0MFP_QSPI0_MOSI0 | SYS_GPC_MFPL_PC1MFP_QSPI0_MISO0
- | SYS_GPC_MFPL_PC2MFP_QSPI0_CLK | SYS_GPC_MFPL_PC3MFP_QSPI0_SS;
- /* Enable SPI0 clock pin (PC2) schmitt trigger */
- PC->SMTEN |= GPIO_SMTEN_SMTEN2_Msk;
- }
- }
- if(rt_memcmp(configuration, &spi->configuration, sizeof(*configuration)) != 0)
- {
- rt_memcpy(&spi->configuration, configuration, sizeof(*configuration));
- init_bus = 1;
- }
- if(init_bus)
- {
- switch(configuration->mode & RT_SPI_MODE_3)
- {
- case RT_SPI_MODE_0:u32QSPIMode = QSPI_MODE_0;break;
- case RT_SPI_MODE_1:u32QSPIMode = QSPI_MODE_1;break;
- case RT_SPI_MODE_2:u32QSPIMode = QSPI_MODE_2;break;
- case RT_SPI_MODE_3:u32QSPIMode = QSPI_MODE_3;break;
- default:RT_ASSERT(0);
- }
- u32BusClock = configuration->max_hz;
- if(u32BusClock > 50*1000*1000)
- {
- u32BusClock = 50*1000*1000;
- }
- QSPI_Open(spi->spi_base, QSPI_MASTER, u32QSPIMode, configuration->data_width, u32BusClock);
- QSPI_EnableAutoSS(spi->spi_base, QSPI_SS, QSPI_SS_ACTIVE_LOW);
- if(configuration->mode & RT_SPI_MSB)
- {
- QSPI_SET_MSB_FIRST(spi->spi_base);
- }
- else
- {
- QSPI_SET_LSB_FIRST(spi->spi_base);
- }
- }
- return RT_EOK;
- }
- /**
- * @brief SPI bus 轮询
- * @param dev : SPI总线设备结构体指针
- * @param send_addr : 发送缓冲区地址
- * @param recv_addr : 接收缓冲区地址
- * @param length : 数据长度
- */
- static void qspi_transmission_with_poll(struct m487_qspi *spi_bus,
- const uint8_t *send_addr, uint8_t *recv_addr, int length)
- {
- QSPI_T *spi_base = spi_bus->spi_base;
- // 写
- if (send_addr != RT_NULL && recv_addr == RT_NULL)
- {
- while (length--)
- {
- // 等待TX FIFO 为空
- while(QSPI_GET_TX_FIFO_FULL_FLAG(spi_base));
- // 输入数据
- QSPI_WRITE_TX(spi_base, *send_addr++);
- }
- // 等待SPI空闲
- while(QSPI_IS_BUSY(spi_base));
- }
- // 读写
- else if (send_addr != RT_NULL && recv_addr != RT_NULL)
- {
- // 清空读FIFO
- if(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- QSPI_ClearRxFIFO(spi_base);
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base));
- }
- while (length--)
- {
- // 等待TX FIFO 为空
- while(QSPI_GET_TX_FIFO_FULL_FLAG(spi_base));
- // 输入数据
- QSPI_WRITE_TX(spi_base, *send_addr++);
- // 读取RX FIFO
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- *recv_addr++ = QSPI_READ_RX(spi_base);
- }
- }
- // 等待SPI空闲
- while(QSPI_IS_BUSY(spi_base))
- {
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- *recv_addr++ = QSPI_READ_RX(spi_base);
- }
- }
- }
- //读
- else
- {
- // 清空读FIFO
- if(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- QSPI_ClearRxFIFO(spi_base);
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base));
- }
- while (length--)
- {
- // 等待TX FIFO 为空
- while(QSPI_GET_TX_FIFO_FULL_FLAG(spi_base));
- // 输入数据
- QSPI_WRITE_TX(spi_base, 0x00);
- // 读取RX FIFO
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- *recv_addr++ = QSPI_READ_RX(spi_base);
- }
- }
- // 等待SPI空闲
- while(QSPI_IS_BUSY(spi_base))
- {
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- *recv_addr++ = QSPI_READ_RX(spi_base);
- }
- }
- while(!QSPI_GET_RX_FIFO_EMPTY_FLAG(spi_base))
- {
- *recv_addr++ = QSPI_READ_RX(spi_base);
- }
- }
- }
- static rt_uint32_t m487_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
- {
- struct m487_qspi *spi;
- spi = (struct m487_qspi *) device->bus;
- if (message->cs_take)
- {
- QSPI_SET_SS_LOW(spi->spi_base);
- }
- if (message->length > 0)
- {
- qspi_transmission_with_poll(spi, message->send_buf,
- message->recv_buf, message->length);
- }
- if (message->cs_release)
- {
- QSPI_SET_SS_HIGH(spi->spi_base);
- }
- return message->length;
- }
- static int m487_qspi_register_bus(struct m487_qspi *spi_bus, const char *name)
- {
- return rt_spi_bus_register(&spi_bus->dev, name, &m487_spi_poll_ops);
- }
- /**
- * 硬件QSPI注册
- */
- static int rt_hw_qspi_init(void)
- {
- #ifdef USEING_QSPI0
- m487_qspi_register_bus(&qspi0, "qspi0");
- #endif
- return 0;
- }
- INIT_DEVICE_EXPORT(rt_hw_qspi_init);
- #endif
|