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.

TM4C123AH6PM 采用串口进行FLASH程序在线更新问题(采用flash bootloader)

Other Parts Discussed in Thread: UNIFLASH

问题背景:由于电路板装在复杂结构内部,必须实现串口更新flash程序,我在实现的时候,遇到了一系列问题。采用tivaware安装目录下的demo,建立自己的工程,编译bootloader,烧写到芯片中,bootloader接收数据进行应用程序更新。但是bootloader烧写到flash中,连接串口,给单片机发送测试命令,没有任何反应。在线调试bootloader,程序直接跑飞了,芯片直接被锁定了,并且不能连接仿真器了,必须用uniflash擦除flash。我也不知道哪里有错误。

详细问题如下:

1)demo 中的bl_link_ccs.cmd是否需要做修改,FLASH的 length应该定义为APP_START_ADDRESS吧,例如demo中0x2800,还有SRAM长度也应该改吧,因为SRAM长度是32K,应该是0x8000。
       TI技术支持邮件回复说应用程序的cmd文件中SRAM的origin 不能为0x20000000了,因为这个时候已经bootLoder占用了。我有个疑问,应为在bootloader运行的时候,应用程序不占用sram,为什么会有冲突呢。
      如果origin 不能为0x20000000,origin 应该定义为多少合适?我看了一下demo的程序,demo是将origin设置为0x20000000
MEMORY
{
FLASH (RX) : origin = 0x00000000, length = 0x00010000
SRAM (RWX) : origin = 0x20000000, length = 0x00010000
}
 
2)bootloader的.s文件是否应该修改,因为不同芯片的中断向量表不同。如果要改怎么该。我想请教一下应用程序cmd文件中.intvecs和vtable 是什么意思,代表什么?还有我看了一下bootloader的.s文件其中call application其中有一段程序是判断APP_START_ADDRESS、VTABLE_START_ADDRESS是否相等,不相等则将APP_START_ADDRESS起始地址的内容拷贝到VTABLE_START_ADDRESS起始地址中,拷贝长度是中断向量表的长度。这个VTABLE_START_ADDRESS是我在bl_config.h中定义等于0x2800的那个么(但是程序注释了一句话是setting VTABLE_START_ADDRESS to 0x20000000 (start of sram) is safe since this will use the same memory that the bootloader already uses for its vector table.)?然后再将APP_START_ADDRESS中的内容拷贝到NVIC_TABLE起始地址中。请问NVIC_TABLE代表什么?NVIC_TABLE和VTABLE_START_ADDRESS区别在哪里?
 
      还有疑问是若APP_START_ADDRESS 等于VTABLE_START_ADDRESS时,为什么就不用拷贝中断向量表了。
SECTIONS
{
.intvecs: > 0x00000000
.text : > FLASH
.const : > FLASH
.cinit : > FLASH
.pinit : > FLASH
.init_array : > FLASH
.vtable : > 0x20000000
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM
}


 3)因为我用串口进行程序更新,所以我将bootloader demo中bl_check.c/h  bl_config.c/h   bl_flash.c/h  bl_packet.c/h bl_uart.c/h  bl_main.c  bl_commands.h  bl_crystal.h  bl_startup_ccs.s  bl_link_ccs.cmd 单独拷贝出来,重新建立工程,我选择这些文件是否正确?编译时bl_config.c中存在如下问题:
    提示错误1:bl_config.c文件中的equ出错问题    _APP_STRAT_ADDRESS   equ   APP_STRAT_ADDRESS
 
我可以将上述代码改成这样么 #define _APP_STRAT_ADDRESS   APP_STRAT_ADDRESS ,或者有其它方法更好。
 
    提示错误2:bl_config.c文件末尾含有end语句,编译出错,将其删除编译正常,我可以删除吗,或者有其它解决方法  ?
 
        4)FLASH烧写问题:
每次我将编译好的bootloader程序,我用的编译器是ccs5.5。下载到目标板在线运行时,单步调试,程序直接跳转到UART_Receive函数,并且接收的字节个数特别大,但是只执行一次又跳出来了,直接跳转Updater 函数判断0x20000000地址的前两个字(是否为sp、或者复位向量)之后,程序就进入汇编语言中,感觉程序一次乱跑,程序走飞了??并且断电之后,又不能连接仿真器,必须用uniflash擦除程序,并且用uniflash擦除程序,flash setting 中8MHZ 16MHZ必须切换使用,有时8MHZ可以擦除,有时16MHZ可以擦除,否则报错。到底应该怎样设置?
      5)bootloader 程序能单步调试么?
  
  • 没有楼主改的这么详细。关于自己写boot的问题,可以参考这个帖子

    http://www.deyisupport.com/question_answer/microcontrollers/tiva_arm_cortex/f/96/t/61154.aspx

    其实用ROM_UpdateUART()这个函数更方便点。

  • 谢谢您的回答,这个帖子我之前看过,该帖子是通过LM programer 下载应用程序和bootloader程序,从应用程序跳转到bootloader 进行程序更新,是标准串口。

    而我采用的串口是cameralink接口映射的串口,我用cameralink线将pc机和电路板连接之后,芯片和LM programer 之间是未连接的。还有我用的芯片和demo的芯片是不一样的。

    请问用ROM_UpdateUART()怎么实现??

  • #define TARGET_IS_BLIZZARD_RB1
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_nvic.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "driverlib/rom.h"
    #include "driverlib/uart.h"
    void
    JumpToBootLoader(void)
    {
        //
        // We must make sure we turn off SysTick and its interrupt before entering
        // the boot loader!
        //
        ROM_SysTickIntDisable();
        ROM_SysTickDisable();
        //
        // Disable all processor interrupts.  Instead of disabling them
        // one at a time, a direct write to NVIC is done to disable all
        // peripheral interrupts.
        //
        HWREG(NVIC_DIS0) = 0xffffffff;
        HWREG(NVIC_DIS1) = 0xffffffff;
        ROM_UpdateUART();
    }
    void
    SetupForUART(void)
    {
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        // Configure the UART for 115200, n, 8, 1
        ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,
                                (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_WLEN_8));
        //
        // Enable the UART operation.
        //
        ROM_UARTEnable(UART0_BASE);
    }
    int main(void)
    {
        int i;
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
        ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x02);
        for(i=0;i<50;i++)
            ROM_SysCtlDelay(100000);
        SetupForUART();
        ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x04);
        JumpToBootLoader();
        while(1)
        {
        }
    }

    那个帖子上面就有的,可以参考看看。

  • 谢谢您的回复! 您的意思是强制跳转到ROM 中的自带bootloader 进行程序更新么?ROM_UpdateUART()函数看不到源码,串口接收的数据协议我不知道?

  • 苦行僧您好:

    您提到可以通过rom boadloader 中ROM_UpdateUART函数实现串口更新程序?
    现在有几个疑问:
    1、首先不知道ROM_UpdateUART接收数据的协议是什么?ROM_UpdateUART能提供其原函数和协议么?按照你给我发的改了一下程序烧写到flash中了,运行执行ROM_UpdateUART函数,我发送一个ping命令,0x03 0x20 0x20  总长度、校验和、数据,但是没有反应,返回状态数据。
    2、ROM_UpdateUART更新程序时是不是必须通过LM Programmer实现,因为我的电路板在复杂结构内部,不能直接连接PC机,必须通过其他设备将数据转发到我的电路板上
    3、如果不是必须通过LM Programmer,我可以自己编写一个发送程序数据(bin)文件的程序么?如果可以的话,每帧程序数据(例如8个字节)发送的周期是多少?怎么定?
    4、更新程序数据时,直接传bin文件就可以了,bin文件是否需要处理
  • 1.应该数据的协议是这个吧?我也不确定,因为这个程序内嵌ROM中了,只和LM Programmer进行通讯

    2.ROM_UpdateUART应该是必须通过LM Programmer通讯的,看来你自己得写boot了

    3.可以呀,如果自己写boot的话,串口通讯的协议自己定

    4.直接传bin文件应该就可以了。你需要单独做一个离线的烧写工具,这样的工程量更大了。你可以咨询下,TI有没有这样的离线烧写工具