前言
stm32mp157 的 QSPI 启动网上没有相关教程,官方文档只找到了相关说明,更具体的没发现。本文旨在学习、记录与分享。
https://wiki.st.com/stm32mpu/wiki/STM32MP15_ROM_code_overview
https://wiki.st.com/stm32mpu/wiki/QUADSPI_device_tree_configuration
https://wiki.st.com/stm32mpu/wiki/STM32MP15_Flash_mapping
stm32mp157 的 QSPI 启动比较坑,实测启动时,只有 MISO 引脚有数据输出,实际启动为 SPI 启动,故读出 uboot 时,速度较慢。而在进入 linux 系统后,初始化 QSPI FLASH 后,使用的确实是 QSPI 接口,SPI nor-Flash 芯片前后模式不一致也就造成了一个问题,直接按复位键或者使用 reboot 命令无法重启系统,只能下电后重新上电。
文件修改
- 将 u-boot 配置修改成 QSPI 启动, 环境变量存储改成 Environment is in SPI flash
- 在
/include/configs/stm32mp1.h
文件添加如下内容
#ifdef CONFIG_STM32_QSPI
# define CONFIG_SYS_FLASH_BASE 0x70000000
# define CONFIG_SYS_FLASH_SIZE (32 * 1024 * 1024)
# define CONFIG_SYS_MAX_FLASH_BANKS 1
# define CONFIG_SYS_MAX_FLASH_SECT 512
# define CONFIG_SYS_FLASH_ERASE_TOUT 1000
# define CONFIG_SYS_FLASH_WRITE_TOUT 5000
# define CONFIG_FLASH_SHOW_PROGRESS 10
#endif /* #ifdef CONFIG_STM32_QSPI*/
/* Environment */
#ifndef CONFIG_ENV_IS_NOWHERE
# define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE * 16
# ifndef CONFIG_ENV_OFFSET
# define CONFIG_ENV_OFFSET 0x170000
# endif
#endif
查看手册,QYADSPI 地址为 0x70000000~0x7FFFFFFF
,故 CONFIG_SYS_FLASH_BASE
值为 0x70000000
SPI nor-Flash 芯片为 32MB。环境变量偏移 0x170000。
- uboot 设备树修改,在
aliases
中添加spi0
,同时添加&qspi
内容,如下:
{
aliases {
...
spi0 = &qspi;
};
...
}
&qspi {
u-boot,dm-spl;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
reg = <0x58003000 0x1000>, <0x70000000 0x2000000>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
flash0: n25q256a@0 {
u-boot,dm-spl;
compatible = "jedec,spi-nor";
reg = <0>;
spi-rx-bus-width = <4>;
spi-max-frequency = <108000000>;
#address-cells = <1>;
#size-cells = <1>;
};
};
修改完成后,将固件通过网口烧写到 SPI nor-Flash 芯片上,重启,可看到系统启动(注:由于启动使用 SPI 方式,故需要拉高 Flash 芯片的7脚,否则每次上电需要按复位键启动
):
注
由于 SPI nor-Flash 芯片前后模式不一致,故重启使用 reboot
命令不好使,可在内核中修改 SPI nor-Flash 芯片的驱动文件,在 m25p_shutdown
函数中添加 SPI nor-Flash 芯片的复位,本文使用MT25QL256
芯片,故写入 0x66
与 0x99
进行复位(不同产家芯片复位操作有所不同,如 s25fl256s 芯片写入 0xF0 复位
)。
static void m25p_shutdown(struct spi_mem *spimem)
{
struct m25p *flash = spi_mem_get_drvdata(spimem);
printk(KERN_INFO "reset qspi flash \n");
m25p80_write_reg(&flash->spi_nor, 0x66, NULL, 0); //reset nor flash
m25p80_write_reg(&flash->spi_nor, 0x99, NULL, 0);
}
重新编译并烧录后,进入系统,输入reboot
命令就可以正常重启系统了,复位键不好用无法通过软件解决。