我在使用一种 通过应用来烧写flash的功能,在应用程序中运行 flash API函数,然后将程序烧录到代码区,测试是 flash erase后,程序就卡死了。
硬件平台是F2812, 用来编程的 flash函数定义在RAM中,在main()函数中调用,请问这种方式还需要注意什么? 按照手册上的描述,只要编程函数运行在ram中,可以对任意的flash区域进行编程,可是实际中在对 codeflash区域编程失败,单独定义的一款dataflash可以实现。。。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我在使用一种 通过应用来烧写flash的功能,在应用程序中运行 flash API函数,然后将程序烧录到代码区,测试是 flash erase后,程序就卡死了。
硬件平台是F2812, 用来编程的 flash函数定义在RAM中,在main()函数中调用,请问这种方式还需要注意什么? 按照手册上的描述,只要编程函数运行在ram中,可以对任意的flash区域进行编程,可是实际中在对 codeflash区域编程失败,单独定义的一款dataflash可以实现。。。
您好,
的确,Flash API 函数的调用必须在 RAM 中执行。对于 Flash API 函数具体的调用方法,可以参考 ControlSUITE 中其他型号的示例代码,例如 flash_f28069 ;主要有以下几个步骤:
(1)在 .cmd 文件中定义代码搬移的相应区域:
(2)定义函数 Example_CallFlashAPI(),其中包含 Flash API 操作;将其地址空间定义在 ramfuncs 中:
(3)在 main() 中调用 Example_CallFlashAPI() 函数之前,需要先执行代码搬移函数,将在 ramfuncs 中定义的代码从 Flash 搬移到 RAM 中,此时Example_CallFlashAPI() 才真正被搬移至 RAM 中:
(4)最后,执行 Example_CallFlashAPI() 函数,在其中调用相应的 Flash API 函数:
请参考示例代码,对比您工程中的相应操作是否一致?
既然你是使用F2812,那么参考这个文档吧:TMS320F281x Boot ROM Serial Flash Programming
里面包含了详细说明并可以在概要部分下载对应的源代码。
你的main()所在的flash区域如果也要被擦除或编程的话,那肯定是会出问题的,另外记得要关闭中断,具体要求在FlashAPI的手册里都有说明。
感谢回复,以上的(1)(2)(3)(4)都测试过, 当擦写 编程自定义的一块flash时没有问题,这几段flash没有存储任何代码和数据,说明flash api的调用应该没有问题。
但是当擦写 编程 代码段的flash时,没有成功,怀疑的原因有以下: ①因为是在一个flash函数里面调用了 ramfunc 来编程,擦除调用函数本身是否属于违法操作 ②falsh的编程需要 配置PLL以及cpu scaltor,和call back ptr,这些都是全局变量,flash的编程是否需要将这些数据也copy到 ram中去,这种在代码如何实现?
通常的做法 -- 对于需要在线擦除并编程:
将实现该功能的代码(也即你现在调用FlashAPI的代码,通常称为用户bootloader),放在一个flash sector,运行时全部copy到RAM运行,包括初始化函数,通讯传输数据的代码,memcpy函数等都不要在flash上运行,使用的变量不要与应用程序的放在一起。
自己的应用程序放在剩下的其它flash sector,可由用户bootloader任意操作。
对比一下上面提到的文档参考看看吧。
10# 说:通常的做法 -- 对于需要在线擦除并编程:
将实现该功能的代码(也即你现在调用FlashAPI的代码,通常称为用户bootloader),放在一个flash sector,运行时全部copy到RAM运行,包括初始化函数,通讯传输数据的代码,memcpy函数等都不要在flash上运行,使用的变量不要与应用程序的放在一起。
自己的应用程序放在剩下的其它flash sector,可由用户bootloader任意操作。
对比一下上面提到的
1.memcopy不在flash运行会引起矛盾,因为加载到ram中需要调用memcopy,函数不能修改自己的调用地址
2 将bootloader放到一个单独的sector可以做到,但是这对于应用升级来说没有区别,除非在硬件启动和函数调用后,手动修改起始运行的PC指针; 假设这样去做,那么要如何实现指针的跳转,
3.如何将特定的变量和应用程序不放在一起,变量本身应该都是在RAM存储的,如果定义时没有初始化的话,调用过程应该是和flash无关的,还有必要做一些调整么?
4,因为代码从内部flash运行,所以不改变硬件BOOT过程的话,默认上电后,进入的都是falsh里面的main()函数首地址,如果自定义boot函数,只能在flash中调用,
Blake Ma 说:请问您要擦除自身的代码段的目的是什么?
因为现在测试没有通过,我怀疑 要么这种设计的思路有问题,还是我本身程序应用的有错误?
但是从TI已有的技术手册来看,应该是允许这种应用,即 只要正确的运行一个RAM函数,正确调用FLASH API ,然后使用这个RAM函数是可以编程任意Secotr的flash, 而函数本身在哪里进行调用应该是没有问题的。
flash编程的限制应该在于,boot程序不能再访问任何的处于编程状态的flash 的code 和数据, 而我的Boot程序,只使用了 局部变量和未初始化的全局变量 Flash_Callbackptr, Flash_CPUScaleFactor,
覆盖整个代码区的做法应用到产品中是很危险的:不能应对操作中突然断电的情况。
建议把flash分为bootloader区和应用程序区,bootloader区一次烧写后永不擦出。
更新时bootloader把应用程序的第一条指令重定位到其它地方,芯片上电后先执行到
bootloader里然后再检查那个地方是否有合法指令,有则执行无则停留在bootloader里等待更新。
he yuanjie 说:覆盖整个代码区的做法应用到产品中是很危险的:不能应对操作中突然断电的情况。
建议把flash分为bootloader区和应用程序区,bootloader区一次烧写后永不擦出。
更新时bootloader把应用程序的第一条指令重定位到其它地方,芯片上电后先执行到
bootloader里然后再检查那个地方是否有合法指令,有则执行无则停留在bootloader里等待更新。
这个建议物理上分开boot和flash区域,可以增加可修复性。我是新手,DSP不是很熟,一边看AN NOTE一边修改,有些问题请教
请问具体实现方法? 如何重定位应用的指令?怎么检查指令正常?
如何自定义 应用程序的跳转,目前 是在codestart.asm 里面跳转 LB _c_int00 ,应该是程序入口,自己要怎么再定义一个自己boot的入口呢?
这个功能我已经实现但不能提供代码参考,这里我只能简单描述一下。
首先我是将最后两个扇区和最开始两个扇区保留为boot使用,其它开发者使用其余的空间。
应用程序的第一条指令是放在此处的:BEGIN : origin = 0x3F7FF6, length = 0x000002 。
当你转换为hex后可以看到这个地址的32位数据,原本这32位数据是放在0x3F7FF6处的。重定位就是把这32位数据放到其它地方。
he yuanjie 说:这个功能我已经实现但不能提供代码参考,这里我只能简单描述一下。
首先我是将最后两个扇区和最开始两个扇区保留为boot使用,其它开发者使用其余的空间。
应用程序的第一条指令是放在此处的:BEGIN : origin = 0x3F7FF6, length = 0x000002 。
当你转换为hex后可以看到这个地址的32位数据,原本这32位数据是放在0x3F7FF6处的。重定位就是把这32位数据放到其它地方。
从TI的手册来看,0x3F7FF6这个位置时 flash boot模式下,默认的起始地址,一般应用中,在这里放一个跳转指针 ,多数跳转到 cinit(这个是C环境初始化),这个32位数据 如果拿来用的话,相当于执行完Bootloader后再跳转到(C环境初始化),那么引入的问题是:
1)0x3F7FF6原来位置的数据需要修改么,修改的话,相当于修改了启动模式,要么改成RAM boot要么在这里给出Bootloader程序的入口,
2)在boot 程序前不调用 cinit的话,Bootloader程序还可以用C语言定义么?
3)要怎样获取bootloader的入口地址呢,以保证系统上电跳转到此处?
其实这样考虑的话,有没有可能这样,flash升级的时候,直接重新把代码全部拷到未使用的一块flash,然后重启过程直接把这个flash作为codeflash,
当flash中有bootloader和应用程序后整个flash中其实有两个cinit。
你的bootloader首先用仿真器烧写的 在0x3F7FF6处会是boot的起始地址。
进入boot后你再跳转到应用程序的起始地址是会再调用一次cinit的,只是不是bootloader的cinit。
当然了bootloader是不能和应用程序一起编译的必须得两个工程。
he yuanjie 说:当flash中有bootloader和应用程序后整个flash中其实有两个cinit。
你的bootloader首先用仿真器烧写的 在0x3F7FF6处会是boot的起始地址。
进入boot后你再跳转到应用程序的起始地址是会再调用一次cinit的,只是不是bootloader的cinit。
当然了bootloader是不能和应用程序一起编译的必须得两个工程。
理解你的意思了,这样实际上仿真器烧录bootloader工程,利用bootloader加载应用。 虽然没有直接解决我的问题,还是谢谢你的回复,我尝试按照你的这种方式来尝试一下。
he yuanjie
说的这个是很重要的。
“覆盖整个代码区的做法应用到产品中是很危险的:不能应对操作中突然断电的情况。”
我理解你的意思,你的想法把Bootloader与APP做成一个项目。这样是可以实现的。至少我已经实现这个功能。
我先说明一下我的做法。
1、使用的Flash操作函数采用的是TI的官方API库。平台CCS5.0
2、Flash区域需要定义4个固定的区域。
请看我的CMD文件部分代码
FLASHD : origin = 0x3F0000, length = 0x003000 /* on-chip FLASH */
FLASHC : origin = 0x3F3000, length = 0x001000 /* on-chip FLASH */
FLASHB : origin = 0x3F4000, length = 0x001FD0 /* on-chip FLASH */
FLASHB_LINK : origin = 0x3F5FD0, length = 0x00002C /* 存放跳转APP的固定指令 */
FLASHB_INFO : origin = 0x3f5FFC, length = 0x000004 /*存放固件的信息,包括固件是否完整的信息*/
FLASHA_API : origin = 0x3F6000, length = 0x001800 /*存放部分Bootloader函数*/
FLASHA_CODE : origin = 0x3F7800, length = 0x000770 /*存放APP中调用的Bootloader入口函数*/
CSM_RSVD : origin = 0x3F7F80, length = 0x000076 /* Part of FLASHA. Program with all 0x0000 when CSM is in use. */
加粗部分很重要。
3、实现原理
C2000上电后,直接进入Bootloader函数,Bootloader函数检查固件是否完整,如果固件完整执行APP函数,正常启动系统,如果不完整执行Bootloader功能。
4、部分代码。
C2000上电后首先执行的是
BEGIN : origin = 0x3F7FF6, length = 0x000002 /* Part of FLASHA. Used for "boot to Flash" bootloader mode. */
中的代码,你可以看到在一个Asm文件中。
部分代码:
WD_DISABLE .set 1 ;set to 1 to disable WD, else set to 0
.ref _bootloader
.global code_start
***********************************************************************
* Function: codestart section
*
* Description: Branch to code starting point
***********************************************************************
.sect "codestart"
code_start:
.if WD_DISABLE == 1
LB wd_disable ;Branch to watchdog disable code
.else
LB _bootloader ;Branch to start of boot.asm in RTS library
.endif
;end codestart section
***********************************************************************
* Function: wd_disable
*
* Description: Disables the watchdog timer
***********************************************************************
.if WD_DISABLE == 1
.sect "BootFlash"
wd_disable:
SETC OBJMODE ;Set OBJMODE for 28x object code
EALLOW ;Enable EALLOW protected register access
MOVZ DP, #7029h>>6 ;Set data page for WDCR register
MOV @7029h, #0068h ;Set WDDIS bit in WDCR to disable WD
EDIS ;Disable EALLOW protected register access
LB _bootloader ;Branch to start of boot.asm in RTS library
.endif
你看到bootloader这个函数没有,这个就是改变了C2000上电后的执行方向,
并不时直接向main()跳转了,而直接向bootloader跳转。
下面部分是我自己写的一个汇编文件
.global _BootProcess
.global _InitC
.ref _SysCtrlRegs
.ref _mProgramFlag
.ref _SCI_Init
.ref _Time0Init
.ref _fFlashProcess
.ref _CpuTimer0Regs
.ref _fInit28035
.ref _mReconnectTime
/*
APP函数中调用Bootloader程序的函数入口
*/
.sect "BootProcess"
_BootProcess:
MOV @SP, #0x0050
SPM #0
SETC OBJMODE
CLRC AMODE
SETC M0M1MAP
CLRC PAGE0
MOVW DP, #0x0
CLRC OVM
ASP
EALLOW
MOV @AL, #0xffff
MOV @AH, #0xffff
ADDB ACC, #1
SB 27, EQ
MOVL XAR7, #0x3fffff
CLRC TC
SB 15, UNC
MOVB AH, #0x0
PREAD @AL, *XAR7
ADDB XAR7, #1
SB 4, NTC
CLRC TC
PREAD @AH, *XAR7
ADDB XAR7, #1
MOVL @XAR6, ACC
RPT @AR1
|| PREAD *XAR6++, *XAR7
MOVL ACC, @XAR7
ADD ACC, @AR1
ADDB ACC, #1
MOVL @XAR7, ACC
PREAD @AL, *XAR7
SB 3, GEQ
NEG AL
SETC TC
MOVZ AR1, @AL
ADDB XAR7, #1
BANZ -20,AR1--
EDIS
MOV @AL, #0xffff
MOV @AH, #0xffff
ADDB ACC, #1
SB 14, EQ
MOVL XAR7, #0x3fffff
SB 6, UNC
ADDB XAR7, #1
MOVL *SP++, XAR7
MOVL @XAR7, ACC
LCR *XAR7
MOVL XAR7, *--SP
PREAD @AL, *XAR7
ADDB XAR7, #1
PREAD @AH, *XAR7
TEST ACC
SB -9, NEQ
LCR #_fInit28035
LCR #_Time0Init
LCR #_SCI_Init
MOVW DP,#_mProgramFlag
MOVW @_mProgramFlag,#0
EALLOW
MOVW DP,#_SysCtrlRegs+25
MOVW @_SysCtrlRegs+25,#0x0068
EDIS
BootContious:
LCR #_fFlashProcess
LB BootContious
NOP
NOP
NOP
LRETR
/*APP函数的入口地址*/
.sect "FlashForAPP"
.global _app_address
.ref _c_int00
_app_address:
LB #_c_int00 /*指向了main()的初始化部分*/
.end
代码有些乱,由于代码有加密,无法给你看到整个项目的布局。
希望这些对你有帮助。
还有一点,需要把bootloader中用到的cinit载入Bootloader函数的Flash区域。不然这些数据在擦除后,数据会丢失。
方法:
SECTIONS
{
Flash28_API:
{
-l Flash2802x_API_V200.lib(.econst)
-l Flash2802x_API_V200.lib(.text)
} LOAD = FLASHA_API
RUN = RamBoot,
LOAD_START(_Flash28_API_LoadStart),
LOAD_END(_Flash28_API_LoadEnd),
RUN_START(_Flash28_API_RunStart),
PAGE = 0
RESETAPP:
{
-l rts2800_ml.lib(.cinit)
-l rts2800_ml.lib(.text)
-l Flash28027_API.obj(.cinit) /*Bootloader中使用的常量以及初始化变量*/
} LOAD = FLASHA_API
PAGE = 0
专家您好:
能否请教下关于这个帖子的回答;
现在我用28033去做这个booterloader功能。
先是通过修改codestart中的跳转指令。
代码运行先跳到bootmain()(我的升级功能代码),--->main()(APP代码)
不过现在的问题是:
在bootmain()里面对FLASH操作不了,但是在main()中是可以的,我用的是同一段操作flash的代码,而且所需要擦除编程的flash是没有用到的一个块区。
1.我的cmd文件:
Flash28_API :
LOAD = FLASH_BOOT,
RUN = RAML0_PRG,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
2.我的bootmain()函数
#pragma CODE_SECTION(BOOT_MAIN,"FlashBoot");
void BOOT_MAIN (void)
{
init();//各种初始化
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd,&RamfuncsRunStart);
CallFlashAPI();
}
3.调用FLASH函数
#pragma CODE_SECTION(CallFlashAPI,"Flash28_API");//FlashBoot
CallFlashAPI();//对FLASH进行擦除,编写........
对照例程做的,感觉没有问题,但是就是不能对FLASH操作。
能否帮我看下
谢谢!!