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.

DSP-C2000 flash编程,自己定义的烧写函数在主函数中运行无法通过

Other Parts Discussed in Thread: CONTROLSUITE

我在使用一种 通过应用来烧写flash的功能,在应用程序中运行 flash API函数,然后将程序烧录到代码区,测试是 flash erase后,程序就卡死了。

硬件平台是F2812, 用来编程的 flash函数定义在RAM中,在main()函数中调用,请问这种方式还需要注意什么?  按照手册上的描述,只要编程函数运行在ram中,可以对任意的flash区域进行编程,可是实际中在对 codeflash区域编程失败,单独定义的一款dataflash可以实现。。。

 

 

  • 补充说明,我的主函数main()是在 flash中运行的,烧写函数在main()中调用,烧写函数本身在RAM段中加载; 我希望通过这个烧写函数将代码段直接覆盖我的整个flash代码区域。

     

  • 您好,

    的确,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任意操作。

    对比一下上面提到的文档参考看看吧。

  •  

    我自定义一个boot()子函数,然后把这个子函数加载到RAM 空间去运行,然后进行编程,这种调用不允许么?    如果不允许的话,那么有什么办法可以在reset后 运行一个独立的函数,这个独立函数运行后再跳到main()里面? 

     

     另外, 在通过 Hex2000得到HEX文件后,包含了地址信息,TI有工具可以把HEX文件改成 BIN文件么?

  • 请问您要擦除自身的代码段的目的是什么?

  • 我是为了在线的代码升级,嵌入式的方式实现,因而需要自定义boot程序,将升级代码烧录到当前的代码区,这种实现方式和CKFA(SCI的BOOT)类似,只不过目前函数头 main()还是在flash中(不想改变原有的程序和硬件结构),

    我的问题在于: flash的API调用测过了,没有问题;但是这个boot的结果不对,原因可能就是 main()在falsh中运行这个限制,

  • 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



  • 你好,我想请问一下你的这段代码是怎么跳出去的呢?

    “BootContious:
        LCR #_fFlashProcess
        LB    BootContious
        NOP
        NOP
        NOP
        LRETR

    在#_fFlashProcess中进行的处理吗

  • 还有请问一下你这是怎么实现数据从Flash搬移到RAM中并实现跳转的呢

  • 专家您好:

    能否请教下关于这个帖子的回答;

    现在我用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操作。

    能否帮我看下

    谢谢!!