基于GD32微控制器通过SPI和QSPI模式读取GD的NOR Flash,并支持DMA模式和文件系统的实现方案:
硬件连接
以GD32F303为例,其SPI接口与NOR Flash的连接方式如下:
- NOR Flash的片选信号(CS)连接到GD32的某个GPIO引脚(如PG14),因为PG14不是SPI的NSS管脚,所以需要使用主机NSS软件模式。
- NOR Flash的SO(数据输出)、SI(数据输入)和SCLK(时钟信号)分别连接到GD32的SPI2_MISO(PB4)、SPI2_MOSI(PB5)和SPI2_CLK(PB3)。
SPI/QSPI初始化
SPI初始化:配置SPI接口的参数,如时钟极性、数据位顺序、帧大小等。例如,设置为全双工模式、8位数据帧格式、硬件NSS管理等。
void driver_spi_init(typdef_spi_struct *spix) { spi_parameter_struct spi_init_struct; rcu_periph_clock_enable(spix->rcu_spi_x); spi_i2s_deinit(spix->spi_x); driver_gpio_general_init(spix->spi_cs_gpio); driver_gpio_general_init(spix->spi_sck_gpio); driver_gpio_general_init(spix->spi_mosi_gpio); driver_gpio_general_init(spix->spi_miso_gpio); if(spix->spi_mode==MODE_DMA) { if(spix->spi_rx_dma!=NULL) { if(spix->frame_size==SPI_FRAMESIZE_8BIT) { driver_dma_com_init(spix->spi_rx_dma,(uint32_t)&SPI_DATA(spix->spi_x),NULL,DMA_Width_8BIT,DMA_PERIPHERAL_TO_MEMORY); } else { driver_dma_com_init(spix->spi_rx_dma,(uint32_t)&SPI_DATA(spix->spi_x),NULL,DMA_Width_16BIT,DMA_PERIPHERAL_TO_MEMORY); } } if(spix->spi_tx_dma!=NULL) { if(spix->frame_size==SPI_FRAMESIZE_8BIT) { driver_dma_com_init(spix->spi_tx_dma,(uint32_t)&SPI_DATA(spix->spi_x),NULL,DMA_Width_8BIT,DMA_MEMORY_TO_PERIPH); } else { driver_dma_com_init(spix->spi_tx_dma,(uint32_t)&SPI_DATA(spix->spi_x),NULL,DMA_Width_16BIT,DMA_MEMORY_TO_PERIPH); } } } spi_struct_para_init(&spi_init_struct); spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; spi_init_struct.device_mode = spix->device_mode; // 其他参数配置... spi_init(spix->spi_x, &spi_init_struct); spi_enable(spix->spi_x); }QSPI初始化:QSPI的初始化与SPI类似,但QSPI支持更多的数据线和更高的传输速率。以GD32H7为例,其QSPI接口支持四线SPI功能,可以显著提高数据传输速率。
NOR Flash读写操作
读取操作:通过SPI或QSPI发送读取指令和地址,然后接收数据。例如,使用SPI读取NOR Flash的代码如下:
void W25QXX_Read(unsigned char* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead) { gpio_bit_reset(GPIOA,GPIO_PIN_4); // 拉低片选信号 QSPI_Send_CMD(W25X_FastReadQuad); // 发送快速读取指令 QSPI_Send_DAT((unsigned char)(ReadAddr>>16)); // 发送地址的高字节 QSPI_Send_DAT((unsigned char)(ReadAddr>>8)); // 发送地址的中字节 QSPI_Send_DAT((unsigned char)ReadAddr); // 发送地址的低字节 QSPI_Receive(pBuffer,NumByteToRead); // 接收数据 gpio_bit_set(GPIOA,GPIO_PIN_4); // 拉高片选信号 }写入操作:写入操作需要先发送写使能指令,然后发送写入指令和地址,最后发送数据。需要注意的是,NOR Flash的写入操作不能跨页,一次最多写入一页。
DMA模式支持
DMA配置:在SPI或QSPI的初始化函数中,配置DMA的相关参数,如内存地址、传输方向、数据宽度等。
if(spix->frame_size==SPI_FRAMESIZE_8BIT) { driver_dma_com_init(spix->spi_rx_dma,(uint32_t)&SPI_DATA(spix->spi_x),NULL,DMA_Width_8BIT,DMA_PERIPHERAL_TO_MEMORY); } else { driver_dma_com_init(spix->spi_rx_dma,(uint32_t)&SPI_DATA(spix->spi_x),NULL,DMA_Width_16BIT,DMA_PERIPHERAL_TO_MEMORY); }DMA传输:在读写操作中,启动DMA传输,DMA会在后台自动完成数据的传输,无需CPU干预,从而提高系统的效率。
文件系统支持
文件系统初始化:使用文件系统(如FATFS)来组织和管理存储在NOR Flash中的数据。首先需要初始化文件系统,挂载存储设备。
FATFS fs; FRESULT res = f_mount(&fs, "", 1); // 挂载文件系统文件操作:通过文件系统提供的API进行文件的创建、读写、删除等操作。例如,创建一个文件并写入数据:
FIL file; res = f_open(&file, "test.txt", FA_CREATE_ALWAYS | FA_WRITE); // 打开文件 if(res == FR_OK) { char data[] = "Hello, GD32!"; f_write(&file, data, sizeof(data), &bytes_written); // 写入数据 f_close(&file); // 关闭文件 }
通过以上步骤,可以实现GD32微控制器通过SPI和QSPI模式读取GD的NOR Flash,并支持DMA模式和文件系统。