前言
1.环境搭建 Zephyr开发环境搭建记录(Clion)
2. 使用的开发板为正点原子的探索者:mcu使用的是STM32F407ZGT6
3. 本篇参考示例spi_flash
4. 开发环境使用Clion
参考说明
W25Q128部分原理图
W25Q128资料信息
DMA通道映射
参考示例
打开测试项目
项目配置编写(启用FLASH)
CONFIG_LOG=y CONFIG_FLASH=y CONFIG_FLASH_LOG_LEVEL_INF=y设备树覆盖文件编写
- 完整overlay文件配置
/* 探索者开发板LED灯驱动 LED0 PF9 LED1 PF10 ===================w25q128(SPI1)=================== SPI1_MISO == PB4 SPI1_SCK == PB3 SPI1_MOSI == PB5 SPI1_CS == PB14 */// 定义根节点,包含整个设备树的主要配置/{// 配置系统选择项,指定控制台和shell使用的UART接口chosen{// 指定系统控制台使用USART1zephyr,console=&usart1;// 指定shell命令行使用USART1zephyr,shell-uart=&usart1;};// 定义LED设备节点,配置GPIO控制的LEDleds{// 设置兼容性字符串,表示使用GPIO LED驱动compatible="gpio-leds";// 定义第一个LED设备,别名为led_0led_0:led_0{// 配置GPIO引脚为PF9(GPIOF端口第9号引脚),高电平有效gpios=<&gpiof9GPIO_ACTIVE_HIGH>;// PF9// 设置LED的标签名称label="User LED0";};// 定义第二个LED设备,别名为led_1led_1:led_1{// 配置GPIO引脚为PF10(GPIOF端口第10号引脚),高电平有效gpios=<&gpiof10GPIO_ACTIVE_HIGH>;// PF10// 设置LED的标签名称label="User LED1";};};// 定义别名节点,为设备树中的节点提供简短的别名引用aliases{// 将"led0"别名指向led_0节点led0=&led_0;// 将"led1"别名指向led_1节点led1=&led_1;usart1=&usart1;// 将"w25q128"别名指向w25q128节点w25q128=&w25q128;};};&spi1{dmas=<&dma233STM32_DMA_PERIPH_TX STM32_DMA_FIFO_FULL>,<&dma232STM32_DMA_PERIPH_RX STM32_DMA_FIFO_FULL>;dma-names="tx","rx";status="okay";// clk、mosi、misopinctrl-0=<&spi1_sck_pb3&spi1_miso_pb4&spi1_mosi_pb5>;pinctrl-names="default";cs-gpios=<&gpiob14GPIO_ACTIVE_LOW>;w25q128:w25q128@0{compatible="jedec,spi-nor";size=<0x8000000>;reg=<0>;spi-max-frequency=<4000000>;status="okay";jedec-id=[ef4018];};};&dma2{status="okay";};// 引用并修改预定义的usart1节点&usart1{// 配置USART1的引脚控制,TX连接到PA9,RX连接到PA10pinctrl-0=<&usart1_tx_pa9>,<&usart1_rx_pa10>;// 定义引脚控制配置的名称pinctrl-names="default";// 设置串口通信波特率为115200current-speed=<115200>;// 启用此UART外设status="okay";};测试主函数编写
/* * Copyright (c) 2025 Embeint Inc * * SPDX-License-Identifier: Apache-2.0 */#include<zephyr/kernel.h>#include<zephyr/device.h>#include<zephyr/net_buf.h>#include<zephyr/logging/log.h>#include<zephyr/drivers/flash.h>#include<stdio.h>#include<string.h>// SPI测试LOG_MODULE_REGISTER(test,LOG_LEVEL_DBG);#defineSPI_FLASH_TEST_REGION_OFFSET0xff000#defineSPI_FLASH_SECTOR_SIZE4096constuint8_terased[]={0xff,0xff,0xff,0xff};voidsingle_sector_test(conststructdevice*flash_dev){constuint8_texpected[]={0x55,0xaa,0x66,0x99};constsize_tlen=sizeof(expected);uint8_tbuf[sizeof(expected)];intrc;LOG_DBG("\nPerform test on single sector");/* Write protection needs to be disabled before each write or * erase, since the flash component turns on write protection * automatically after completion of write and erase * operations. */LOG_DBG("\nTest 1: Flash erase\n");/* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and * SPI_FLASH_SECTOR_SIZE = flash size */rc=flash_erase(flash_dev,SPI_FLASH_TEST_REGION_OFFSET,SPI_FLASH_SECTOR_SIZE);if(rc!=0){LOG_DBG("Flash erase failed! %d\n",rc);}else{/* Check erased pattern */memset(buf,0,len);rc=flash_read(flash_dev,SPI_FLASH_TEST_REGION_OFFSET,buf,len);if(rc!=0){LOG_DBG("Flash read failed! %d\n",rc);return;}if(memcmp(erased,buf,len)!=0){LOG_DBG("Flash erase failed at offset 0x%x got 0x%x\n",SPI_FLASH_TEST_REGION_OFFSET,*(uint32_t*)buf);return;}LOG_DBG("Flash erase succeeded!\n");}LOG_DBG("\nTest 2: Flash write\n");LOG_DBG("Attempting to write %zu bytes\n",len);rc=flash_write(flash_dev,SPI_FLASH_TEST_REGION_OFFSET,expected,len);if(rc!=0){LOG_DBG("Flash write failed! %d\n",rc);return;}memset(buf,0,len);rc=flash_read(flash_dev,SPI_FLASH_TEST_REGION_OFFSET,buf,len);if(rc!=0){LOG_DBG("Flash read failed! %d\n",rc);return;}if(memcmp(expected,buf,len)==0){LOG_DBG("Data read matches data written. Good!!\n");}else{constuint8_t*wp=expected;constuint8_t*rp=buf;constuint8_t*rpe=rp+len;LOG_DBG("Data read does not match data written!!\n");while(rp<rpe){LOG_DBG("%08x wrote %02x read %02x %s\n",(uint32_t)(SPI_FLASH_TEST_REGION_OFFSET+(rp-buf)),*wp,*rp,(*rp==*wp)?"match":"MISMATCH");++rp;++wp;}}}intmain(void){conststructdevice*flash_dev=DEVICE_DT_GET(DT_ALIAS(w25q128));if(!device_is_ready(flash_dev)){LOG_ERR("%s: device not ready.\n",flash_dev->name);return0;}LOG_DBG("\n%s SPI flash testing\n",flash_dev->name);LOG_DBG("==========================\n");single_sector_test(flash_dev);return0;}