赞
踩
需要的软件
Keil
STM32cubeMX
J-Flash
参考博客:
基于Keil生成外部Nor Flash下载算法,并使用J-Flash直接烧录(以W25Q64为例)
手把手系列–编写Keil MDK 外部FLASH下载算法
教你如何找到导致程序跑飞的指令
制作jflash下载算法,并解决堆栈溢出导致的写数据错误问题
参考文档:
这个是keil官方给的参考文档,但由于我在keil官方只下载到STM32F103ZE系列的标准库设备支持包,所以无法按照教程来配置,没有从keil打开STM32CubeMX的选项,这个走了会弯路
我前面贴了很多链接,都可以参考,但我这里主要划分3步核心
(4)GPIO
这个可以先不勾选,生成main函数了就先测试下Flash能不能正常读写,然后再勾选重新生成项目
添加必要的文件;
生成外设相关的.c和.h文件(这个没影响,只是勾了就不会所有函数都挤在main.c里);
保持用户代码(这个勾一下,重新生成时user注释区域的代码会保持的);
删除之前的文件
系统启动文件
这个不细说了,直接添加就行
这个直接参考文档,不细说 了,重要的提示一下
cmd.exe /C copy "STM32F103ZET6_SPIFLASH\%L" ".\@L.FLM"
这只是个复制的命令,生成FLM文件
Q:\NewStart\sample\STM32F10x_W25Q128\MDK-ARM\after_bulid.bat @L
这是个bat批处理文件,@L是传入的链接路径;这个可以不管,只是把FLM文件复制到对应的地方,懒得手动复制来复制去了
@echo off
set linker_output_file_name=%1
REM 将文件复制到第一个目录
cmd.exe /C copy ".\%linker_output_file_name%.FLM" "D:\ProSoft2\MDK5\ARM\Flash\%linker_output_file_name%.FLM"
REM 将文件复制到第二个目录
cmd.exe /C copy ".\%linker_output_file_name%.FLM" "C:\Users\qianmen\AppData\Roaming\SEGGER\JLinkDevices\STM32F10x_W25QXX\STM32F10x_W25Q128\%linker_output_file_name%.FLM"
REM 添加更多的复制命令...
FlashDev.c
struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, // Driver Version, do not modify! "STM32F10x_W25Q128 Flash", // Device Name EXTSPI, // Device Type 0x00000000, // Device Start Address 0x01000000, // Device Size in Bytes (256kB) 0x1000, // Programming Page Size 0, // Reserved, must be 0 0xFF, // Initial Content of Erased Memory 10000, // Program Page Timeout 100 mSec 30000, // Erase Sector Timeout 3000 mSec // Specify Size and Address of Sectors 0x1000, 0x000000, // Sector Size 8kB (8 Sectors) // 0x010000, 0x010000, // Sector Size 64kB (2 Sectors) // 0x002000, 0x030000, // Sector Size 8kB (8 Sectors) SECTOR_END };
FlashPrg.c
配置相关函数,init函数中进行一些初始化,uninit我没写,其他看着配置自己的flash擦除、写入、校验函数即可
#include "FlashOS.H" // FlashOS Structures #include "main.h" #include "spi.h" #include "gpio.h" /* Mandatory Flash Programming Functions (Called by FlashOS): int Init (unsigned long adr, // Initialize Flash unsigned long clk, unsigned long fnc); int UnInit (unsigned long fnc); // De-initialize Flash int EraseSector (unsigned long adr); // Erase Sector Function int ProgramPage (unsigned long adr, // Program Page Function unsigned long sz, unsigned char *buf); Optional Flash Programming Functions (Called by FlashOS): int BlankCheck (unsigned long adr, // Blank Check unsigned long sz, unsigned char pat); int EraseChip (void); // Erase complete Device unsigned long Verify (unsigned long adr, // Verify Function unsigned long sz, unsigned char *buf); - BlanckCheck is necessary if Flash space is not mapped into CPU memory space - Verify is necessary if Flash space is not mapped into CPU memory space - if EraseChip is not provided than EraseSector for all sectors is called */ /* * Initialize Flash Programming Functions * Parameter: adr: Device Base Address * clk: Clock Frequency (Hz) * fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) * Return Value: 0 - OK, 1 - Failed */ #include "flash_W25Qx.h" #include "nst_flash.h" #include "nst_log.h" #include "stdint.h" #include "stdio.h" #include "main.h" extern void SystemClock_Config(void); int Init (unsigned long adr, unsigned long clk, unsigned long fnc) { int ret = 0; volatile int i; volatile unsigned char * ptr = (volatile unsigned char * )&hspi2; for (i = 0; i < sizeof(hspi2); i++) { *ptr++ = 0U; } HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI2_Init(); // MX_USART1_UART_Init(); ret=nst_flash_init(); /* Add your Code */ return (ret); // Finished without Errors } /* * De-Initialize Flash Programming Functions * Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) * Return Value: 0 - OK, 1 - Failed */ int UnInit (unsigned long fnc) { /* Add your Code */ return (0); // Finished without Errors } /* * Erase complete Flash Memory * Return Value: 0 - OK, 1 - Failed */ int EraseChip (void) { // printf("EraseChip %d",__LINE__); nst_flash_erase_chip(); /* Add your Code */ return (0); // Finished without Errors } /* * Erase Sector in Flash Memory * Parameter: adr: Sector Address * Return Value: 0 - OK, 1 - Failed */ int EraseSector (unsigned long adr) { // printf("EraseSector %d",__LINE__); nst_flash_erase_block((uint32_t)adr); /* Add your Code */ return (0); // Finished without Errors } /* * Program Page in Flash Memory * Parameter: adr: Page Start Address * sz: Page Size * buf: Page Data * Return Value: 0 - OK, 1 - Failed */ int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) { // printf("ProgramPage %d",__LINE__); // nst_flash_write(buf,(uint32_t)adr,(uint32_t)sz); BSP_W25Qx_Write(buf,adr,sz); /* Add your Code */ return (0); // Finished without Errors } #define bufsize 4096 uint8_t aux_buf[bufsize]; unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf) { volatile int i=0, j=0; for(i = 0; i < sz/bufsize; i++) { nst_flash_read(aux_buf,adr+bufsize*i,bufsize); for (j = 0; j< bufsize; j++) { if (aux_buf[j] != buf[j+bufsize*i]) return (adr + j + bufsize*i); } } if(sz%bufsize) { nst_flash_read(aux_buf,adr+bufsize*i,sz%bufsize); for (j = 0; j< sz%bufsize; j++) { if (aux_buf[j] != buf[j+bufsize*i]) return (adr + j + bufsize*i); } } return (adr+sz); } int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat) { volatile int i=0, j=0; for(i = 0; i < sz/bufsize; i++) { nst_flash_read(aux_buf, adr+bufsize*i, bufsize); for (j = 0; j< bufsize; j++) { if (aux_buf[j] != pat) return 1; } } if(sz%bufsize) { nst_flash_read(aux_buf, adr+bufsize*i, sz%bufsize); for (j = 0; j< sz%bufsize; j++) { if (aux_buf[j] != pat) return 1; } } return 0; }
1 在 C:\Users\用户\AppData\Roaming\SEGGER 这个目录下创建JlinkDevices文件夹
2 接着创建
3 打开,接着创建
4 将FLM文件复制到这个目录下
5 回到上一个目录,创建并编辑xml文件
<Database>
<Device>
<ChipInfo Vendor="STM32F10x_W25QXX" Name="STM32F10x_W25Q128" WorkRAMAddr="0x20000000" WorkRAMSize="0x29000" Core="JLINK_CORE_CORTEX_M3" />
<!-- 512 KB internal code flash bank with 1 loader -->
<FlashBankInfo Name="SPI Flash" BaseAddr="0x00000000" AlwaysPresent="1" >
<LoaderInfo Name="Default" MaxSize="0x01000000" Loader="C:/Users/qianmen/AppData/Roaming/SEGGER/JLinkDevices/STM32F10x_W25QXX/STM32F10x_W25Q128/STM32F10x_W25Q128.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN" />
</FlashBankInfo>
</Device>
</Database>
检差路径的配置,xml文件是否写对了
-2 需要配置链接文件
SP=0x200064C8,STM32F103的RAM起始地址是0x20000000,64C8对应的就是map的aux_buf数组区域
bss段的起始地址和DSCR一样,我解决的办法是推移
target.lin 文件的DSCR地址加0x2000
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。