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.

C2000上电引导模式解析------【TI FAE 经验分享】

Guru 60308 points
Other Parts Discussed in Thread: CONTROLSUITE, TMS320F28335

在使用C2000的时候,经常遇到工程师说芯片仿真能够运行,但是单机跑却不能跑起来;或者在调试时,复位芯片 > run,发现程序不能跑起来。这其中的原因主要是没有了解C2000的引导模式设置。另外当我们想通过其他方式去引导芯片启动的时候,往往也需要清楚知道C2000的引导是怎么设置的。因此,在这里跟大家分享一下我对C2000引导模式的理解,希望对各位理解芯片从上电到跑到main这一段芯片运行情况有所帮助。

以C2000 Piccolo系列的引导模式为例,delfino稍微有点区别,concerto系列的引导则更复杂。但理解了Piccolo的引导原理对我们理解后面两个系列的芯片有非常大的帮助。

1.首先我们根据图1来看一下芯片上电后的代码执行流程,当芯片在接收到一个复位信号后,会到0x3FFFC0去复位向量,该复位向量跳到BootROM 0x3FF75C中去执行bootloader的程序,这里主要有initboot, 和SelectBootMode, 以及一些外设引导的函数。SeleteBootMode根据芯片的硬件或软件设置来判断芯片该去哪里寻找程序入口,直接目的是如何找到main,然后执行应用程序。

                               图1. 芯片的复位流程图

我们最常用到的主要有两种引导模式:

一种是boot to RAM,即跳到0x000000的RAM中,去开始执行指令,主要针对程序加载在RAM的仿真模式;另外一种是boot to Flash,则跳到0x3F7FF6中去开始执行代码。

相应的,程序会这两个入口地址0x000000, 0x3F7FF6放一条跳转指令,在codestart.asm源文件中,原因是在Flash的入口地址处只有两个单元的空间,后面是CSM模块,所以需要跳转;而在RAM中之所以也需要跳转,主要是因为在跳转到main之前,需要执行一小段代码_c_int00,该代码会使用0x000003之后的一段RAM,如果代码放在那里,在执行_c_int00之后会损坏代码。

另外就是一些外设引导模式,如SCI引导以及SPI引导等,像我们常使用的C2PROG软件就支持SCI引导,然后通过串口下载程序。

2. 那么芯片的SelectBootMode函数是如何来判断芯片的引导模式(boot mode)呢?

从图2中我们可以看到,首先会判断芯片是否连接仿真器,根据TRST引脚的状态来判断。

如果是仿真器连接,则进入仿真引导(Emulation Boot),这时候芯片的引导主要是靠2个RAM的单元来判断,即EMU_BMODE和EMU_KEY,地址是0xD01和0xD00,所以我们在连接仿真器后,可以首先修改这两个EMU_BMODE和EMU_KEY来设置引导模式;

如果没有连接仿真器,则进入单机跑模式(stand alone), 这时候芯片的引导主要靠GPIO34和GPIO37的状态,以及两个OTP存储单元的值来判断。不过我们经常没有使用OTP这两个单元,用GPIO的状态就已经够了。

                                            图2. 两种状态下的引导模式

3. 仿真器连接时的引导模式配置

  

当带仿真器的时候,芯片会根据EMU_BMODE和EMU_KEY这两个单元的值来判断引导模式,比如我们带仿真器最常用的就是引导到RAM,即需要设置EMU_KEY = 0X55AA, EMU_BMODE = 0X000A。当我们在仿真的时候,程序load到Flash的时候,就需要设置EMU_KEY = 0X55AA, EMU_BMODE = 0X000B,如果EMU_BMODE = 0x0003的话,由于我们没有对OTP单元进行操作,即OTP的值为0xFFFF,所以这种情况下也是boot to flash。

在带仿真器跑程序的时候,我们发现即使我们不配置引导模式,程序也能够跑到main,这主要是因为CCS的功能,在程序load到芯片的时候,或是reset > restart,CCS会自动屏蔽bootloader的过程,自动跳到main函数入口。如果我们只选择reset CPU,则需要配置引导模式,即对0x0d01, 0x0d00这两个单元在memory window进行写相应的值,或是在script的菜单中选择引导模式,程序才能够跑到main中。

  • 4. 单机跑是引导模式配置

    单机跑的时候,我们最常用的是跑到Flash中,这时候则需要配置GPIO34和GPIO37的引脚为高电平,由于Piccolo系列芯片这几个引导都有上电默认内部上拉使能,所以即使不用加上拉电阻也可以。这时候的引导模式是GetMode,由于我们没有去配置OTP两个单元,所以这两个单元默认为0xFFFF,所以芯片的引导模式最终为boot to Flash。

    5. 其他外设的引导模式

    从上面这几张图中可以看到还有许多外设引导的功能,以SCI引导为例,带仿真器和单机跑的时候,都要配置相应的存储单元以及GPIO口状态,使之配置为SCI boot mode。然后芯片会SCI boot 函数,准备接收串口的代码,上位机要根据SCI boot的通信协议,生成SCI boot的数据流格式,将数据通过串口发送给芯片,芯片的bootloader会接收该代码,接收完后会根据该数据流中的起始运行地址去开始执行从SCI下载的代码。

    参考文献:

    TMS320x2803x Piccolo Boot ROM reference guide

    Eric

     

  • 您好,我纠结于这个问题很久了。我现在的跑马灯的程序带仿真器跑比不带仿真器跑快很多,还有SCI串口带仿真器时能够正常发送接收数据,不带仿真器时就是乱码了,请问是不是都是这个引起的呢?如果是这样,我应该怎么解决呢?直接加BOOTLOADER程序就可以了么?

  • yafang,

    不带仿真器的时候,也即程序下载到Flash,需要对Flash进行初始化,Initflash()。 参见controlSUITE例程

    C:\ti\controlSUITE\device_support\f2803x\v127\DSP2803x_examples_ccsv5\flash_f28035

    另外程序在Flash上跑肯定比在RAM跑慢,如果你有些程序要求跑的比较快,那就把它copy到RAM中运行吧。

    建议你从controlSUITE中的例程去开始你的工作。

    至于SCI不带仿真器的时候乱码,带仿真器的时候程序是跑在RAM还是在Flash中?

    我认为这个跟bootloader没有关系。

    Eric

  • 您好,

    我已经把灯的亮灭在定时中断程序,中断程序放在RAM中运行,可是还是会出当拿掉仿真器后速度会变慢很多,附件中是我的代码,麻烦帮忙看一看

    #include "DSP280x_Device.h" // DSP280x Headerfile Include File
    #include "DSP280x_Examples.h" // DSP280x Examples Include File

    // Configure which ePWM timer interrupts are enabled at the PIE level:
    // 1 = enabled, 0 = disabled
    #define PWM3_INT_ENABLE 1

    // Configure the period for each timer
    #define PWM3_TIMER_TBPRD 0x1FFF

    // Make this long enough so that we can see an LED toggle
    #define DELAY 1000000L
    #define DELAY1 100000L

    // Functions that will be run from RAM need to be assigned to 
    // a different section. This section will then be mapped using
    // the linker cmd file.
    #pragma CODE_SECTION(epwm3_timer_isr, "ramfuncs");
    // Prototype statements for functions found within this file.

    interrupt void epwm3_timer_isr(void);
    void InitEPwmTimer(void);
    void Gpio_select(void);
    // Global variables used in this example
    Uint32 EPwm1TimerIntCount;
    Uint32 EPwm2TimerIntCount;
    Uint32 EPwm3TimerIntCount;
    Uint32 LoopCount;

    // These are defined by the linker (see F2808.cmd)
    extern Uint16 RamfuncsLoadStart;
    extern Uint16 RamfuncsLoadEnd;
    extern Uint16 RamfuncsRunStart;

    void main(void)
    {

    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP280x_SysCtrl.c file.
    InitSysCtrl();

    // Step 2. Initalize GPIO: 
    // This example function is found in the DSP280x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio(); // Skipped for this example 
    EALLOW;
    GpioCtrlRegs.GPAMUX1.all = 0x0; // GPIO pin
    GpioCtrlRegs.GPADIR.all = 0xFF; // Output pin
    GpioDataRegs.GPADAT.all =0xFF; // Close LEDs
    EDIS;

    // For this example use the following configuration:
    Gpio_select();

    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts 
    DINT;

    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared. 
    // This function is found in the DSP280x_PieCtrl.c file.
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt 
    // Service Routines (ISR). 
    // This will populate the entire table, even if the interrupt
    // is not used in this example. This is useful for debug purposes.
    // The shell ISR routines are found in DSP280x_DefaultIsr.c.
    // This function is found in DSP280x_PieVect.c.
    InitPieVectTable();

    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file. 
    EALLOW; // This is needed to write to EALLOW protected registers
    // PieVectTable.EPWM1_INT = &epwm1_timer_isr;
    // PieVectTable.EPWM2_INT = &epwm2_timer_isr;
    PieVectTable.EPWM3_INT = &epwm3_timer_isr;
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Step 4. Initialize all the Device Peripherals:
    // This function is found in DSP280x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example
    InitEPwmTimer(); // For this example, only initialize the ePWM Timers
    MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);

    // Call Flash Initialization to setup flash waitstates
    // This function must reside in RAM
    InitFlash();

    // Initalize counters: 
    EPwm1TimerIntCount = 0;
    EPwm2TimerIntCount = 0;
    EPwm3TimerIntCount = 0;
    LoopCount = 0;

    // Enable CPU INT3 which is connected to EPWM1-3 INT:
    IER |= M_INT3;

    // Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
    PieCtrlRegs.PIEIER3.bit.INTx3 = PWM3_INT_ENABLE;

    // Enable global Interrupts and higher priority real-time debug events:
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM

    // Step 6. IDLE loop. Just sit and loop forever (optional):
    EALLOW;
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;
    EDIS;

    for(;;)
    {
    // This loop will be interrupted, so the overall
    // delay between pin toggles will be longer. 
    DELAY_US(DELAY);
    LoopCount++;
    GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;
    }

    }


    void InitEPwmTimer()
    {

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks
    EDIS;

    // Setup Sync
    EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Pass through
    // Allow each timer to be sync'ed
    EPwm3Regs.TBCTL.bit.PHSEN = TB_ENABLE;
    EPwm3Regs.TBPHS.half.TBPHS = 300; 
    EPwm3Regs.TBPRD = PWM3_TIMER_TBPRD;
    EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Enable INT on Zero event
    EPwm3Regs.ETSEL.bit.INTEN = PWM3_INT_ENABLE; // Enable INT
    EPwm3Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced
    EDIS;


    }


    interrupt void epwm3_timer_isr(void)
    {
    Uint16 i;

    EPwm3TimerIntCount++;

    // Short Delay to simulate some ISR Code
    for(i = 1; i < 0x01FF; i++) {}
    GpioDataRegs.GPADAT.all=0xFFFDFFFF; //GPIO17=0    LED灯亮
    DELAY_US(DELAY1);
    GpioDataRegs.GPADAT.all=0xFFF7FFFF; //GPIO19=0     两个LED交替亮
    DELAY_US(DELAY1);
    // Clear INT flag for this timer
    EPwm3Regs.ETCLR.bit.INT = 1;

    // Acknowledge this interrupt to receive more interrupts from group 3
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }

    void Gpio_select(void)
    {


    EALLOW;

    GpioCtrlRegs.GPAPUD.bit.GPIO6 = 0; // Enable pullup on GPIO11
    GpioDataRegs.GPASET.bit.GPIO6 = 1; // Load output latch
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 0; // GPIO11 = GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO6 = 1; // GPIO11 = output

    GpioCtrlRegs.GPAPUD.bit.GPIO16= 0; // Enable pullup on GPIO11
    GpioDataRegs.GPASET.bit.GPIO16 = 1; // Load output latch
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0; // GPIO11 = GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO16 = 1; // GPIO11 = output

    GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0; // Enable pullup on GPIO11
    GpioDataRegs.GPASET.bit.GPIO17 = 1; // Load output latch
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0; // GPIO11 = GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO17 = 1; // GPIO11 = output

    GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; // Enable pullup on GPIO11
    GpioDataRegs.GPASET.bit.GPIO19 = 1; // Load output latch
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0; // GPIO11 = GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO19= 1; // GPIO11 = output

    GpioCtrlRegs.GPAPUD.bit.GPIO8 = 0; // Enable pullup on GPIO11
    GpioDataRegs.GPASET.bit.GPIO8 = 1; // Load output latch
    GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 0; // GPIO11 = GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO8 = 1; // GPIO11 = output

    GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0; // GPIO11 = GPIO
    GpioCtrlRegs.GPADIR.bit.GPIO31 = 0; // GPIO11 = output

    EDIS;

    }

  • 您好,我在使用F28035  sci boot 时碰到一些问题想咨询您: 我使用的sci是SCIA ,外面接的是485 芯片,不过这个芯片是自动使能端的,也就是说只要485a、485b两根线就可以使用,带仿真器调试过485口工作正常,拔掉仿真器将GPIO34和GPIO37设定为SCI启动,使用C2Prog1.5进行程序烧写时,提示错误“Connecting with target (autobaud)...  failed (no response)!”,请帮我分析下,谢谢!

  • 你先不用C2Prog软件烧录。

    用个低速波特率,9600,8bit,1stop,

    设置成SCIboot以后,上电,用串口助手发字符“A”,看看有没有返回“A”

    有说明通讯成功,应该是可以用C2Prog烧录

    没有返回说明通讯无法建立起来

    再检查一下你的自动使能的芯片对于a,b信号的要求,试试把DSP的串口TX上啦去掉?

  • 您好  请教下   我的程序无法进入中断(Controlsuite里的led blink例程)   是否跟这个boot有关系呢

  • HI  tongshu,

    我也遇到了同样的问题,你解决了这个问题没?

    怎么解决的? help

    Regards

    Fan

  • 我想问下,我连上ccs3.3后,你上文所说“我们带仿真器最常用的就是引导到RAM,即需要设置EMU_KEY = 0X55AA, EMU_BMODE = 0X000A。当我们在仿真的时候,程序load到Flash的时候,就需要设置EMU_KEY = 0X55AA, EMU_BMODE = 0X000B

    我想问下,从哪个地址设置EMU_KEY 和EMU_BMODE 值啊,谢谢

  • C2Prog请问下这个烧录软件从何处找到,谢谢

  • 你好

    EMU_KEY 的地址是0x0D00, EMU_BMODE是0x0D01, 通过memory brower可以修改。

    另外,带仿真器烧写的时候,CCS烧写完之后,默认会自动跳转到main,这个过程CCS屏蔽了这个boot loader的过程。

    ERIC
     

  • C2prog 可以到www.codeskin.com下载

    Eric

  • 帅哥你好,

            你在这里面提到的codestart.asm(图1下面第四行)和SelectBootMode函数(第2条),应该都是固化在DSP里面的吧,我在一般的工程里都没见过。

    ps.

    我只是在在前人做好的工程里面加点函数,增加点功能,只需会点c语言就行了,这些细节还得请教大神你呀

  • Jim

    F28xx_CodeStartBranch.asm应该在工程能够找到的。

    SelectBootMode是在BOOTROM中的,工程中没有

    Eric

  • 我将GPIO34拉高,而GPIO37/TDO悬空,为什么也能跳到FLASH里面去执行,这是什么原因?

    单机跑的时候,我们最常用的是跑到Flash中,这时候则需要配置GPIO34和GPIO37的引脚为高电平,由于Piccolo系列芯片这几个引导都有上电默认内部上拉使能,所以即使不用加上拉电阻也可以。这时候的引导模式是GetMode,由于我们没有去配置OTP两个单元,所以这两个单元默认为0xFFFF,所以芯片的引导模式最终为boot to Flash。

  • 那是因为GPIO37内部有上拉电阻,默认上拉使能。所以GPIO34,GPIO37都为高电平的话,就能跑到flash。

    Eric

  • 能够解释一下C2prog原理吗?

  • 请问试过用CAN烧写程序么,我用C2Prog这个软件无法切换到CAN port,是不是需要配合特殊的CAN硬件才行

  • 请问一下,我想通过CAN对28035程序进行更新,是不是必须将相应的GPIO设置为CAN的引导模式啊?

  • 我认为有三种方式:

    1. 配置GPIO口,设置引导模式

    芯片的ROM中有自带的引导程序,如果要进入那个引导程序,就需要配置对应的GPIO口,见TMS320x2803x Piccolo Boot ROM reference guide文档说明。

    同时需要上位机通过CAN硬件将对应格式的数据发送给到C2000.

    2. 在应用程序中跳转到ROM中的CAN引导入口

    参考例程C:\ti\controlSUITE\device_support\f2803x\v130\DSP2803x_examples_ccsv5\f2803x_flash_kernel

    这种情况是可以用在在线升级中。

    3. 自己写引导程序,包括flash API操作

    这种也用于在线升级中,跟2有点类似,只不过你可以自己定义数据格式,通过CAN接受上位机的数据,然后擦除flash,烧写接收到的数据包。

    Eric





  • 您好,Eric Ma,看了您分享的文章很有收获,我想在TI分享的boot loader例程上做些修改,写一个自己的bootloader,

    但是还有些基本的问题没搞清楚,您能否解答下?

    1、我打算代码分两部分,一部分放在A区做引导程序,另一部分是应用程序在其他区,请问A区的代码是否需要main函数?一个芯片里是否可以有

    两个main函数?

    2、将例程中代码烧写到A区,用仿真器单步调试的时候发现,selectmode函数内设置断点,发现根本无法进入,请问这种调试方法有什么问题吗?

    谢谢!

  • 你好,关于上电引导这部分,我现在也还没有弄成功,但是一个程序两个main函数是可以的吧。

  • Eric Ma:请问下 FLASH copy到RAM中运行,应该参考那些资料呢?谢谢!

  • 参考例程:

    C:\ti\controlSUITE\device_support\f2803x\v130\DSP2803x_examples_ccsv5\flash_f28035

    其中initflash这个函数就是从flash复制到ram中运行,

    1. 定义函数

    #pragma CODE_SECTION(InitFlash, "ramfuncs");

    void InitFlash(void)

    2. cmd

    ramfuncs : LOAD = FLASHD,
    RUN = RAML0,
    LOAD_START(_RamfuncsLoadStart),
    LOAD_SIZE(_RamfuncsLoadSize),
    RUN_START(_RamfuncsRunStart),
    PAGE = 0

    3. 调用前先copy to ram

    memcpy((uint16_t *)&RamfuncsRunStart,(uint16_t *)&RamfuncsLoadStart, (unsigned long)&RamfuncsLoadSize);

    // Call Flash Initialization to setup flash waitstates
    // This function must reside in RAM
    InitFlash();

    这样就可以。 

    Eric

  • 我是分开成两个工程的,bootloader通过CMD全部都放在一个扇区,如A扇区,另外用户的工程放在其他扇区,这样就可以由各自的main。 然后用bootloader跳转到app工程的codestart, 或是要升级时,APP跳转到bootloader的_c_int00.

    Eric

  • 一个工程是不可以有两个main的吧,会编译出错的。

    Eric

  • 现在ti的dsp已经得到了广泛应用了,ti原厂是不是可以把这些代码公开下,这样会极大的节省我们用户的时间。

  • C:\ti\controlSUITE\device_support\f2803x\v130\DSP2803x_examples_ccsv5\f2803x_flash_kernel

    这儿有最新的基于F2803x的例程,是发布出来的。我自己做的那个是没经过详细测试的,所以不能正式发布,只是分享一些思路而已。

    这是另外一个例子:

    Eric

  • 你好,Eric Ma,这个例程我研究了下,完全按照他的写法,脱开仿真器上电引导不能成功,

    我看前面的帖子讨论了不少分2个区域烧写代码的思路,如果这样做,那实际上完全不需要bootload,

    我只需在一个区域放烧写代码,另一个区域放执行代码,并配合上跳转指令,只要烧写的时候不少写该区域就可以了,

    这个和TI说的bootload有啥关系呢?文件格式A00也不需要,hex不就行了吗?

    那这样说来,bootloader有啥用呢?它到底有什么独特之处?

  • 我也感觉,ti给的bootloader对于实际应用来说,也没啥用处啊,最终还是靠自己写bootloader引导程序啊。

  • 我看前面的帖子讨论了不少分2个区域烧写代码的思路,如果这样做,那实际上完全不需要bootload,

    我只需在一个区域放烧写代码,另一个区域放执行代码,并配合上跳转指令,只要烧写的时候不少写该区域就可以了,

    放烧写代码即就是我们说的升级用bootloader,如我最初的帖子谈的那种思路。

    至于TI ROM中的bootloader,那种是出厂自带的,TI的逻辑,可以配合引导管脚来烧写芯片,包括裸片。

    ERIC

  • 一个程序或一个工程文件两个main函数,我认为是不行的。违背C语言的基础。

    但是对于DSP/MCU而言,DSP的flash的sector可以划分为多个flash区,因而是可以同时烧写两个main函数的,即两个工程。

  • 可以将两个工程放在不同的flash扇区,分开烧录。

  • 官方的办法适合脱机批量生产的!

  • 您好,我现在就是一个区域放烧写代码,一个区域放置执行代码。用仿真器烧写能够正常运行。当我使用烧写代码烧写一个新的执行代码后,程序无法启动。请问这个跳转指令是跳转到哪里?是执行代码main函数的位置么?我现在就是跳转到main函数位置,无法启动。

    2、如果新的执行函数和原执行函数基本不变,只是改改定时器参数等,是可以启动的。如果增加了.c文件或者main函数执行内容完全不同,这种情况无法启动;

    请问是在什么位置出现问题?跳转指令么?

  • 你好  我也出现了 这个报错 请问你是怎么解决的呢

  • 具体是什么样的报错?

    ERIC

  • 您好,我现在就是一个区域放烧写代码,一个区域放置执行代码。用仿真器烧写能够正常运行。当我使用烧写代码烧写一个新的执行代码后,程序无法启动。请问这个跳转指令是跳转到哪里?是执行代码main函数的位置么?我现在就是跳转到main函数位置,无法启动。

    这个跳转指令该怎么写呢?

  • Eric您好!

    我在使用28021进行SCI在线升级的时候遇到以下情况:在应用程序中嵌入通讯协议进入SCI_Boot,判断数据流的数据类型为08AA后开始copy我的BootLoader程序的.bin文件至RAM中,目前可以测试出copy完bin文件的过程执行正确,也返回了正确的EntryAddr(是RAM中的一个位置),按道理此时应该执行ExitBoot,然后跳转到EntryAddress位置去执行BootLoader程序,解锁、擦除Flash、传输需要更新的APPCode,可是现在的问题是在执行ExitBoot之后跳转到了Codestart的位置,重新开始执行我的APPCode了,麻烦指导一下这种情况会是什么原因导致的?特别感谢!

  • 你好!Eric Ma

    我看了你发的附件代码,为什么在Unlock_Main.c 的main函数中最开始都没有初始化时钟、串口就可以通过串口直接发送数据呢?如下

    void main(void)

    {

       Uint16 Status;

    //Clear HyperTerminal screen

    SCIARegs.SCIFFTX.bit.SCIFFENA = 1;

    SCIARegs.SCIFFTX.bit.TXFIFOXRESET = 0;

    SCIARegs.SCIFFTX.bit.TXFIFOXRESET = 1;

    SCI_SendStatus("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\r");

    SCI_SendStatus("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\r");

    .......................

  • 我看了你发的附件代码,为什么在Unlock_Main.c 的main函数中最开始都没有初始化时钟、串口就可以通过串口直接发送数据呢?如下

    void main(void)

    {

       Uint16 Status;

    //Clear HyperTerminal screen

    SCIARegs.SCIFFTX.bit.SCIFFENA = 1;

    SCIARegs.SCIFFTX.bit.TXFIFOXRESET = 0;

    SCIARegs.SCIFFTX.bit.TXFIFOXRESET = 1;

    SCI_SendStatus("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\r");

    SCI_SendStatus("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\r");

    Eric:

    我没印象有发过这部分代码函数。其实你再初始化一次也没问题,如果你找不到它在哪个地方被初始化。

  • 你好 Eric

    我是在你2016-2-17的回帖中看到的,其中有个附件5277.281x SCI flash program.zip 在附件中的CKFA工程中的main函数代码;

    麻烦你查看一下呢

    望不吝赐教!

  • 我是在你2016-2-17的回帖中看到的,其中有个附件5277.281x SCI flash program.zip 在附件中的CKFA工程中的main函数代码;

    Eric:

    关于串口的初始化那部分是在APP里面做了,然后接受到升级指令后,就直接跳转到CKFA来。

  • 您好,在学习TMS320F28335的Boot-ROM相关数据手册的时候,遇见了一些不太能理解的问题,希望能够向您请教!

    DSP上电复位后,4个GPIO引脚选择引导模式,若选择Boot to Flash/OTP/H0-SARAM,则不需要调用Bootloader加载程序到RAM中吗?而其他的SPI/SCI/I2C等外设存储器方式,则需要先用Bootloade加载程序再确定入口地址。

    请问cpu执行的代码到底是在ROM中还是RAM中?在我的理解中,应该是Bootloader将代码从片内或者片外ROM中复制带RAM中,再确定RAM中CPU执行程序的入口地址。但是在阅读数据手册的过程中,好像是说在若选择Boot toFlash引导模式,直接确定了CPU执行程序的入口地址,程序是从片内Flash中执行的,请问Boot to Flash引导模式中Flash中的程序到死要不要复制到RAM中去执行?

  • 您好

    我现在在做串口在线升级程序,想咨询您一下。我的升级程序写在FLASHG,应用程序写在FLASHE,我应该编写什么程序可以实现到另一个FLASH的跳转呢,即从FLASHG跳转到FLASHE,或者说从升级程序的main函数跳转至应用程序的main函数。

    谢谢!