TMS320F2812 FLASH的应用和远程更新

1、概述

由于电力系统自动化设备大多安装在野外,给程序维护工作带来了极大的困难。已安装的设备若出现程序缺陷,或者用户提出新的需求,需要对程序进行更新。传统的维护方法均是到实地取下设备,通过仿真器进行烧写维护,此方法效率低,作业危险性大。考虑到多数设备具有通信信道,远程通信更新程序是智能设备的必然趋势和要求。

TMS 320F 2812片内有18k*16 RAM 以及128k*16 Flash资源, 可以用来存放程序代码、数据表格以及用户信息,可多次擦除和写入数据,并且片内带有电荷泵,使其可在正常工作电压下对FLASH的逐段擦写。TMS 320F 2812具备开发IAP系统的硬件条件,通过在Flash自定义的段中放置升级代码:擦写Flash、读取存储器和通信程序。升级时运行这段代码擦写Flash,更新应用程序,实现在线编程。

2、实现原理和步骤

首先将需要更新的程序,经过CCS编译环境生成.out文件,然后利用TI提供的转换工具将.out文件转换为16进制数据流文件,再通过上位机程序将数据流文件通过串口发送,然后经过各种传输通道如GPRS网络,最后通过TMS 320F 2812的串口,把需要升级的新代码数据流文件先存到外部扩展RAM芯片或FLASH芯片中,经过校验无误,才启动下位机升级程序,将外部RAMFLASH中代码数据搬移到相应的片内FLASH段中,实现程序的更新。

3、更新程序数据流文件的创建

  由于在CCS3.1开发环境中最后生成的文件是.out格式,此文件只能在CCS环境下通过JATG口下载到DSP中。为了实现程序的串口更新,还要将.out格式的文件转化成能被DSP Bootloader程序所能识别的引导表数据流格式。我们可以通过TI提供的数据转换工具Hex2000.out文件转化成数据流文件。为此,需要编写批处理文件,此文件的作用就是指定引导表的格式。例如创建批处理文件build2812hex,内容是:

RemoteUpdate.out        //输入文件名

-a                     //输出文件格式为txt

-map RemoteUpdate.map  //生成地址映射文件

-o RemoteUpdate.txt      //输出文件名

-boot                 //TMS 320F 2812Bootloader标准格式生成数据流

-sci8                 //8位模式,与电力规约中传输数据的字符宽度相符

接着在cmd命令行内输入命令:hex2000.exe build2812hex.cmd即可生成RemoteUpdate.txt文件

4引导表数据流文件的下载

上位机程序中最主要的功能就是分析解包数据流文件并将处理后的数据信息传给下位机,并控制程序更新的操作。

在分析解包数据流文件时,需要将RemoteUpdate.txt中的数据流文件内的每块程序块的大小和烧入FLASH的首地址等信息从RemoteUpdate.txt中提取出来,同时计算出暂时存入外扩存储器的相应地址,存放在结构体中。

上位机与设备终端的通讯采用电力规约(如05国电规约或IEC60870-5-101协议)的帧格式通讯规约的基础设计的。

在读取数据流文件的相关信息并处理过之后,进入传输数据流文件的数据段部分,在此过程中PC通讯程序将数据段部分分段添加到通讯报文的数据部分,分成多帧的形式,通过串口发送。每帧都自带校验和,并且设备终端在收到数据并且确认正确后,将发送确认帧到上位机。上位机只有在收到确认帧后,才会继续发送下一帧数据,否则将重新传送该帧的数据,直到收到确认帧为止。待全部数据发送完后,通过将发送数据的总长度通过特定帧下传给终端设备,并与终端设备所接收到的数据总长度相互比较,若两者不等,将全部重传,以此实现了总校验,提高了数据传输的正确性。

5、下位机文件数据的接收

    终端设备接收到PC通过串口传输的数据流的地址和大小等信息时,同时将占据外扩存储资源(RAMFLASH)的相关的应用程序关闭,保证了下传的数据流不被破坏,并且覆盖了程序正常运行时存放在该资源上的数据。在接收到PC的第一帧的更新信息时,除了外部串口通讯的中断,会关闭其他外部的可屏蔽中断,保证了接收的数据段的正确性、完整性。由于将所有的需更新的数据均存放在外扩的RAM中,保证若在传输更新数据的过程中,终端设备断电或者是传输丢帧的情况发生,原运行系统将完全正常工作,不会受到任何影响。此时上位机会发现错误,只需再次发出更新信号,并且重传所需更新的数据即可。

这部分的功能的实现即是实现写外部RAMFLASH的过程,下位机将收到的数据流根据其地址和大小信息,将数据写入外部RAMFLASH。例如假设系统现在外扩了一片FLASH芯片SST39VF3202,需要将数据流信息保存在外部FLASH中,需要编写如下的函数,相关参数和操作请具体查阅SST39VF3202使用手册:

int WriteSstflash(far Uint16 *pdata,Uint32 wordadd,Uint16 length);    //write words into device

int EraseSstflashSector(Uint16 sectornum); // Erase one sector (2K words)

int EraseSstFlashBlock (Uint16 blocknum); // Erase one block (32K word)

int EraseSstFlashChip(void);// Erase the whole chip

void  SuspendErase(void); // Temporarily suspend one sector-erase or block-erase

int  ResumeErase(void);  // Resume suspended sector-erase or block-erase

int16 CheckToggleReady (Uint32 wordadd, Uint32 timeout);// Wait until DQ6 stops toggling

 

//写入SSTFLASH *pdata-数据缓存 wordadd - 字地址 length-长度

int WriteSstflash(far Uint16 *pdata,Uint32 wordadd,Uint16 length)

{

       Uint16 sector,area;

       volatile Uint16 *pflash = (volatile Uint16 *)EXFLASH_ADD;

       if(wordadd + length >= CHIP_SIZE)

              return FALSE;

       if(CheckToggleReady(0, SECTOR_ERASE_TIME) == FALSE)  //FLASH BUSY检测等待      

           return FALSE;

       sector = wordadd>>11;

       if(wordadd == (Uint32)sector*SECTOR_SIZE)    //段首擦除   

       {

              EraseSstflashSector(sector);     

       }

       if(wordadd+length >= (Uint32)(sector+1)*SECTOR_SIZE) //数据跨段

       {

              EraseSstflashSector(sector+1);        

       }

        area = wordadd>>19;      //FLASH区域选择 A0-A18

        wordadd &= (AERA_SIZE-1);

              while(length--)   

       {

              SET_FLASH_AERA(0); 

              *((volatile Uint16 *)(EXFLASH_ADD + 0x5555)) = 0x00AA; //擦写控制字

           *((volatile Uint16 *)(EXFLASH_ADD + 0x2AAA)) = 0x0055; 

           *((volatile Uint16 *)(EXFLASH_ADD + 0x5555)) = 0x 00A 0; 

               SET_FLASH_AERA(area);

           *(pflash + wordadd++) = *pdata++;

                     if(wordadd == AERA_SIZE)

              {

                     SET_FLASH_AERA(area++);

                     wordadd = 0;

              }

         if(CheckToggleReady(wordadd, WORD_PROGRAME_TIME) == FALSE)  //FLASH BUSY检测等待        

                return FALSE;            

    }

       return TRUE;

}

6、程序的更新实现

当下位机收到PC发来的程序更新命令以后,下位机开始执行程序更新,即将系统外部存储器中程序数据流写入到TMS320F2812的片内FLASH中。由于TMS320F2812片内FLASH不支持在其中一个扇区运行程序去擦出烧写其他扇区的操作,所以将外部存储器中的程序数据流写入TMS320F2812片内FLASH的操作必须在TMS320F2812片内RAM或外部RAM中运行。

例如在*.cmd文件中的SECTIONS {}段内添加如下代码,即可实现代码运行从FLASHJ段中转移到RAMH02中运行。

   Flash28_API

   {

        -lFlash2812_API_V210.lib(.econst)

        -lFlash2812_API_V210.lib(.text)

   }                   

LOAD = FLASHJ,

         RUN =  RAMH02 ,

         LOAD_START(_Flash28_API_LoadStart),

         LOAD_END(_Flash28_API_LoadEnd),

         RUN_START(_Flash28_API_RunStart),

         PAGE = 0

   ramfuncs    LOAD = FLASHJ,

                 RUN =  RAMH02 ,

                 LOAD_START(_RamfuncsLoadStart),

                 LOAD_END(_RamfuncsLoadEnd),

                 RUN_START(_RamfuncsRunStart),

                 PAGE = 0

 

7、片内FLASH的操作

片内Flash烧写程序是boot程序的主要部分,程序可分为3部分:擦除Flash、向已擦除的Flash段写入代码、校验代码写入的正确性。Ti 公司提供了专门用于操作TMS 320F 2812片内FlashAPI。规定了对TMS 320F 2812片内Flash擦除的最小单位是页,不能单独擦除Flash1个字或位。调用API函数库中的擦除函数Flash_Erase()可完成对Flash的擦除操作。调用API函数库中的编程函数Flash_Program()可完成对Flash的写操作。与此同时Ti 所提供的API函数能检测所擦除的Flash段是否越界等等,并且根据相应的错误返回错误状态信息。在对Flash写入代码段之后,可调用API中的Flash_Verify()函数对已经写入Flash的代码段和原始数据进行校验。

通过调用TIFLASH API库,编写了如下FLASH操作函数:

函数名称                           功能描述

void CallFlashAPI();              FLASH操作的核心函数,主要调用API

void Error(Uint16 Status);               鉴别错误类型,并停止运行

void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr);                  

void InitUpdate(void)                    初始化FLASH操作函数

void DataHexFunc(void)               FLASH操作主程序

值得注意的是FLASH操作的相关函数在系统的应用中需要从FLASH中搬移到RAM中来运行,所以需要进行如下定义:

#pragma CODE_SECTION(Error,"ramfuncs");

#pragma CODE_SECTION(CallFlashAPI,"ramfuncs");

利用#pragma定义将函数的入口地址定义在固定的位置ramfuncs,有利于系统的操作。

 应用中,系统需要将某些参数存入片内FLASH的某个段中,编写如下的

CallFlashAPI函数。

 

void CallFlashAPI(Param * Address)

{

      Uint16 Status;

      Uint16 *Flash_ptr;     // Pointer to a location in flash

      Uint16 *Origin_ptr;    // Pointer to a location in ram

      Uint32 Length;        

      int Sector;     

      Sector= SECTORJ;   //将参数保存在J

      Status = Flash_Erase(Sector,&EraseStatus);

      if(Status != STATUS_SUCCESS)

      {

       F2812_Error(Status);

      }                   

       Origin_ptr= (Uint16 *)Address; //参数所在的地址

       Length=sizeof(Param);     //

       Flash_ptr= (Uint16 *)0x3D8000;//最后保存的目标地址FLASH J

    Status = Flash_Program(Flash_ptr,Origin_ptr,Length,&ProgStatus);

    if(Status != STATUS_SUCCESS)

    {

        F2812_Error(Status);

    }

    // Verify the values programmed.   

    Status = Flash_Verify(Flash_ptr,Origin_ptr,Length,&VerifyStatus);

    if(Status != STATUS_SUCCESS)

    {

        F2812_Error(Status);

    }                  

}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值