前言
上篇文章,我们移植了 nr_micro_shell 串口shell组件到MM32F5277上,在此基础上,我们继续移植Nor Flash和Embdded Flash的驱动,并编写串口命令进行测试!
Nor Flash驱动移植
我们先到灵动微的官网下载官方的SDK,贴个官网链接:灵动微电子SDK下载https://mindsdk.mindmotion.com.cn/userprofile/login/?next=/sdk/sdk-create/
在下载首页选择Window系统平台,编译工具选择MDK,Board选择plus-f5270,然后Build Project并下载;
下载好官网的SDK后,我们在路径..\plus-f5270_mdk\driver_examples\qspi\qspi_x25q_basic下可以找到官方对QSPI 驱动Nor Flash的驱动Demo,我们移植这个代码就可以实现QSPI驱动Nor Flash,以下是目录中的文件:
我们先修改一下官网的例程然后烧录进我们的板子先验证一下代码的功能,首先我们需要修改引脚定义,打开pin_init.c文件,将DEBUG串口修改为UART2的A2/A3引脚,紧接着修改QSPI引脚;对应的还要将board_init.h文件中的串口宏定义改为UART2,串口的外设时钟源改为APB1;同时还要在clock_init.c文件中修改UART2的时钟初始化;
//修改pin_init.c中的引脚定义
void BOARD_InitPins(void)
{
GPIO_Init_Type gpio_init;
/* PA2 - UART2_TX. */
gpio_init.Pins = GPIO_PIN_2;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_7);
/* PA3 - UART2_RX. */
gpio_init.Pins = GPIO_PIN_3;
gpio_init.PinMode = GPIO_PinMode_In_Floating;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_7);
/* PB6 - QSPI_CS. */
gpio_init.Pins = GPIO_PIN_6;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB5 - QSPI_SCK. */
gpio_init.Pins = GPIO_PIN_5;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB7 - QSPI_IO0. */
gpio_init.Pins = GPIO_PIN_7;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB8 - QSPI_IO1. */
gpio_init.Pins = GPIO_PIN_8;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB3 - QSPI_IO2. */
gpio_init.Pins = GPIO_PIN_3;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB4 - QSPI_IO3. */
gpio_init.Pins = GPIO_PIN_4;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; //GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
}
//修改board_init.h中的UART2宏定义
/* DEBUG UART. */
#define BOARD_DEBUG_UART_PORT UART2
#define BOARD_DEBUG_UART_BAUDRATE 115200u
#define BOARD_DEBUG_UART_FREQ CLOCK_APB1_FREQ
//修改clock_init.c中的时钟外设初始化
void BOARD_InitBootClocks(void)
{
CLOCK_ResetToDefault();
CLOCK_BootToHSE120MHz();
/* UART2. */
RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_UART2, true);
RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_UART2);
/* QSPI. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_QSPI, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_QSPI);
/* GPIOA. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOA, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOA);
/* GPIOB. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOB, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOB);
/* GPIOC. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOC, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOC);
/* GPIOG. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOG, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOG);
}
由于官网SDK使用的是Nor Flash型号与我们板上实际的不一致,所以还要修改一下Nor Flash的型号和大小,打开X25q_conf.h,修改对应的Device型号和Memsize大小,以及统一修改X25Q_Device_W25Q32这个参数在其他地方的引用;
/* list the index value of the device. */
enum
{
X25Q_Device_W25Q32 = 0u, /* the W25Q32 device index. */
};
/* define the device table. */
#define X25Q_DEVICE_TABLE \
{ \
[X25Q_Device_W25Q32] = \
{ \
.MemSize = (4u * 1024u * 1024u), /* 4MB. */ \
.SectorSize = 4096u, /* 4K. */ \
.PageSize = 256u, /* 256 Byte. */ \
.OperationMode = X25Q_OperationMode_QSPI, \
}, /* 4MB memory size, QPI mode. */ \
}
修改完后编译烧录到板上并打开串口工具查看,根据命令提示测试读写、擦除是否成功:
测试完成,验证官网例程功能没有问题,我们就进行移植,首先在我们的工程目录下创建../driver/flash文件夹,然后将以下四个文件复制到这个目录中:
并在MDK中包含../driver/flash编译路径,并添加x25q.c/x25q_port.c文件到工程中:
增加QSPI的引脚初始化、对应的外设时钟初始化到我们工程的初始化函数gpio_pin_init/boot_clock_init中:
static void gpio_pin_init(void)
{
GPIO_Init_Type gpio_init;
/* PA2 - UART2_TX. */
gpio_init.Pins = GPIO_PIN_2;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_7);
/* PA3 - UART2_RX. */
gpio_init.Pins = GPIO_PIN_3;
gpio_init.PinMode = GPIO_PinMode_In_Floating;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_7);
/* PB6 - QSPI_CS. */
gpio_init.Pins = GPIO_PIN_6;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; // GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB5 - QSPI_SCK. */
gpio_init.Pins = GPIO_PIN_5;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; // GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB7 - QSPI_IO0. */
gpio_init.Pins = GPIO_PIN_7;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; // GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB8 - QSPI_IO1. */
gpio_init.Pins = GPIO_PIN_8;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; // GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB3 - QSPI_IO2. */
gpio_init.Pins = GPIO_PIN_3;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; // GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PB4 - QSPI_IO3. */
gpio_init.Pins = GPIO_PIN_4;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull; // GPIO_PinMode_AF_OpenDrain
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConf(GPIOB, gpio_init.Pins, GPIO_AF_10);
/* PD2 - LED0. */
gpio_init.Pins = GPIO_PIN_2;
gpio_init.PinMode = GPIO_PinMode_Out_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &gpio_init);
GPIO_WriteBit(LED0_GPIO_PORT, LED0_GPIO_PIN, 1u); /* led off. */
/* PC14 - KEY1. */
gpio_init.Pins = GPIO_PIN_14;
gpio_init.PinMode = GPIO_PinMode_In_PullUp;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
/* PC15 - KEY2. */
gpio_init.Pins = GPIO_PIN_15;
gpio_init.PinMode = GPIO_PinMode_In_PullUp;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
}
static void boot_clock_init(void)
{
clock_reset_default();
// clock_sourse_hse_120();
clock_sourse_hsi_120();
delay_ms(500);
/* UART2. */
RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_UART2, true);
RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_UART2);
/* UART1. */
RCC_EnableAPB2Periphs(RCC_APB2_PERIPH_UART1, true);
RCC_ResetAPB2Periphs(RCC_APB2_PERIPH_UART1);
/* FLASH. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_FLASH, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_FLASH);
/* QSPI. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_QSPI, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_QSPI);
/* GPIOA. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOA, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOA);
/* GPIOB. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOB, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOB);
/* GPIOC. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOC, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOC);
/* GPIOD. */
RCC_EnableAHB1Periphs(RCC_AHB1_PERIPH_GPIOD, true);
RCC_ResetAHB1Periphs(RCC_AHB1_PERIPH_GPIOD);
}
在bsp_init()函数中添加X25Q_Init()函数用以初始化Qspi;
void bsp_init(void)
{
boot_clock_init(); // 时钟源选择 外部 HSE 12Mhz PLL1 120Mhz 外设时钟初始化
gpio_pin_init(); // 板载外设gpio初始化
clock_systick_init();
debug_console_init(); // uart2 debug串口初始化 115200
shell_init();
X25Q_Init();
}
至此,我们移植官方SDK的Nor Flash驱动已经完成,接下来我们移植Embdded Flash的驱动!
Embdded Flash驱动移植
首先添加一个空白的flash.c/flash.h文件到我们工程目录..\driver\flash路径下,并在MDK中添加flash.c到我们的工程中,再打开官网SDK路径..\plus-f5270_mdk\driver_examples\flash\flash_iap例程目录下的main.c文件,复制以下三个函数到我们的flash.c文件,再编写一个flash_read_data()函数:
#inlcude "flash.h"
void flash_read_page(uint32_t page, uint8_t *buff)
{
uint32_t addr = EMBDDED_FLASH_BASE + page * EMBDDED_PAGE_SIZE;
for (uint32_t i = 0u; i < EMBDDED_PAGE_SIZE; i++, buff++)
{
*buff = *((uint8_t *)(addr + i));
}
}
void flash_read_data(uint32_t addr, uint32_t size, uint8_t *buff)
{
if (size > 1024 || size < 0)
{
return;
}
for (uint32_t i = 0u; i < size; i++, buff++)
{
*buff = *((uint8_t *)(addr + i));
}
}
void flash_erase_page(uint32_t page)
{
FLASH_SetCmd(EMBDDED_FLASH, FLASH_CMD_ERASE_PAGE);
FLASH_SetAddr(EMBDDED_FLASH, EMBDDED_FLASH_BASE + page * EMBDDED_PAGE_SIZE);
FLASH_SetCmd(EMBDDED_FLASH, FLASH_CMD_START_ERASE);
while (!FLASH_WaitDone(EMBDDED_FLASH, 1000u))
; /* flash controller operation done. */
while (FLASH_STATUS_END_OF_OPERATION != FLASH_GetStatus(EMBDDED_FLASH))
; /* flash memory erase operation done. */
FLASH_ClearStatus(EMBDDED_FLASH, FLASH_STATUS_END_OF_OPERATION);
}
void flash_program_page(uint32_t page, uint8_t *buff)
{
uint32_t addr = EMBDDED_FLASH_BASE + page * EMBDDED_PAGE_SIZE;
for (uint32_t i = 0u; i < FLASH_PAGE_SIZE; i += 2u, buff += 2u)
{
FLASH_SetCmd(EMBDDED_FLASH, FLASH_CMD_PROGRAM);
FLASH_SetData16b(addr + i, *((uint16_t *)buff));
while (!FLASH_WaitDone(EMBDDED_FLASH, 100u))
;
}
}
打开flash.h文件并编写:
#ifndef __FLASH_H__
#define __FLASH_H__
#include "common.h"
void flash_read_page(uint32_t page, uint8_t *buff);
void flash_read_data(uint32_t addr, uint32_t size, uint8_t *buff);
void flash_erase_page(uint32_t page);
void flash_program_page(uint32_t page, uint8_t *buff);
#endif
在board.c文件的bsp_init()函数中添加解锁FLASH的函数:
void bsp_init(void)
{
boot_clock_init(); // 时钟源选择 外部 HSE 12Mhz PLL1 120Mhz 外设时钟初始化
gpio_pin_init(); // 板载外设gpio初始化
clock_systick_init();
debug_console_init(); // uart2 debug串口初始化 115200
shell_init();
FLASH_Unlock(EMBDDED_FLASH);
X25Q_Init();
}
部分宏定义在我们工程的common.h中:
#ifndef __COMMON_H__
#define __COMMON_H__
//c .h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//HAL .h
#include "hal_common.h"
#include "hal_gpio.h"
#include "hal_uart.h"
#include "hal_rcc.h"
#include "hal_qspi.h"
#include "hal_flash.h"
//bsb .h
#include "clock.h"
#include "board.h"
//usr.h
#include "uart.h"
#include "x25q.h"
#include "flash.h"
//compoent .h
#include "nr_micro_shell.h"
#include "ymodem.h"
#ifdef DEBUG
#define _here_ printf("--->%s:%d: \r\n", __FILE__, __LINE__);
#else
#define _here_ ((void)0)
#endif
#define BOARD_VERSION "uboot"
#define AUTOBOOT_TIMEOUT 5u //autoboot延时
/* nor Flash*/
#define NOR_FLASH_START 0x00000000 //nor flash的首地址
#define APP_SAVE_ADDRSS 0x00000100 //APP在norflash中的存储首地址
#define BOARD_APP_BASE 0x08008000 //APP起始地址
#define USER_FLASH_END_ADDRESS 0x08040000 //APP结束地址
#define USER_FLASH_SIZE (USER_FLASH_END_ADDRESS - BOARD_APP_BASE) //APP大小
#define X25Q_SECTOR_SIZE 4096u //nor flash 扇区大小 = 4096 Byte
#define X25Q_PAGE_SIZE 256u //nor flash 页大小 = 256 Byte
/* on-chip FLASH. */
#define EMBDDED_FLASH FLASH
#define EMBDDED_FLASH_BASE 0x08000000 //Embdded Flash的首地址
#define EMBDDED_BLOCK_SIZE 4096u //Embdded Flash 块大小 = 4096 Byte
#define EMBDDED_PAGE_SIZE 1024u //Embdded Flash 页大小 = 1024 Byte
#define EMBDDED_APP_PAGE_START 32 //APP在Embaded Flash 中的首地址位于第 32 Page: 0x08008000 / 1024 = 32 Page
/* 版本信息存储地址 */
#define VERSION_DATA_SIZE 48 //版本信息占用flash字节大小
#define BOARD_INFO_BASE 0x0B00 //版本信息存储的基地址
#define BOARD_INFO_OFFSITE_UBOOT (EMBDDED_FLASH_BASE + BOARD_INFO_BASE) //uboot版本信息存储的偏移地址 位于embdded flash
#define BOARD_INFO_OFFSITE_WORK (BOARD_APP_BASE + BOARD_INFO_BASE) //work app版本信息存储的偏移地址 位于embdded flash
#define BOARD_INFO_OFFSITE_FACTORY (APP_SAVE_ADDRSS + BOARD_INFO_BASE) //factory app版本信息存储的偏移地址 位于nor flash
extern const char Ver[5];
extern const char Date[16];
extern const char Time[16];
#endif
到这一步,我们从官方的例程中移植完了Embdded Flash的驱动,下一步,我们编写shell的命令来对Nor Flash和Embdded Flash进行读写测试;
串口shell测试命令编写
打开..\driver\flash\flash.c,添加以下代码:
void shell_mtd_command(char argc, char *argv)
{
uint32_t id;
uint8_t i;
uint8_t flash_test_buf[EMBDDED_PAGE_SIZE];
uint16_t addr, page;
switch (X25Q_ReadManuId(X25Q_Device_W25Q32))
{
case 0xef13:
id = 0xef13;
break;
case 0xef14:
id = 0xef14;
break;
case 0xef15:
id = 0xef15;
break;
case 0xef16:
id = 0xef16;
break;
case 0xef17:
id = 0xef17;
break;
default:
id = -1;
break;
}
if ((!strcmp("mtd", &argv[argv[0]])) && (argc > 1 && argc <= 4))
{
if (!strcmp("-h", &argv[argv[1]]))
{
shell_printf("mtd -h --help.\r\n");
shell_printf("mtd [tab] [-o] [-addr]\r\n");
shell_printf("eg: mtd 1 r 0.\r\n");
shell_printf("eg: mtd 0 r 0.\r\n");
shell_printf("eg: mtd 1 e .\r\n");
}
else if (!strcmp("0", &argv[argv[1]]))
{
/*mtd 0*/
if ((!strcmp("r", &argv[argv[2]])))
{
page = atoi(&argv[argv[3]]);
if (page < 0 || page > 255)
{
shell_printf("command option error,mtd0 page should be between 0~255.\r\n");
return;
}
shell_printf("mtd0 read 1024 Byte start page:%d\r\n", page);
flash_read_page(page, flash_test_buf);
for (uint32_t i = 0; i < EMBDDED_PAGE_SIZE; i++)
{
if (0 == i % 16u)
{
shell_printf("\r\n");
}
shell_printf("%02X ", flash_test_buf[i]);
}
shell_printf("\r\n");
}
else if ((!strcmp("w", &argv[argv[2]])) || (!strcmp("e", &argv[argv[2]])))
{
shell_printf("command option error,user can not write or erase mtd0.\r\n");
return;
}
}
else if ((!strcmp("1", &argv[argv[1]])))
{
if (id == -1)
{
shell_printf("command option error. not found mtd1.\r\n");
}
/*mtd 1*/
if ((!strcmp("r", &argv[argv[2]])))
{
addr = atoi(&argv[argv[3]]);
shell_printf("mtd1 read 256 Byte start addr:%d\r\n", addr);
X25Q_ReadData(X25Q_Device_W25Q32, addr, X25Q_PAGE_SIZE, flash_test_buf);
for (uint32_t i = 0; i < 256u; i++)
{
if (0 == i % 16u)
{
shell_printf("\r\n");
}
shell_printf("%02X ", flash_test_buf[i]);
}
shell_printf("\r\n");
}
else if ((!strcmp("w", &argv[argv[2]])))
{
for (uint32_t j = 0u; j < X25Q_PAGE_SIZE; j++)
{
flash_test_buf[j] = j % 0x100;
}
addr = atoi(&argv[argv[3]]);
shell_printf("mtd1 write 256 Byte start addr:%d\r\n", addr);
for (uint32_t k = 0; k < 256u; k++)
{
if (0 == k % 16u)
{
shell_printf("\r\n");
}
uint32_t temp = flash_test_buf[k] + 1u;
flash_test_buf[k] = temp & 0xffu;
shell_printf("%02X ", flash_test_buf[k]);
}
X25Q_WritePage(X25Q_Device_W25Q32, addr, X25Q_PAGE_SIZE, flash_test_buf);
shell_printf("\r\n");
}
else if ((!strcmp("e", &argv[argv[2]])))
{
shell_printf("mtd1 erasing...\r\n");
X25Q_EraseChip(X25Q_Device_W25Q32);
shell_printf("mtd1 erase done.\r\n");
}
else
{
shell_printf("command option error.\r\n");
}
}
}
else
{
shell_printf("tab-------type----------size------id\r\n");
shell_printf("mtd0 embdded flash 256K Byte none\r\n");
switch (id)
{
case 0xef13:
shell_printf("mtd1 w25q80 1M Byte 0x%x\r\n", id);
break;
case 0xef14:
shell_printf("mtd1 w25q16 2M Byte 0x%x\r\n", id);
break;
case 0xef15:
shell_printf("mtd1 w25q32 4M Byte 0x%x\r\n", id);
break;
case 0xef16:
shell_printf("mtd1 w25q64 8M Byte 0x%x\r\n", id);
break;
case 0xef17:
shell_printf("mtd1 w25q128 16M Byte 0x%x\r\n", id);
break;
default:
break;
}
}
}
FLash驱动移植成果验证
将工程编译并烧录至板子上,打开串口工具,按tab键查看mtd命令;
输入mtd 会打印当前的Embdded Flash大小和Nor Flash大小以及他们的id,其中mtd0为Embdded Flash,mtd1为Norflash,型号为W25q32;
输入mtd -h 会有相关的命令提示;
输入mtd 1 r 0 会打印Nor Flash第一页 256 byte数据;
输入mtd 1 e 会擦除Nor Flash;
输入mtd 1 w 0 会向Nor Flash的地址0写入256byte的随机数据;
输入mtd 0 r 0 会打印Embdded Flash的第一页 1024 byte数据;
标签:flash,Flash,boot,init,MM32F5277,gpio,GPIO,PinMode,RCC From: https://blog.csdn.net/Kiouker/article/details/139473921