开源PLC学习笔记06(再从51开始 IAP)——2013_11_11
在笔记05中遇到环形队列的狙击,还好网上资料丰富,完成了初步理解。在FX1NProcessing函数中,调用了和IAP相关的函数,因为不影响理解,所以直接跳过了IAP的细节。现在要开始理解这些细节。什么是IAP?In Application Programming 是指在应用编程,单片机程序自己可以往程序存储器里写数据或修改程序!http://zhidao.baidu.com/link?url=Ob1__CoHYLCZZ1wd0PlwuxeaMSiDHMZiGbt3mdBu-BeF885lX4193TJw18RYiDhFZwZmJAAyxn_QVPamxxUZE_
51 IAP资料比较少,因为大多数需要IAP的设计都不会选51。
IAP编程和所选的MCU密切相关,不同MCU的IAP编程代码会不相同,不过原理和步骤大概类似。因为开源PLC选用的是MPC82g516,所以就以它的手册为辅助工具。点击此处下载 ourdev_428676.pdf(文件大小:1.56M) (原文件名:MPC82G516A8位微处理器中文用户手册(第三版).pdf)
看一下结构
看了结构图,继续采用边看代码边理解功能方法。
*******************************
好在IAP.c中函数比较少,先捏软柿子,
// 函数名称: IAPFlashErasureMode
//
// 功能描述:页面擦除模式
//
// 输 入:unsigned int pageaddr
//
// 输 出:void
void IAPFlashErasureMode(unsigned int pageaddr)
{
ISPCR=0x83; // ISPCR.7=1,启用ISP
// ISPCR=011, 假设MPC82系列运行在11.0592M
IFMT=0x03; // 选择页擦除模式
IFADRH=pageaddr>>8; // 这个页面必须在IAP存储区
IFADRL=pageaddr;
SCMD=0x46; // 触发的ISP处理
SCMD=0xb9; // MCU将会停止运行.直到处理完成
}
我第一次看到上面的代码,不知所措,因为有许多和IAP相关的寄存器操作
一一看下,
ISPCR=0x83; // ISPCR.7=1,启用ISP
振荡器频率6~12MHz,
IFMT=0x03; // 选择页擦除模式
本帖最后由 oldbeginner 于 2013-11-12 09:51 编辑
IFADRH=pageaddr>>8; // 这个页面必须在IAP存储区
IFADRL=pageaddr;
pageaddr是个形参,unsigned int pageaddr,因为IFADRH和IFADRL是8位,所以用16位的赋值时,pageaddr向右移8位赋值给IFADRH是高8位。
SCMD=0x46; // 触发的ISP处理
SCMD=0xb9; // MCU将会停止运行.直到处理完成
根据手册也很好理解。
和手册上例子一样。
*********************************
// 函数名称: IAPFlashProgrem
//
// 功能描述:单字节写入模式(无"检查是否写入成功")
//
// 输 入:unsigned int codeaddr,unsigned char ucdata
//
// 输 出:void
void IAPFlashProgrem(unsigned int codeaddr,unsigned char ucdata)
{
ISPCR=0x83; // ISPCR.7=1,启用ISP
// ISPCR=011, 假设MPC82系列运行在11.0592M
IFMT=0x02; // 进入编程模式
IFADRH=codeaddr>>8; // 这个字节必须在IAP存储区
IFADRL=codeaddr;
IFD=ucdata; // 填写待编程的数据
SCMD=0x46; // 触发的ISP处理
SCMD=0xb9; // MCU将会停止运行.直到处理完成
}
是手册上的例子。
******************************************
//=======================================
// 函数名称: IAPFlashReadMode
//
// 功能描述:单字节读取模式
//
// 输 入:unsigned int codeaddr
//
// 输 出:unsigned char
unsigned char IAPFlashReadMode(unsigned int codeaddr) // 读模式
{
ISPCR=0x83; // ISPCR.7=1,启用ISP
// ISPCR=011, 假设MPC82系列运行在11.0592M
IFMT=0x01; // 进入读模式
IFADRH=codeaddr>>8; // 这个字节必须在IAP存储区
IFADRL=codeaddr;
SCMD=0x46; // 触发的ISP处理
SCMD=0xb9; // MCU将会停止运行.直到处理完成 // 触发IAP
return IFD; // 读出的数据
}
也和手册一致。
// 函数名称: IAPFlashProgremMode
//
// 功能描述:单字节写入模式(含有"检查是否写入成功")
//
// 输 入:unsigned int codeaddr,unsigned char ucdata
//
// 输 出:void
IAPFlashProgremMode是个比较繁琐的函数,要逐步分析,
1、首先,void IAPFlashProgremMode(unsigned int codeaddr,unsigned char ucdata) // 编程模式
codeaddr是地址,ucdata是待编程的数据。
2、 unsigned char checkdata=0;
checkdata=IAPFlashReadMode(codeaddr);
把所写的数据赋值给checkdata,因为ucdata是待编程数据,所以两者应该相等。(具体原理还不清楚)
3、while(checkdata!=ucdata)
{
纠正措施;
}
如果不相等,如何解决。暂时跳过。
**********************************
要返回FX1NProcessing函数,去了解当时略过的几个IAP函数。
本帖最后由 oldbeginner 于 2013-11-12 11:39 编辑
oldbeginner 发表于 2013-11-11 18:39 static/image/common/back.gif
IFADRH=pageaddr>>8; // 这个页面必须在IAP存储区
IFADRL=pageaddr;
pageaddr是 ...
在IAP中存储非易失性数据,
// IAP 空间分配如下:(31K) ----ASCII转HEX后存储.
// 1.IAP起始页 0x8000 ~ 0xbfff 存储PLC程序 -- 对应PLC 的0x8000~0xbfff 地址共8000步程序空间
// 2.IAP最后一页0 地址 存储 PLC类型标识核实标志 共 1 个字节
// 3.IAP最后一页1 ~ PLCTypeArrayLenMAX 存储 PLC类型标识 共 PLCTypeArrayLen 个字节 PLCTypeArrayLen
// 4.IAP倒数第二页 缓存空间 不许被其他数据占用!
// 5.其他 保留
为什么这样分布还不是很清楚,先看代码,看是否能从中理解空间分布。
// 函数名称: WriteFlash
//FX1N.c
// 功能描述:HEX 转 ASCII
//
// 输 入:unsigned int WriteAddr,unsigned char *Buf,unsigned int WriteLen
//
// 输 出:void
void WriteFlash(unsigned int WriteAddr,unsigned char *Buf,unsigned int WriteLen)
{
unsigned int i;
unsigned char wrdata=0;
for(i=0;i<WriteLen*2;i+=2) // 由原来的每页写512字节,改为每页写256个字节.存储地址不连续; 由原来存储ASCII码格式,改为存储HEX格式.
{
wrdata=asctohex((unsigned char *)(Buf+i));
IAPFlashProgremMode(WriteAddr++,wrdata);
}
}
这里调用了(含有"检查是否写入成功")单字节写入模式,只看代码也比较难理解,画个图看看,
注释中:由原来的每页写512字节,改为每页写256个字节。感觉有问题,因为WriteAddr++,所以还是512个字节,而且还是连续的,反而被存储的内容不连续了。
如果改成i++,Writeaddr+=2,则好像符合1、由原来的每页写512字节,改为每页写256个字节。2、存储地址不连续。
感觉这里源程序的注释和代码不一致。
至于为何要改成256个字节,应该和页面缓冲区有关(由RAM决定),可以猜测MPC82G516的RAM是256字节。
oldbeginner 发表于 2013-11-12 09:42 static/image/common/back.gif
在IAP中存储非易失性数据,
// IAP 空间分配如下:(31K) ---- ...
// 函数名称: ErasurePLC
//
// 功能描述:PLC擦除IAP空间
//
// 输 入:unsigned char allorcode
//
// 输 出:void
这个函数的代码有点多,逐次了解,
********************************************
void ErasurePLC(unsigned char allorcode)
unsigned int i;
unsigned char ucdata=0;
*****************************************************************
1、全部擦除
if(allorcode==ErasureALL)
{
for(i=0;i<MCUIAPFLASHSIZE;i+=512) // 全部擦除 初始PLC程序为空
{
IAPFlashErasureMode(PLCIAPCODEAddr+i);
}
}
找到FX1N.c中的定义
#define ErasureALL 0
#define ErasureCODE 1
#define MCUFLASHSIZE 64*1024 // 64K
#define MCUIAPFLASHSIZE 31*1024 // 31K
#define MCUISPFLASHSIZE 1*1024 // 1K
而注释是
// 默认当前MPC82G516A的设置为
// 1KISP Code
// 31K IAP Code
// 32K Flash Code
注释应该改为64K Flash(其中包括1K ISP和 31K IAP)
首先,查看#define MCUIAPFLASHSIZE 31*1024 // 31K
可知 IAP code容量为31K。
然后,#define PLCIAPCODEAddr (MCUFLASHSIZE-MCUIAPFLASHSIZE-MCUISPFLASHSIZE)
根据字面意思就是,PLC IAP地址为,64*1024 - 31*1024 - 1*1024 = 32 * 1024 =64 * 512
地址的格式没见到过,是不是相对地址,先继续。
调用 IAPFlashErasureMode(PLCIAPCODEAddr+i);来执行擦除。
又由于一个循环for(i=0;i<62 * 512 ;i+=512)
IAPFlashErasureMode(64 * 512 + i);
从第64页开始,一共擦除62页。最后2页没有擦除。
*********************************************************
2、else if(allorcode==ErasureCODE),只擦除程序
3、擦除IAP缓存备份空间
IAPFlashErasureMode(PLCTempAddr);
查看 #define PLCTempAddr (MCUFLASHSIZE-MCUISPFLASHSIZE-1024) // IAP倒数第二页地址
PLCTempAddr= 64 * 1024 - 1 * 1024 - 1024 = 62 * 1024 = 124 * 512,IAP倒数第二页是第124页。
4、备份PLC 0x8000~0x805c 地址的数据,0x8000 =40 * 512第40页上的数据
for(i=0;i<0x5c;i++) // 备份PLC 0x8000~0x805c 地址的数据
{
ucdata=IAPFlashReadMode(i+0x8000);
IAPFlashProgremMode(i+PLCTempAddr,ucdata);
}
0x5c小于512字节,所以IAP倒数第二页可以放下。
5、擦除PLC程序空间
for(i=PLCIAPCODEAddr;i<PLCTempAddr;i+=512) // 擦除PLC程序空间
{
IAPFlashErasureMode(i);
}
6、还原PLC 0x8000~0x805c 地址的数据
for(i=0;i<0x5c;i++) // 还原PLC 0x8000~0x805c 地址的数据
{
ucdata=IAPFlashReadMode(i+PLCTempAddr);
IAPFlashProgremMode(i+0x8000,ucdata);
}
**************************************
上述IAP更新步骤遵循了手册上说明。
oldbeginner 发表于 2013-11-12 12:59 static/image/common/back.gif
// 函数名称: ErasurePLC
//
// 功能描述:PLC擦除IAP空间
Read code中涉及IAP的代码
Readdat=IAPFlashReadMode(ReadAddr+i-1); // 读FlashData
其中,ReadAddr是通过接收到的报文获得的,详细理解在笔记04中。这里复习一下,
*******************************************
// 计算得到读取地址:
for(i=4;i<8;i++)
Buffer=ascto0F(UartReceiveBuffer);
ReadAddr =Buffer<<12;
ReadAddr+=Buffer<<8;
ReadAddr+=Buffer<<4;
ReadAddr+=Buffer;
*********************************************
把i=1带入,看看结果
Readdat=IAPFlashReadMode(ReadAddr+i-1);
即Readdat=IAPFlashReadMode(ReadAddr);
然后调用IAP函数
IFADRH=ReadAddr>>8; // 这个字节必须在IAP存储区
IFADRL=ReadAddr;
然后
Readdat=IFD;
IFD保存着对应地址的数值,赋值给Readdat。
************************************************
1、首先,WriteAddr是通过报文得到的
// 计算得到写入地址:
for(i=4;i<8;i++)Buffer=ascto0F(eBuffer);
WriteAddr =Buffer<<12;
WriteAddr+=Buffer<<8;
WriteAddr+=Buffer<<4;
WriteAddr+=Buffer;
*************************************************
2、Write code中涉及IAP的代码
if(WriteAddr==0x8000)
ErasurePLC(ErasureCODE); // 擦除PLC程序区
刚理解过如何擦除程序区
***************************************************
3、WriteFlash(WriteAddr,(unsigned char *)Buffer+10),(unsigned char)WriteLen); // 写 flash
Buffer+10,指向报文的指令,是是由上位机发送的。
存储格式及报文发送格式说明:http://www.amobbs.com/thread-3303497-1-1.html
存储格式为字型,低在先,高在后(如指令END,指令码为00 0F,存储为0F 00。指令LDX002,指令码为24 02,存储为02 24)。
在报文发送时,以字为单位传送,低字节在先。在字节传送过程中,高位在先,低位在后,转换成 ASCII 码 后传送(即以存储格式传送)。
指令LDX002,指令码为24 02,存储格式为02 24,转换成 ASCII 码传送为30 32 32 34。
以 LD X002为例,则Buffer='0' ,Buffer='2',Buffer='2',Buffer='4',并且WriteLen=4。
本帖最后由 oldbeginner 于 2013-11-12 16:54 编辑
oldbeginner 发表于 2013-11-12 14:45 static/image/common/back.gif
Read code中涉及IAP的代码
Readdat=IAPFlashReadMode(ReadAddr+i-1); // 读FlashData
从上图中可以看出,FX1NProcessing是把三菱命令映射到相应Flash的核心。
从中也可看出,FX1NProcessing有两个关键功能,
1、接收电脑来的报文;
2、将报文写入Flash。
虽然main函数中也涉及到IAP功能,放在后面再理解。因为IAP的步骤是规定的,所以发挥空间不大。第1遍理解暂时到这里,因为芯片原因,后面还要移植,必定需要把IAP理解一清二楚。
下一步分析指令LD OUT SET RST是如何传递和实现功能的。
http://www.amobbs.com/thread-5558798-1-1.html
oldbeginner 发表于 2013-11-12 16:28 static/image/common/back.gif
从上图中可以看出,FX1NProcessing是把三菱命令映射到相应Flash的核心。
从中也可看出,FX1NProcessing ...
IAP主要补充相关硬件知识,不同芯片操作过程不太一致。
*******************************************************
先搜一下简单区别,http://zhidao.baidu.com/question/151117377.html?qbl=relate_question_1
ISP(In-system programmable)是在系统可编程:
指的是不需要把单片机从目标系统板上取下来就可以直接从PC往单片机里面烧录程序。
IAP(In-Application programmable)是在应用可编程:
指的是可以通过单片机自身的程序修改单片机该程序区的内容;
EEPROM功能是:
在程序区1中的程序可以修改程序区2中的内容;通常程序区2中的内容不可以执行,只能当数据使用,功能相当于EEPROM;
区别:
ISP:从PC机修改单片机程序区的内容(即烧录)
IAP:单片机自己修改自己程序区的内容
EEPROM:单片机程序区1中的程序可以修改程序区2中的内容
****************************************************************
http://www.ndiy.cn/archiver/tid-5836.html
ISP是指可以在板级上进行编程,也就是不用拆芯片下来,写的是整个程序,一般是通过ISP接口线来写。
IAP虽然同样也是在板级上进行编程,但是是自已对自已进行编程,在应用中进行编程,也即可以只是更改某一部分而不影响系统的其它部分,另外接口程序是自已写的,这样可以进行远程升级而不影响应用。
打个比喻吧:
1、ISP是把房子拆了再重造一间,那么在造好之前当然是不能住人的啦!
2、IAP是在造好的房子里边进行一些装修,当然人可以继续住啦!
*******************************************************
通常在用户需要实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信管道(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:
1)检查是否需要对第二部分代码进行更新
2)如果不需要更新则转到4)
3)执行更新操作
4)跳转到第二部分代码执行
对于STM32来说,因为它的中断向量表位于程序存储器的最低地址区,为了使第一部分代码能够正确地响应中断,通常会安排第一部分代码处于Flash的开始区域,而第二部分代码紧随其后。
在第二部分代码开始执行时,首先需要把CPU的中断向量表映像到自己的向量表,然后再执行其他的操作。
**********************************************************
本帖最后由 oldbeginner 于 2013-11-15 20:16 编辑
oldbeginner 发表于 2013-11-15 19:35 static/image/common/back.gif
IAP主要补充相关硬件知识,不同芯片操作过程不太一致。
********************************************* ...
考虑到资料的丰富程度和通用性,STM32是用来理解IAP比较好的入门芯片,而不是51。
第四十八章 串口IAP实验
http://www.openedv.com/posts/list/11494.htm
STM32 IAP 设计实例 (一)
http://blog.csdn.net/qq236106303/article/details/9977191
谢谢楼主!学习了! 我还以为xuyiyi回来了呢
页:
[1]