STM32F103ZET6 J-flash外部SPI Flash烧录算法制作(keil)
需要的软件参考文档:这个是keil官方给的参考文档,但由于我在keil官方只下载到STM32F103ZE系列的标准库设备支持包,所以无法按照教程来配置,没有从keil打开STM32CubeMX的选项,这个走了会弯路。
STM32F103ZET6 J-flash外部SPI Flash烧录算法制作(keil)
1 说明
需要的软件
Keil
STM32cubeMX
J-Flash
参考博客:
基于Keil生成外部Nor Flash下载算法,并使用J-Flash直接烧录(以W25Q64为例)
手把手系列–编写Keil MDK 外部FLASH下载算法
教你如何找到导致程序跑飞的指令
制作jflash下载算法,并解决堆栈溢出导致的写数据错误问题
参考文档:
这个是keil官方给的参考文档,但由于我在keil官方只下载到STM32F103ZE系列的标准库设备支持包,所以无法按照教程来配置,没有从keil打开STM32CubeMX的选项,这个走了会弯路
2 步骤
我前面贴了很多链接,都可以参考,但我这里主要划分3步核心
- 1.使用STM32cubeMX生成MDK工程(keil),保证这个工程能够正常进行外部spi Flash的读写
- 2.参考文档,或者keil安装目录下的模板去设置工程参数
- 3.J-flash测试,调整报错
2.1 STM32cubeMX生成简单工程(spi Flash)
2.1.1 PinOut
- (1)时钟


- (2)SYS

(3)SPI
(4)GPIO
2.1.2 生成配置
- 1勾选Do not generate the main()
这个可以先不勾选,生成main函数了就先测试下Flash能不能正常读写,然后再勾选重新生成项目
- code生成选项
添加必要的文件;
生成外设相关的.c和.h文件(这个没影响,只是勾了就不会所有函数都挤在main.c里);
保持用户代码(这个勾一下,重新生成时user注释区域的代码会保持的);
删除之前的文件


2.2 MDK工程配置
- 1 取消一些不参加编译的文件
系统启动文件


- 2 添加Flash相关的文件,包括添加include路径
这个不细说了,直接添加就行

2.3 Options配置
这个直接参考文档,不细说 了,重要的提示一下



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 添加更多的复制命令...



3 Flash文件修改
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;
}
4 J-flash测试
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>





5 J-Flash测试遇到的一些错误
- 1 J-Flash搜不到设备
检差路径的配置,xml文件是否写对了
-2 需要配置链接文件

SP=0x200064C8,STM32F103的RAM起始地址是0x20000000,64C8对应的就是map的aux_buf数组区域bss段的起始地址和DSCR一样,我解决的办法是推移

target.lin 文件的DSCR地址加0x2000
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)