共4条
1/1 1 跳转至页
STR7,flash STR7 flash烧写问题
问
写一段程序将一些数据写入16K的BANK1中(使用ADS环境加mutli-ice仿真器,使用英蓓特STR711评估板),在ram中调试正常,然后烧写到Flash中,通过Jtag调试也正常,但是如果脱离仿真器直接运行,程序运行就不稳定,现象是:如果上电可以正常运行,那么按reset可以复位,复位后运行也正常,如果上电不能正常运行,则reset也不能使程序运行正常。程序代码如下:
#include "LED.h"
#include "FlashHelper.h"
void Main(void)
{
int i,j;
u32 strWrite=0x400C0000;//Bank1基地址
static const unsigned BinFile[]={
0xE59FF018,0xE59FF018,0xE1A00000,0xE59FF018,0xE59FF018,
0x40004584,0x400000C0,0x400000DC,0x400000F8,0x40000118,0x00000000,0x4000187C,0x40001914,
0x40000138,0x40000150,0x40000168,0x40000180,0x40000198,0x400001B0,0x400001C8,0x400001E0,
0x400001F8,0x40000210,0x40000228,0x40000240,0x40000258,0x40000270,0x40000288,0x400002A0,
0x400002B8,0x400002D0,0x400002E8,0x40000300,0x40000318,0x40000330,0x00000000,0x00000000,
0x00000000,0x40000348,0x40000360,0x00000000,0x00000000,0x40000378,0x40000390,0x400003A8,
};
#ifdef DEBUG
debug();
#endif
LED_Init();
LED_Set(LED3,GPIO1,1);
IntFlash_Program(strWrite, BinFile, sizeof(BinFile));
for(i = sizeof(BinFile) / sizeof(unsigned) - 1; i >= 0; i--)
{
if(((u32 *)strWrite)[i] != BinFile[i])
break;
else
{ /*进行校验,LED3闪烁*/
LED_Set(LED3,GPIO1,1);
for(j=0;j<100000;j++);
LED_Set(LED3,GPIO1,0);
for(j=0;j<100000;j++);
}
}
if(i < 0)
LED_Set(LED4,GPIO1,1);
while(1);
}
这个不稳定现象百思不解,考虑到使用STR912的时候也出现过在Flash中不能执行程序的现象,是因为程序无法在flash中正确跳转到Reset_Handler的原因,因为912默认的bootbank size只有32k,因此不能跳转到32K以外的地址,所以使用了一个中间函数,先将bootbank size寄存器调大,在进行跳转,解决了这个问题。
如下
B Reset0
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
Reset0
LDR R6, =0x54000000
LDR R7, =0x4
STR R7, [R6]
LDR PC, Reset_Addr
这次在这个程序里面试验
发现进行如下的修改可以使程序在Flash中稳定地的运行
对跳转表进行修改:
LDR PC, Reset_Addr
; LDR PC, Undefined_Addr
LDR PC, TEST
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
TEST
LDR PC,Undefined_Addr
912的修改可以知道原因,但是STR7的修改就让人摸不着头脑了,进行上面的修改为什么可以提高稳定性?现特向ST板块的各位高人求教,跪求答案! 答 1: “STR7 flash烧写问题”,问几个问题1)能把IntFlash_Program()的代码贴上来吗?
2)没有修改的Reset向量表是什么样的?你修改了什么?现在只看到改后的结果。
3)有没有启动PLL? 答 2: 一些数据写入16K的BANK1中的问题#include "LED.h"
#include "FlashHelper.h"
void Main(void)
{
int i,j;
u32 strWrite=0x400C0000;//Bank1基地址
static const unsigned BinFile[]={
0xE59FF018,0xE59FF018,0xE1A00000,0xE59FF018,0xE59FF018,
0x40004584,0x400000C0,0x400000DC,0x400000F8,0x40000118,0x00000000,0x4000187C,0x40001914,
0x40000138,0x40000150,0x40000168,0x40000180,0x40000198,0x400001B0,0x400001C8,0x400001E0,
0x400001F8,0x40000210,0x40000228,0x40000240,0x40000258,0x40000270,0x40000288,0x400002A0,
0x400002B8,0x400002D0,0x400002E8,0x40000300,0x40000318,0x40000330,0x00000000,0x00000000,
0x00000000,0x40000348,0x40000360,0x00000000,0x00000000,0x40000378,0x40000390,0x400003A8,
};
#ifdef DEBUG
debug();
#endif
LED_Init();
LED_Set(LED3,GPIO1,1);
IntFlash_Program(strWrite, BinFile, sizeof(BinFile));
for(i = sizeof(BinFile) / sizeof(unsigned) - 1; i >= 0; i--)
{
if(((u32 *)strWrite)[i] != BinFile[i])
break;
else
{ /*进行校验,LED3闪烁*/
LED_Set(LED3,GPIO1,1);
for(j=0;j<100000;j++);
LED_Set(LED3,GPIO1,0);
for(j=0;j<100000;j++);
}
}
if(i < 0)
LED_Set(LED4,GPIO1,1);
while(1);
}
这段代码在RAM中运行肯定没有问题,但是在FLASH中运行就会出错,原因是:
在对STR71x的FLASH进行写或擦除操作时,第一次的操作必须在RAM里运行,所以你在STR71x里就会出现错误。
至于你所说的跳转,我不明白是什么意思,是将PC指针指向Bank1吗?请明示,谢谢! 答 3: 回香水城1.flash编程
#include "FlashHelper.h"
/* address offset of each sector in internal flash memory */
static const struct flash_sector_info {
u32 base, mask;
} FlashSectorInfo[] = {
{0x000000, FLASH_B0F0},
{0x002000, FLASH_B0F1},
{0x004000, FLASH_B0F2},
{0x006000, FLASH_B0F3},
{0x008000, FLASH_B0F4},
{0x010000, FLASH_B0F5},
{0x020000, FLASH_B0F6},
{0x030000, FLASH_B0F7},
{0x040000, ~0},
{0x0C0000, FLASH_B1F0},
{0x0C2000, FLASH_B1F1},
{0x0C4000, ~0},
{~0, ~0},
};
void Flash_Init(void)
{
FLASH_Init();
}
static void IntFlash_Wait(void)
{
FLASH_Delay();
while(FLASHR->CR0 & 0x16);
}
int IntFlash_Program(u32 addr, const void *buf, u32 size)
{
const struct flash_sector_info *p;
u32 tbase, tmask;
u32 limit, mask;
u8* cTemp;
u32 tmpaddr=addr;
addr -= INT_FLASH_BASE;
limit = addr + size;
p = FlashSectorInfo;
while(addr >= p[1].base)
p++;
mask = (p->mask);
while(limit > p[1].base)
mask |= (++p)->mask;
if(mask == ~0)
return -1;
IntFlash_Wait();
FLASH_WritePrConfig(mask, DISABLE);
IntFlash_Wait();
FLASH_SectorErase(mask);
IntFlash_Wait();
FLASH_BlockWrite((u32)buf, tmpaddr, size + 3 >> 2);
IntFlash_Wait();
return 0;
}
调用的都是ST官方的最新库函数
原来的向量表是
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
没有使用pll
答 4: 回 ST_ARM按照您说的原因,那么我每次在Flash中运行都应该出错了,但实现在程序可以很稳定的执行,而我仅仅是改了一下向量表。。。。。而且即使不改,程序也不是每次都出错。
需要的函数基本上都在上面了,大家可以试一下
跳转指的是在向量表里的跳转,bank1使用来放一些数据,不会把pc指向它的 答 5: 在对STR71x的FLASH进行写或擦除操作时,第一次的操作必须在RAM里运行, 这个在最新版本的str7 Flash编程手册有提及 答 6: 上面两位是对的,第一次FLASH的写或擦除操作必须在RAM里运行不是每次出错不表示正确,正确的做法是第一次FLASH的写或擦除操作必须在RAM里运行。
你改了向量表,可以看成是移动了程序的位置,你的程序可以运行也应该是偶然的,你可以试试再加几条指令移动一下,也许程序又不能正常工作了。
#include "LED.h"
#include "FlashHelper.h"
void Main(void)
{
int i,j;
u32 strWrite=0x400C0000;//Bank1基地址
static const unsigned BinFile[]={
0xE59FF018,0xE59FF018,0xE1A00000,0xE59FF018,0xE59FF018,
0x40004584,0x400000C0,0x400000DC,0x400000F8,0x40000118,0x00000000,0x4000187C,0x40001914,
0x40000138,0x40000150,0x40000168,0x40000180,0x40000198,0x400001B0,0x400001C8,0x400001E0,
0x400001F8,0x40000210,0x40000228,0x40000240,0x40000258,0x40000270,0x40000288,0x400002A0,
0x400002B8,0x400002D0,0x400002E8,0x40000300,0x40000318,0x40000330,0x00000000,0x00000000,
0x00000000,0x40000348,0x40000360,0x00000000,0x00000000,0x40000378,0x40000390,0x400003A8,
};
#ifdef DEBUG
debug();
#endif
LED_Init();
LED_Set(LED3,GPIO1,1);
IntFlash_Program(strWrite, BinFile, sizeof(BinFile));
for(i = sizeof(BinFile) / sizeof(unsigned) - 1; i >= 0; i--)
{
if(((u32 *)strWrite)[i] != BinFile[i])
break;
else
{ /*进行校验,LED3闪烁*/
LED_Set(LED3,GPIO1,1);
for(j=0;j<100000;j++);
LED_Set(LED3,GPIO1,0);
for(j=0;j<100000;j++);
}
}
if(i < 0)
LED_Set(LED4,GPIO1,1);
while(1);
}
这个不稳定现象百思不解,考虑到使用STR912的时候也出现过在Flash中不能执行程序的现象,是因为程序无法在flash中正确跳转到Reset_Handler的原因,因为912默认的bootbank size只有32k,因此不能跳转到32K以外的地址,所以使用了一个中间函数,先将bootbank size寄存器调大,在进行跳转,解决了这个问题。
如下
B Reset0
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
Reset0
LDR R6, =0x54000000
LDR R7, =0x4
STR R7, [R6]
LDR PC, Reset_Addr
这次在这个程序里面试验
发现进行如下的修改可以使程序在Flash中稳定地的运行
对跳转表进行修改:
LDR PC, Reset_Addr
; LDR PC, Undefined_Addr
LDR PC, TEST
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
TEST
LDR PC,Undefined_Addr
912的修改可以知道原因,但是STR7的修改就让人摸不着头脑了,进行上面的修改为什么可以提高稳定性?现特向ST板块的各位高人求教,跪求答案! 答 1: “STR7 flash烧写问题”,问几个问题1)能把IntFlash_Program()的代码贴上来吗?
2)没有修改的Reset向量表是什么样的?你修改了什么?现在只看到改后的结果。
3)有没有启动PLL? 答 2: 一些数据写入16K的BANK1中的问题#include "LED.h"
#include "FlashHelper.h"
void Main(void)
{
int i,j;
u32 strWrite=0x400C0000;//Bank1基地址
static const unsigned BinFile[]={
0xE59FF018,0xE59FF018,0xE1A00000,0xE59FF018,0xE59FF018,
0x40004584,0x400000C0,0x400000DC,0x400000F8,0x40000118,0x00000000,0x4000187C,0x40001914,
0x40000138,0x40000150,0x40000168,0x40000180,0x40000198,0x400001B0,0x400001C8,0x400001E0,
0x400001F8,0x40000210,0x40000228,0x40000240,0x40000258,0x40000270,0x40000288,0x400002A0,
0x400002B8,0x400002D0,0x400002E8,0x40000300,0x40000318,0x40000330,0x00000000,0x00000000,
0x00000000,0x40000348,0x40000360,0x00000000,0x00000000,0x40000378,0x40000390,0x400003A8,
};
#ifdef DEBUG
debug();
#endif
LED_Init();
LED_Set(LED3,GPIO1,1);
IntFlash_Program(strWrite, BinFile, sizeof(BinFile));
for(i = sizeof(BinFile) / sizeof(unsigned) - 1; i >= 0; i--)
{
if(((u32 *)strWrite)[i] != BinFile[i])
break;
else
{ /*进行校验,LED3闪烁*/
LED_Set(LED3,GPIO1,1);
for(j=0;j<100000;j++);
LED_Set(LED3,GPIO1,0);
for(j=0;j<100000;j++);
}
}
if(i < 0)
LED_Set(LED4,GPIO1,1);
while(1);
}
这段代码在RAM中运行肯定没有问题,但是在FLASH中运行就会出错,原因是:
在对STR71x的FLASH进行写或擦除操作时,第一次的操作必须在RAM里运行,所以你在STR71x里就会出现错误。
至于你所说的跳转,我不明白是什么意思,是将PC指针指向Bank1吗?请明示,谢谢! 答 3: 回香水城1.flash编程
#include "FlashHelper.h"
/* address offset of each sector in internal flash memory */
static const struct flash_sector_info {
u32 base, mask;
} FlashSectorInfo[] = {
{0x000000, FLASH_B0F0},
{0x002000, FLASH_B0F1},
{0x004000, FLASH_B0F2},
{0x006000, FLASH_B0F3},
{0x008000, FLASH_B0F4},
{0x010000, FLASH_B0F5},
{0x020000, FLASH_B0F6},
{0x030000, FLASH_B0F7},
{0x040000, ~0},
{0x0C0000, FLASH_B1F0},
{0x0C2000, FLASH_B1F1},
{0x0C4000, ~0},
{~0, ~0},
};
void Flash_Init(void)
{
FLASH_Init();
}
static void IntFlash_Wait(void)
{
FLASH_Delay();
while(FLASHR->CR0 & 0x16);
}
int IntFlash_Program(u32 addr, const void *buf, u32 size)
{
const struct flash_sector_info *p;
u32 tbase, tmask;
u32 limit, mask;
u8* cTemp;
u32 tmpaddr=addr;
addr -= INT_FLASH_BASE;
limit = addr + size;
p = FlashSectorInfo;
while(addr >= p[1].base)
p++;
mask = (p->mask);
while(limit > p[1].base)
mask |= (++p)->mask;
if(mask == ~0)
return -1;
IntFlash_Wait();
FLASH_WritePrConfig(mask, DISABLE);
IntFlash_Wait();
FLASH_SectorErase(mask);
IntFlash_Wait();
FLASH_BlockWrite((u32)buf, tmpaddr, size + 3 >> 2);
IntFlash_Wait();
return 0;
}
调用的都是ST官方的最新库函数
原来的向量表是
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
没有使用pll
答 4: 回 ST_ARM按照您说的原因,那么我每次在Flash中运行都应该出错了,但实现在程序可以很稳定的执行,而我仅仅是改了一下向量表。。。。。而且即使不改,程序也不是每次都出错。
需要的函数基本上都在上面了,大家可以试一下
跳转指的是在向量表里的跳转,bank1使用来放一些数据,不会把pc指向它的 答 5: 在对STR71x的FLASH进行写或擦除操作时,第一次的操作必须在RAM里运行, 这个在最新版本的str7 Flash编程手册有提及 答 6: 上面两位是对的,第一次FLASH的写或擦除操作必须在RAM里运行不是每次出错不表示正确,正确的做法是第一次FLASH的写或擦除操作必须在RAM里运行。
你改了向量表,可以看成是移动了程序的位置,你的程序可以运行也应该是偶然的,你可以试试再加几条指令移动一下,也许程序又不能正常工作了。
共4条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |