Flash基础入门之LPC1768IAP(详解,有上位机)
小标 2019-01-24 来源 : 阅读 2240 评论 0

摘要:本文主要向大家介绍了Flash基础入门之LPC1768IAP(详解,有上位机),通过具体的内容向大家展现,希望对大家学习Flash基础入门有所帮助。

本文主要向大家介绍了Flash基础入门之LPC1768IAP(详解,有上位机),通过具体的内容向大家展现,希望对大家学习Flash基础入门有所帮助。

  之前说了stm32的iap编程,今天天气真好,顺手就来说说lpc1788的iap编程(没看前面的请查看stm笔记下的内容)
  首先是flash的算法,lpc1768并没有寄存器来让我们操作flash,他内置了iap的flash算法,在技术手册的525页有如下说明
 
  
  其支持的iap命令有这些
 
这样我们就能够做出相关的flash读写借口呢(具体请查看lpc1768的技术手册)
unsigned param_table[5];//传递参数列表
unsigned result_table[5];//返回结果列表
//调用iap命令
void iap_entry(unsigned param_tab[],unsigned result_tab[])
{
    void (*iap)(unsigned [],unsigned []);
 
    iap = (void (*)(unsigned [],unsigned []))IAP_ADDRESS;
    iap(param_tab,result_tab);
}
  通过这种手段就能够调用iap命令,我们演示性的看一个命令
//扇区准备好指令
//起始扇区号 结束扇区号 系统时钟
void prepare_sector(unsigned start_sector,unsigned end_sector,unsigned cclk)
{
    param_table[0] = PREPARE_SECTOR_FOR_WRITE;
    param_table[1] = start_sector;
    param_table[2] = end_sector;
    param_table[3] = cclk;
    iap_entry(param_table,result_table);
}
  该指令在写flash和擦除flash之前必须调用
具体的完整flash代码请查看工程文件,会在文章末尾上传
然后依旧是五个指令
"iap_down"
"iap_jump_app"
"iap_over"
"iap_set_flag"
"iap_clear_flag"
  功能和之前的stm32差不多,但是下载算法变化了,因为stm32支持的写入是每次写入一个十六位数据,而lpc1768每次写入8位数据,而且每次写入数据的量为128/256/512/1024/4096,正好没有我们之前所用的2048,所以算法修改成如下的样子
u8 iapbuf[1024] = {0}; //用于缓存数据的数组
u16 receiveDataCur = 0;  //当前iapbuffer中已经填充的数据长度,一次填充满了之后写入flash并清零
u32 addrCur = FLASH_APP1_ADDR;         //当前系统写入地址,每次写入之后地址增加2048
 
#define vu32 volatile unsigned int
 
//开始下载
void iap_down_s(void)
{
    u16 i = 0;
    u16 receiveCount;
    if(erase_user_flash())
    {
       printf("error\r\n");
       return;
    }
    printf("begin,wait data download\r\n");
    receiveMode = 1;//串口进入下载接收数据模式
    while(1)
    {
       //循环接收数据,每次必须要发128个数据下来,如果没有128,说明这是最后一包数据
       //接收到一包数据之后,返回一个小数点,发送完成,系统编程完成之后返回一个iap_over
       if(serial_Buffer_Length & 0x8000)
       {
           receiveCount = (u8)(serial_Buffer_Length&0x00ff);
           if(receiveCount == 128)//满足一包,填充并查看是否有了1024字节,有了写入闪存
           {
              for(i = 0; i < receiveCount; i++)
              {
                  iapbuf[receiveDataCur] = serial_Buffer[i];
                  receiveDataCur++;//完成之后receiveDataCur++;
              }
              receiveExpectCount = 0;//清除期望接收模式
              serial_Buffer_Length = 0;//清除串口满标志
              printf(".");//每次接受一次数据打一个点
              //此时需要检测receiveDataCur的值,要是放满了,就需要写入
              if(receiveDataCur == 1024)
              {
                  //写入flash中
                  if(write_flash(100000,addrCur,(unsigned*)iapbuf,1024))
                  {
                     receiveMode = 0;
                     addrCur = FLASH_APP1_ADDR;
                     receiveDataCur = 0;
                     return;
                  }
                  addrCur += 1024;//地址+2048
                  //写完之后receiveDataCur要清零等待下一次传输
                  receiveDataCur = 0;
              }
              else //有可能最后一包有128个数据但是最终没有2048个数据,此时扩展一个指令用于完成最后一个的写入
              {
                 
              }
              //还没放满,等待下一次数据过来
           }
           else   //不满足一包,说明数据传送这是最后一包,写入闪存
           {
              //没有一包也要传送到缓存中
              for(i = 0; i < receiveCount; i++)
              {
                  iapbuf[receiveDataCur] = serial_Buffer[i];
                  receiveDataCur++;//完成之后receiveDataCur++;
              }
              receiveExpectCount = 0;//清除期望接收模式
              serial_Buffer_Length = 0;//清除串口满标志
              printf(".");//每次接受一次数据打一个点
              //要将没接收满的数据变成0xff
              for(i= receiveDataCur; i < 1024; i++)
              {
                  iapbuf[i] = 0xff;
              }
              //之后就要将这数据写入到闪存中
              if(write_flash(100000,addrCur,(unsigned*)iapbuf,1024))
              {
                  receiveMode = 0;
                  addrCur = FLASH_APP1_ADDR;
                  receiveDataCur = 0;
                  return;
              }
              //printf("\r\nwrite addr %x,length %d\r\n",addrCur,receiveDataCur);
              //写完之后要把地址恢复到原来的位置
              addrCur = FLASH_APP1_ADDR;
              receiveDataCur = 0;
              //写完之后要退出下载循环并告诉上位机,已经下载完了
              printf("download over\r\n");
               //同时,也要退出下载循环模式
              receiveMode = 0;
              return;
           }
      
  因为lpc1768比较独特的扇区分区,如下
 
我们要修改地址的定义,现在app代码不能存放在0x08002000位置了,而是存储在0x00003000的位置,我们将012三个扇区当做iap代码的存放区域,并将2号扇区的最后一个位定义成了app固化标志存在的位置,写入固化标志的函数如下
unsigned char iapConfigBuffer[4096];//一个扇区4K
 
//失败返回1 成功返回0
u8 Iap_Write_Config_Value(u8 value)
{
    u32 i = 0;
    u8 *p;
    p = (u8*)SECTOR_2_START;
    //首先要将第三扇区的数据全部读取到ram里面
    for(i = 0; i < 4096; i++)
    {
       iapConfigBuffer[i] = *p;
       p++;
    }
    //然后检查最后一个数据和我们要设置的数据是否相等
    if(iapConfigBuffer[4095] == value)//相等,不用设置了
    {
       return 0;
    }
    else
    {
       //不等,先擦除第2扇区
       prepare_sector(2,2,100000);
       erase_sector(2,2,100000);
       if(result_table[0] != CMD_SUCCESS)
       {
           return 1;//擦除失败
       }
       //将数组最后一个元素设置为指定值
       iapConfigBuffer[4095] = value;
       prepare_sector(2,2,100000);//根据地址找出应当准备哪一个扇区
       write_data(100000,SECTOR_2_START,(unsigned*)iapConfigBuffer,4096);
       if(result_table[0] != CMD_SUCCESS)
       {
         return 1;
       }
       return 0;
    }
}
  擦除一个扇区的时候必须将扇区内容保存下来,所以必须定义一个能存放4096数据的数组,写入的时候先读取,在擦除,防止数据丢失
Flash存放的地址修改成这样
#define APP_CONFIG_ADDR     0X00002FFF //配置地址
#define APP_CONFIG_SET_VALUE    0X55       //设置值
#define APP_CONFIG_CLEAR_VALUE  0XFF       //清零值
 
#define FLASH_APP1_ADDR     0x00003000     //第一个应用程序起始地址(存放在FLASH)
                                     //保留的空间为IAP使用
  相应的配置就要改成如下
 
 
  当然,在main函数中还是之前一样的流程
 
  而对于app来说,改动的位置是这些
 
 
  还有在系统初始化函数SystemInit中的这个
 
  修改成
#define VECT_TAB_OFFSET  0x3000
  这样基本就能完成了,突然发现,这样app是编译不过去的,原因在于startup_LPC17XX.s文件中的110行有这么一段
 
该段汇编代码在flash的0x000002fc位置存放了一个0xffffffff,但是app程序从0x00003000启动,是不能操作0x000002fc处的flash的,我们来看看这个位置存放的是什么
 
  可以看到,这一段是进行flash读保护的,这一段我们可以注释掉了,因为iap部分的启动代码我们没有改啊,iap代码中已经设置了crp,那iap引导的app只要不去修改,crp就是我们在iap中定义了,放心大胆的注释掉吧.
现在我们比一比相对于stm32的iap,lpc1788的iap有啥变化

flash擦写算法变了
程序的存储空间变了
中断向量表的位置变了
Crp是stm32没有的,算是一个新东西
因为flash的擦写算法变了,所以我们底层接收数据处理数据的方式变了

  综上,协议没变,我们依然可以按照之前的协议使用,那么,之前的上位机还算可以使用的
 
  对了,该上位机需要下载bin文件,需要在keil中将axf转换成bin文件,设置如下
  Target的user界面
 
  注意啊,这是我的工程分布,我在工程文件所在目录里面放了一个output目录,axf生成到了output目录中,如果你没有output目录,那么将output删除,设置生成axf的位置和工程文件的位置位于同一目录就可以了

以上就介绍了Flash的相关知识,希望对Flash有兴趣的朋友有所帮助。了解更多内容,请关注职坐标常用软件Flash频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved