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有啥变化
- flash擦写算法变了
- 程序的存储空间变了
- 中断向量表的位置变了
- Crp是stm32没有的,算是一个新东西
- 因为flash的擦写算法变了,所以我们底层接收数据处理数据的方式变了
综上,协议没变,我们依然可以按照之前的协议使用,那么,之前的上位机还算可以使用的

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

注意啊,这是我的工程分布,我在工程文件所在目录里面放了一个output目录,axf生成到了output目录中,如果你没有output目录,那么将output删除,设置生成axf的位置和工程文件的位置位于同一目录就可以了
http://download.csdn.net/detail/dengrengong/8499921
LPC1768IAP(详解,有上位机)的更多相关文章
- JVM内存详解-阅读笔记
- STM32_IAP详解(有代码,有上位机)
Iap,全名为in applacation programming,即在应用编程,与之相对应的叫做isp,in system programming,在系统编程,两者的不同是isp需要依靠烧写器在单片 ...
- javacv开发详解之1:调用本机摄像头视频(建议使用javaCV1.3版本)
javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...
- 【转】jumpserver 堡垒机环境搭建(图文详解)
jumpserver 堡垒机环境搭建(图文详解) 摘要: Jumpserver 是一款由python编写开源的跳板机(堡垒机)系统,实现了跳板机应有的功能.基于ssh协议来管理,客户端无需安装ag ...
- QAV250四轴穿越机安装全程详解(多图)
QAV250四轴穿越机安装全程详解 最近团队准备使用轻型穿越机QAV250做实验,本文记录了QAV250的安装过程,整理了开箱后较合理的安装顺序,以及各个步骤的注意事项,希望对有需要的朋友有所帮助.主 ...
- javacv开发详解之1:调用本机摄像头视频(建议使用javaCV最新版本)
javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...
- SVM-支持向量机原理详解与实践
前言 去年由于工作项目的需要实际运用到了SVM和ANN算法,也就是支持向量机和人工神经网络算法,主要是实现项目中的实时采集图片(工业高速摄像头采集)的图像识别的这一部分功能,虽然几经波折,但是还好最终 ...
- 【转】使用fastboot命令刷机流程详解
一.Fastboot是什么? 1.1 首先介绍Recovery模式(卡刷) 在系统进行定制时,编译系统会编译出一份ZIP的压缩包,里面是一些系统分区镜像,提供给客户进行手动升级.恢复系统.需要提前将压 ...
- ESP8266使用详解(AT,LUA,SDK)
https://www.cnblogs.com/yangfengwu/p/10100152.html 8266综合开发教程(LUA) https://www.cnblogs.c ...
随机推荐
- 闭包 -> map / floatMap / filter / reduce 浅析
原创: 转载请注明出处 闭包是自包含的函数代码块,可以在代码中被传递和使用 闭包可以捕获和存储其所在上下文中任意常量和变量的引用.这就是所谓的闭合并包裹着这些常量和变量,俗称闭包.Swift 会为您管 ...
- 红帽linux忘记root密码的配置
1.启动linux,不停按上下键,注意鼠标要点击进去才行. 2.按e键. 3.选择kernel/.... 再按e键 4.空格+single 按enter键. 5.按B键,进入root权限. ...
- android平台菜单返回键监听
//声明 void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event); //实现 //按键控制(检测onKeyReleased有反 ...
- Regionals 2010 :: NEERC Eastern Subregional
遇到的问题:题目看错...(TAT英语渣渣没办法) 这里具体就讲一些思想和trick ①A题遇到了公式里面的单位问题. ②E题就是变量初始化忘记了 ③J题就是分情况讨论,实际上没有那么难...(题目读 ...
- 转 Android HTTPS详解
目录(?)[-] 前言 HTTPS原理 SSLTLS协议作用 基本的运行过程 握手阶段的详细过程 客户端发出请求ClientHello 服务器回应ServerHello 客户端回应 服务器的最后回应 ...
- over-float清除浮动
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- LINQ to SQL语句对应SQL的实现
LINQ to SQL语句(1)之Where LINQ to SQL语句(2)之Select/Distinct LINQ to SQL语句(3)之Count/Sum/Min/Max/Avg LINQ ...
- springmvc配置首页的方式
<mvc:view-controller path="/" view-name="redirect:/user/loginUI" />
- java中instanceof的用法
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法:resu ...
- w3school之CSS学习笔记
由于web自动化测试中,会用到比较复杂的定位方式:CSS定位,这种定位方式比较简洁,定位速度较快,所以继续学习前端的CSS知识,总结下学习笔记,以便后续查看.同时,也希望能帮助到大家. 学习网址:ht ...