文件路径: /drivers/board.h
/*-------------------------- QSPI CONFIG BEGIN --------------------------*/
/** if you want to use qspi you can use the following instructions.
*
* STEP 1, open qspi driver framework support in the RT-Thread Settings file
*
* STEP 2, define macro related to the qspi
* such as #define BSP_USING_QSPI
*
* STEP 3, copy your qspi init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
* such as void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)
*
* STEP 4, modify your stm32xxxx_hal_config.h file to support qspi peripherals. define macro related to the peripherals
* such as #define HAL_QSPI_MODULE_ENABLED
*
*/
#define BSP_USING_QSPI
注释中详细描述了qspi配置过程,
|
|---->设备驱动程序
| |---->使能SPI总线/设备驱动程序 √
| |---->使能QSPI模式 √
通过 stm32cubemx工具使能qspi硬件,在一下路径
\Core\Src\stm32f7xx_hal_msp.c中将HAL_QSPI_MspInit拷贝到 /drivers/board.c中
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(qspiHandle->Instance==QUADSPI)
{
/* QUADSPI clock enable */
__HAL_RCC_QSPI_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**QUADSPI GPIO Configuration
PE2 ------> QUADSPI_BK1_IO2
PB2 ------> QUADSPI_CLK
PB10 ------> QUADSPI_BK1_NCS
PD11 ------> QUADSPI_BK1_IO0
PD12 ------> QUADSPI_BK1_IO1
PD13 ------> QUADSPI_BK1_IO3
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
}
烧录,在串口终端输入**/demo>list_device**
qspi1 SPI Bus 0
uart1 Character Device 2
pin Miscellaneous Device 0
可以看到spi总线
/**
* 读取qspi状态寄存器2
* @param device : qspi设备
* @return
*/
char w25qxx_read_status_register2(struct rt_qspi_device *device)
{
/* 0x35 read status register2 */
char instruction = 0x35, status;
rt_qspi_send_then_recv(device, &instruction, 1, &status, 1);//读取状态寄存器
return status;
}
/**
* qspi写使能
* @param device : qspi设备
*/
void w25qxx_write_enable(struct rt_qspi_device *device)
{
/* 0x06 write enable */
char instruction = 0x06;
rt_qspi_send(device, &instruction, 1);//发送数据
}
/**
* 使能qspi模式
* @param device : qspi设备
*/
void w25qxx_enter_qspi_mode(struct rt_qspi_device *device)
{
char status = 0;
/* 0x38 enter qspi mode */
char instruction = 0x38;
char write_status2_buf[2] = {0};
/* 0x31 write status register2 */
write_status2_buf[0] = 0x31;
status = w25qxx_read_status_register2(device);//读取状态寄存器2
if (!(status & 0x02))//判读当前flash通信模式
{
status |= 1 << 1;
w25qxx_write_enable(device); //w25q写使能
write_status2_buf[1] = status; //写状态寄存器
rt_qspi_send(device, &write_status2_buf, 2);//
rt_qspi_send(device, &instruction, 1);//设置qspi模式
rt_kprintf("flash already enter qspi mode\n");
rt_thread_mdelay(10);
}
}
/**
*挂在设备到qspi总线上
* @return 挂载状态
*/
static rt_err_t rt_hw_qspi_flash_with_sfud_init(void)
{
/*W25Q256挂在qspi总线上*/
rt_err_t ret = stm32_qspi_bus_attach_device("qspi1", "qspi10", RT_NULL, 4, w25qxx_enter_qspi_mode, RT_NULL);
if (ret != RT_EOK)
{
rt_kprintf("qspi attach device failed\n");
return -RT_ERROR;
}
rt_kprintf("qspi attach device success\n");
return RT_EOK;
}
/*设备自动初始化 */
INIT_DEVICE_EXPORT(rt_hw_qspi_flash_with_sfud_init);
device type ref count
-------- -------------------- ----------
qspi10 SPI Device 0
qspi1 SPI Bus 0
uart1 Character Device 2
pin Miscellaneous Device 0
- 设备id读取测试
```c
#define W25Q_SPI_DEVICE_NAME "qspi10"
static void qspi_w25q_sample(int argc, char *argv[])
{
struct rt_spi_device *qspi_dev_w25q;
char name[RT_NAME_MAX];
rt_uint8_t w25x_read_id = 0x90;
rt_uint8_t id[5] = {0};
if (argc == 2)
{
rt_strncpy(name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX);
}
/* 查找 spi 设备获取设备句柄 */
qspi_dev_w25q = (struct rt_spi_device *)rt_device_find(name);//根据 SPI 设备名称查找设备获取设备句柄
if (!qspi_dev_w25q)
{
rt_kprintf("qspi sample run failed! can't find %s device!\n", name);
}
else
{
/* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */
rt_qspi_send_then_recv(qspi_dev_w25q, &w25x_read_id, 1, id, 5);//先发送后接收数据id
rt_kprintf("use rt_qspi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]);
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(qspi_w25q_sample, qspi w25q sample);
可以看到spi总线 和 QSPI设备
|
|---->设备驱动程序
| |---->使能SPI总线/设备驱动程序 √
| |---->使能QSPI模式 √
| |---->使能串行Flash通用驱动程序(SFUD) √
| |---->使能QSPI模式 √
| |---->使能自动探针探测Flsh JEDEC SFDP √
| |---->使能Flash 芯片信息表 √
/**
* 创建块设备
* @return
*/
static int rt_hw_qspi_block_device_init(void)
{
/* W25Q256 注册为快设备*/
if (RT_NULL == rt_sfud_flash_probe("W25Q256", "qspi10"))
{
rt_kprintf("flash sfud failed\n");
return -RT_ERROR;
}
rt_kprintf("flash sfud success\n");
return RT_EOK;
}
/*设备自动初始化 */
INIT_DEVICE_EXPORT(rt_hw_qspi_block_device_init);
device type ref count
-------- -------------------- ----------
W25Q256 Block Device 0
qspi10 SPI Device 0
qspi1 SPI Bus 0
uart1 Character Device 2
pin Miscellaneous Device 0
可以看到spi总线 和 QSPI设备 快设备
|
|---->设备虚拟文件系统
| |---->使能设备虚拟文件系统 √
| |---->使能elm chan FatFs √
| |---->elm chan 的FatFs,通用Fat 文件系统模块
| |---->设置要处理的最大扇区大小 4096(根据flash参数决定)
static int mnt_init(void)
{
dfs_mkfs("elm", "W25Q256");//格式化设备
if(dfs_mount("W25Q256", "/", "elm", 0, 0)==0)//挂载文件
{
rt_kprintf("dfs mount success\r\n");
return RT_EOK;
}else {
rt_kprintf("dfs mount failed\r\n");
return -RT_ERROR;
}
}
/* 组件自动初始化 */
INIT_COMPONENT_EXPORT(mnt_init);
注意:
挂载文件系统过程中可能出现
[E/DFS] File system (elm) was not found.
是由于程序先执行了挂载文件系统,但是文件系统并未准备完成
INIT_COMPONENT_EXPORT(elm_init);
可以可能到elm的初始化也是在组件层,,因此挂载文件系统可以将其改为应用自动初始化
INIT_APP_EXPORT(mnt_init);
Directory /: