LPC1768IAP(详解,有上位机)

  之前说了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有啥变化

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

  综上,协议没变,我们依然可以按照之前的协议使用,那么,之前的上位机还算可以使用的

  对了,该上位机需要下载bin文件,需要在keil中将axf转换成bin文件,设置如下

  Target的user界面

  注意啊,这是我的工程分布,我在工程文件所在目录里面放了一个output目录,axf生成到了output目录中,如果你没有output目录,那么将output删除,设置生成axf的位置和工程文件的位置位于同一目录就可以了

http://download.csdn.net/detail/dengrengong/8499921

时间: 2024-12-23 05:17:21

LPC1768IAP(详解,有上位机)的相关文章

STM32_IAP详解(有代码,有上位机)

Iap,全名为in applacation programming,即在应用编程,与之相对应的叫做isp,in system programming,在系统编程,两者的不同是isp需要依靠烧写器在单片机复位离线的情况下编程,需要人工的干预,而iap则是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级.在工程应用中经常会出现我们的产品被安装在某个特定的机械结构中,更新程序的时候拆机很不方便,使用ia

SVM-支持向量机原理详解与实践之一

目录(?)[+] 前言 SVM机器学习与深度学习 人工智能领域 机器学习与深度学习 SVM简介 SVM原理分析 快速理解SVM原理 线性可分和线性不可分 函数间隔和几何间隔 超平面分析与几何间隔详解 二次最优化 SVM-支持向量机原理详解与实践 前言 去年由于工作项目的需要实际运用到了SVM和ANN算法,也就是支持向量机和人工神经网络算法,主要是实现项目中的实时采集图片(工业高速摄像头采集)的图像识别的这一部分功能,虽然几经波折,但是还好最终还算顺利完成了项目的任务,忙碌一年,趁着放假有时间好好

iOS开发——实战篇&amp;Xcode 7真机测试详解

Xcode 7真机测试详解 1.准备 注意:一定要让你的真机设备的系统版本和app的系统版本想对应,如果不对应就会出现一个很常见的问题:could not find developer disk image 首先,准备好下面的设备机相关软件 MAC版本:OSX10.10.4 Xcode版本:Xcode7 beta5(点击下载) 真机设备:iPad Air(iOS 8.1.3)/iphone 6 2.首先先安装Xcode7,并且运行Xcode,点击左上角菜单Xcode -> Preferences

信号量机制中的DOWN操作与UP操作详解

DOWN操作:linux内核中,对信号量的DOWN操作有如下几种: void down(struct semaphore *sem); //不可中断 int down_interruptible(struct semaphore *sem);//可中断 int down_killable(struct semaphore *sem);//睡眠的进程可以因为受到致命信号而被唤醒,中断获取信号量的操作. int down_trylock(struct semaphore *sem);//试图获取信号

51采集PCF8591数据通过ESP8266上传C#上位机

效果    如果想用手机做可以参考这篇文章,自己的协议规定在文章中 android 之TCP客户端编程 ---恢复内容开始--- 请问一下博客为什么又不能直接复制粘贴图片了呢............ 先看8266的配置,8266我是用的Lua语言写的,,因为方便快捷....这次写的当然比以前完善...... 关于WIFI模块可以看这几篇 ESP8266使用详解 NodeMCU初探 ESP8266刷AT固件与nodemcu固件 (一)Lua脚本语言入门 (二)Lua脚本语言入门 (三)Lua脚本语

Grub&initrd&initramfs详解

一.GRUB(Boot loader) 二.Grub命令行 三.Grub加密 四.进入单用户模式 五.Grub损坏,修复 六.救援模式 七.内核模块获取 八.ramdisk和initrd 九.内核信息输出的伪fs 十.initramfs和initrd的区别 一.GRUB(Boot loader)    Grub:GRand Unified Bootloader        Grub 0.x:grub legacy        Grub 1.x:grub2    grub legacy:  

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

使用LVS实现负载均衡原理及安装配置详解

转:http://www.cnblogs.com/liwei0526vip/p/6370103.html 使用LVS实现负载均衡原理及安装配置详解 负载均衡集群是 load balance 集群的简写,翻译成中文就是负载均衡集群.常用的负载均衡开源软件有nginx.lvs.haproxy,商业的硬件负载均衡设备F5.Netscale.这里主要是学习 LVS 并对其进行了详细的总结记录. 一.负载均衡LVS基本介绍 LB集群的架构和原理很简单,就是当用户的请求过来时,会直接分发到Director

大型网站架构系列:负载均衡详解

面对大量用户访问.高并发请求,海量数据,可以使用高性能的服务器.大型数据库,存储设备,高性能Web服务器,采用高效率的编程语言比如(Go,Scala)等,当单机容量达到极限时,我们需要考虑业务拆分和分布式部署,来解决大型网站访问量大,并发量高,海量数据的问题.从单机网站到分布式网站,很重要的区别是业务拆分和分布式部署,将应用拆分后,部署到不同的机器上,实现大规模分布式系统.分布式和业务拆分解决了,从集中到分布的问题,但是每个部署的独立业务还存在单点的问题和访问统一入口问题,为解决单点故障,我们可