zoukankan      html  css  js  c++  java
  • N76E003之IAP

    修改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;
    }    

    这部分比较复杂,我后续会有更新,如果有什么意见或建议,欢迎评论

    知识没有学完的时候,我只能保证明天的自己跟今天不一样,各个方面,无论是做人还是做事,无论是专业素质,还是为人处世,待人接物。

  • 相关阅读:
    Java 反射
    类中静态/普通/构造初始化顺序
    计算机世界中的0和1
    Java并发练习
    HashMap底层
    HashMap 与 Hashtable 的区别
    为什么重写了equals() 就要重写hashcode()
    干货型up主
    JSP页面元素
    重定向与请求转发的区别
  • 原文地址:https://www.cnblogs.com/zhugeanran/p/9272560.html
Copyright © 2011-2022 走看看