打印
[技术问答]

N76E003之IAP

[复制链接]
761|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
uptown|  楼主 | 2024-4-29 09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
修改FLASH数据通常需要很长时间,不像RAM那样可以实时操作。而且擦除、编程或读取FLASH数据需要遵循相当复杂的时序步骤。N76E003提供方便FALSH编程方式,可以帮助用户通过IAP方式,重新编程FLASH内容。IAP就是通过软件实现在线电擦除和编程的方法。
通过设置IAPEN(CHPCON.0受TA保护)使能IAP,并且设置IAPUEN寄存器的相应位,使能需要升级的FLASH区域(CONFIG、LDROM、APROM),用户将16位操作地址写入IAPAH和IAPAL,数据写入IAPFD,命令写入IAPCN。然后通过设置触发位IAPGO(IAPTRG.0),去执行IAP。注意:IAPTRG也受TA保护。此时,CPU保持程序计数器,内嵌IAP自动控制内部充电泵提高电压和信号时序。擦除和编程时间是内部控制的,与工作电压和频率无关。通常页擦除时间是5ms,字节编程时间是 3.5μs。IAP动作完成后,程序计数器继续运行之后的指令,IAPGO位将自动清零。IAPFF (CHPCON.6)是IAP错误标志,可以用来检查之前IAP操作成功与否。通过这些纯软件的设置,用户可以很方便对FLASH存储器进行擦除、编程和校验。


IAP可以方便用户更新FLASH内容,不过用户必须遵循一定规则,以确保IAP正确执行,否则可能引起不确定的结果,甚至损坏器件。此外,下文对于正确执行IAP有很好建议。
(1)没有IAP操作时,用户必须清IAPEN (CHPCON.0)位。可以防止系统意外触发IAP。此外,IAP需要使用内部HIRC振荡器。如果选择外部时钟源,禁止IAP将停止内部HIRC,可以达到省电的目的。注:写IAPEN受TA保护。
(2)当LOCK位(CONFIG0.1) 被激活,IAP读、写或擦除仍然有效。

在进行IAP时,如果中断打开应该临时清除EA位
擦除或编程的页不能是当前代码执行的页。否则会出现不可预计程序动作,甚至破坏存储的数据
使用flash存储器作为数据存储
在一般应用中,有时需要一些数据在断电情况下不能丢失,以便用户读回或更新,作为系统控制的参数。N76E003支持IAP功能并且存储在flash中的字节都可以用MOVC指令读取,所以很适合作为非易失数据存储器。Flash写次数为100,000次,以下参考应用代码:
汇编例程如下:
;******************************************************************************
; This code illustrates how to use IAP to make APROM 201h as a byte of
; Data Flash when user code is executed in APROM.
;******************************************************************************
PAGE_ERASE_AP EQU 00100010b
BYTE_PROGRAM_AP EQU 00100001b
ORG 0000h
MOV TA,#0Aah ;CHPCON is TA protected
MOV TA,#55h
ORL CHPCON,#00000001b ;IAPEN = 1, enable IAP mode
MOV TA,#0Aah ;IAPUEN is TA protected
MOV TA,#55h
ORL IAPUEN,#00000001b ;APUEN = 1, enable APROM update
MOV IAPCN,#PAGE_ERASE_AP ;Erase page 200h~27Fh
MOV IAPAH,#02h
MOV IAPAL,#00h
MOV IAPFD,#0FFh
MOV TA,#0Aah ;IAPTRG is TA protected
MOV TA,#55h
ORL IAPTRG,#00000001b ;write ‘1’ to IAPGO to trigger IAP process
MOV IAPCN,#BYTE_PROGRAM_AP ;Program 201h with 55h
MOV IAPAH,#02h
MOV IAPAL,#01h
MOV IAPFD,#55h
MOV TA,#0Aah
MOV TA,#55h
ORL IAPTRG,#00000001b
MOV TA,#0Aah
MOV TA,#55h
ANL IAPUEN,#11111110b ;APUEN = 0, disable APROM update
MOV TA,#0Aah
MOV TA,#55h
ANL CHPCON,#11111110b ;IAPEN = 0, disable IAP mode
MOV DPTR,#201h
CLR A
MOVC A,@A+DPTR ;Read content of address 201h
MOV P0,A
SJMP $
C 语言例程如下:
//******************************************************************************
// This code illustrates how to use IAP to make APROM 201h as a byte of
// Data Flash when user code is executed in APROM.
//******************************************************************************
#define PAGE_ERASE_AP 0x22
#define BYTE_PROGRAM_AP 0x21
/*Data Flash, as part of APROM, is read by MOVC. Data Flash can be defined as
128-element array in “code” area from absolute address 0x0200 */
volatile unsigned char code Data_Flash[128] _at_ 0x0200;
Main (void)
{
TA = 0xAA; //CHPCON is TA protected
TA = 0x55;
CHPCON |= 0x01; //IAPEN = 1, enable IAP mode
TA = 0xAA; //IAPUEN is TA protected
TA = 0x55;
IAPUEN |= 0x01; //APUEN = 1, enable APROM update
IAPCN = PAGE_ERASE_AP; //Erase page 200h~27Fh
IAPAH = 0x02;
IAPAL = 0x00;
IAPFD = 0xFF;
TA = 0xAA; //IAPTRG is TA protected
TA = 0x55;
IAPTRG |= 0x01; //write ‘1’ to IAPGO to trigger IAP process
IAPCN = BYTE_PROGRAM_AP; // Program 201h with 55h
IAPAH = 0x02;
IAPAL = 0x01;
IAPFD = 0x55;
TA = 0xAA;
TA = 0x55;
IAPTRG |= 0x01; //write ‘1’ to IAPGO to trigger IAP process
TA = 0xAA; //IAPUEN is TA protected
TA = 0x55;
IAPUEN &= ~0x01; //APUEN = 0, disable APROM update
TA = 0xAA; //CHPCON is TA protected
TA = 0x55;
CHPCON &= ~0x01; //IAPEN = 0, disable IAP mode
P0 = Data_Flash[1]; //Read content of address 200h+1
while(1);
}
N76E003 APROM程序DATAFLASH为EEPROM方式

#include <stdio.h>#include "N76E003.h"#include "Common.h"#include "Delay.h"#include "SFR_Macro.h"#include "Function_Define.h"bit BIT_TMP;//-------------------------------------------------------------------------UINT8 read_APROM_BYTE(UINT16 code *u16_addr){    UINT8 rdata;    rdata = *u16_addr>>8;    return rdata;}//-------------------------------------------------------------------------/*****************************************************************************************************************write_DATAFLASH_BYTE :user can copy all this subroutine into project, then call this function in main.******************************************************************************************************************/        void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data){    UINT8 looptmp=0,u8_addrl_r;    unsigned char code *cd_longaddr;    unsigned char xdata *xd_tmp;    //Check page start address    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r = 0;    }    else     {        u8_addrl_r = 0x80;    }//Save APROM data to XRAM    xd_tmp = 0x80;    cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;        while (xd_tmp !=0x100)    {        *xd_tmp = *cd_longaddr;        looptmp++;        xd_tmp++;        cd_longaddr++;    }// Modify customer data in XRAM    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        xd_tmp = u8_addrl_r+0x80;    }    else    {        xd_tmp = u8_addrl_r+0;    }    *xd_tmp = u8_data;//Erase APROM DATAFLASH page        IAPAL = u16_addr;        IAPAH = u16_addr>>8;        IAPFD = 0xFF;      set_IAPEN;         set_APUEN;    IAPCN = 0x22;                  set_IAPGO; //Save changed RAM data to APROM DATAFLASH    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r =0;    }    else    {        u8_addrl_r = 0x80;    }        xd_tmp = 0x80;      IAPAL = u8_addrl_r;    IAPAH = u16_addr>>8;        set_IAPEN;         set_APUEN;      IAPCN = 0x21;        while (xd_tmp !=0xFF)        {            IAPFD = *xd_tmp;            set_IAPGO;            IAPAL++;            xd_tmp++;        }        clr_APUEN;        clr_IAPEN;}    /******************************************************************************************************************/        void main (void) {        UINT8 datatemp;/* -------------------------------------------------------------------------*//*  Dataflash use APROM area                                                                         *//*    APROM 0x3800~0x38FF demo as dataflash                                                         *//* Please use Memory window key in C:0x3800 to check earse result                      */          /* -------------------------------------------------------------------------*/    //call write byte         write_DATAFLASH_BYTE (0x3881,0x55);        write_DATAFLASH_BYTE (0x3882,0x56);        write_DATAFLASH_BYTE (0x3855,0xaa);        write_DATAFLASH_BYTE (0x3856,0x66);//call read byte        datatemp = read_APROM_BYTE(0x3882);    while(1);}

下面针对每一个调用函数进行讲解

void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data){    UINT8 looptmp=0,u8_addrl_r;    unsigned char code *cd_longaddr;    unsigned char xdata *xd_tmp;    //Check page start address    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r = 0;    }    else     {        u8_addrl_r = 0x80;    }//Save APROM data to XRAM    xd_tmp = 0x80;    cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;        while (xd_tmp !=0x100)    {        *xd_tmp = *cd_longaddr;        looptmp++;        xd_tmp++;        cd_longaddr++;    }// Modify customer data in XRAM    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        xd_tmp = u8_addrl_r+0x80;    }    else    {        xd_tmp = u8_addrl_r+0;    }    *xd_tmp = u8_data;//Erase APROM DATAFLASH page        IAPAL = u16_addr;        IAPAH = u16_addr>>8;        IAPFD = 0xFF;        set_IAPEN;         set_APUEN;    IAPCN = 0x22;                  set_IAPGO; //Save changed RAM data to APROM DATAFLASH    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r =0;    }    else    {        u8_addrl_r = 0x80;    }        xd_tmp = 0x80;      IAPAL = u8_addrl_r;    IAPAH = u16_addr>>8;        set_IAPEN;         set_APUEN;      IAPCN = 0x21;        while (xd_tmp !=0xFF)        {            IAPFD = *xd_tmp;            set_IAPGO;            IAPAL++;            xd_tmp++;        }        clr_APUEN;        clr_IAPEN;}   

上面这个函数,是对DATAFLASH  EEPROM进行读写,有主函数给出地址和数据,由该函数进行处理



void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data){    UINT8 looptmp=0,u8_addrl_r;    unsigned char code *cd_longaddr;    unsigned char xdata *xd_tmp;    //Check page start address    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r = 0;    }    else     {        u8_addrl_r = 0x80;    }//Save APROM data to XRAM    xd_tmp = 0x80;    cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;        while (xd_tmp !=0x100)    {        *xd_tmp = *cd_longaddr;        looptmp++;        xd_tmp++;        cd_longaddr++;    }// Modify customer data in XRAM    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        xd_tmp = u8_addrl_r+0x80;    }    else    {        xd_tmp = u8_addrl_r+0;    }    *xd_tmp = u8_data;//Erase APROM DATAFLASH page        IAPAL = u16_addr;        IAPAH = u16_addr>>8;        IAPFD = 0xFF;        set_IAPEN;         set_APUEN;    IAPCN = 0x22;                  set_IAPGO; //Save changed RAM data to APROM DATAFLASH    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r =0;    }    else    {        u8_addrl_r = 0x80;    }        xd_tmp = 0x80;      IAPAL = u8_addrl_r;    IAPAH = u16_addr>>8;        set_IAPEN;         set_APUEN;      IAPCN = 0x21;        while (xd_tmp !=0xFF)        {            IAPFD = *xd_tmp;            set_IAPGO;            IAPAL++;            xd_tmp++;        }        clr_APUEN;        clr_IAPEN;}   

标红部分涉及到两个寄存器IAPL与IAPH,这起什么作用呢?看一下手册
由此可知,这两个寄存器是写入16位地址字节的,也就是说u8_addrl_r这个变量的含义是给寄存器提供地址,因此,需要一些数据的分析和处理,

u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r = 0;    }    else     {        u8_addrl_r = 0x80;    }//Save APROM data to XRAM    xd_tmp = 0x80;    cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;        while (xd_tmp !=0x100)    {        *xd_tmp = *cd_longaddr;        looptmp++;        xd_tmp++;        cd_longaddr++;    }

Save APROM data to XRAM
首先查看N76E003的数据手册得知这颗芯片的XRAM的大小为:768字节i ,即大小为0x300,另外还可知道Flash每一页的大小为128字节即0x80。这段历程划分区域到0X100(256)。



// Modify customer data in XRAM    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        xd_tmp = u8_addrl_r+0x80;    }    else    {        xd_tmp = u8_addrl_r+0;    }    *xd_tmp = u8_data;//Erase APROM DATAFLASH page        IAPAL = u16_addr;        IAPAH = u16_addr>>8;        IAPFD = 0xFF;        set_IAPEN;         set_APUEN;    IAPCN = 0x22;                  set_IAPGO;


Modify customer data in XRAM
在XRAM中修改客户数据




//Save changed RAM data to APROM DATAFLASH    u8_addrl_r = u16_addr;    if (u8_addrl_r<0x80)    {        u8_addrl_r =0;    }    else    {        u8_addrl_r = 0x80;    }        xd_tmp = 0x80;      IAPAL = u8_addrl_r;      IAPAH = u16_addr>>8;        set_IAPEN;         set_APUEN;      IAPCN = 0x21;        while (xd_tmp !=0xFF)        {            IAPFD = *xd_tmp;            set_IAPGO;            IAPAL++;            xd_tmp++;        }        clr_APUEN;        clr_IAPEN;}   



使用特权

评论回复
沙发
micoccd| | 2024-4-29 13:42 | 只看该作者
IAP操作会比直接写FLASH更快吗

使用特权

评论回复
板凳
Henryko| | 2024-5-8 21:27 | 只看该作者
iap需要特定软件下载吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

3492

帖子

2

粉丝