[牛人杂谈] N76E003之IAP

[复制链接]
1376|7
 楼主| dongnanxibei 发表于 2018-8-24 10:12 | 显示全部楼层 |阅读模式
修改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存储器进行擦除、编程和校验。
1318049-20180706105701796-875149122.jpg
1318049-20180706105745948-1463414386.jpg
1318049-20180706105816187-1861245515.jpg
1318049-20180706105848527-79190218.jpg
1318049-20180706105922881-517512414.jpg
1318049-20180706105951232-1423486795.jpg
1318049-20180706110026063-1073879076.jpg
1318049-20180706110106888-2124350367.jpg
1318049-20180706110158681-1852063589.jpg
1318049-20180706110231028-1818188472.jpg
1318049-20180706110312571-1112729011.jpg



 楼主| dongnanxibei 发表于 2018-8-24 10:13 | 显示全部楼层
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次,以下参考应用代码:

汇编例程如下:
  1. ;******************************************************************************
  2. ; This code illustrates how to use IAP to make APROM 201h as a byte of
  3. ; Data Flash when user code is executed in APROM.
  4. ;******************************************************************************
  5. PAGE_ERASE_AP EQU 00100010b
  6. BYTE_PROGRAM_AP EQU 00100001b
  7. ORG 0000h
  8. MOV TA,#0Aah ;CHPCON is TA protected
  9. MOV TA,#55h
  10. ORL CHPCON,#00000001b ;IAPEN = 1, enable IAP mode
  11. MOV TA,#0Aah ;IAPUEN is TA protected
  12. MOV TA,#55h
  13. ORL IAPUEN,#00000001b ;APUEN = 1, enable APROM update
  14. MOV IAPCN,#PAGE_ERASE_AP ;Erase page 200h~27Fh
  15. MOV IAPAH,#02h
  16. MOV IAPAL,#00h
  17. MOV IAPFD,#0FFh
  18. MOV TA,#0Aah ;IAPTRG is TA protected
  19. MOV TA,#55h
  20. ORL IAPTRG,#00000001b ;write ‘1’ to IAPGO to trigger IAP process
  21. MOV IAPCN,#BYTE_PROGRAM_AP ;Program 201h with 55h
  22. MOV IAPAH,#02h
  23. MOV IAPAL,#01h
  24. MOV IAPFD,#55h

  25. MOV TA,#0Aah
  26. MOV TA,#55h
  27. ORL IAPTRG,#00000001b
  28. MOV TA,#0Aah
  29. MOV TA,#55h
  30. ANL IAPUEN,#11111110b ;APUEN = 0, disable APROM update
  31. MOV TA,#0Aah
  32. MOV TA,#55h
  33. ANL CHPCON,#11111110b ;IAPEN = 0, disable IAP mode
  34. MOV DPTR,#201h
  35. CLR A
  36. MOVC A,@A+DPTR ;Read content of address 201h
  37. MOV P0,A
  38. SJMP $
C 语言例程如下:
  1. //******************************************************************************
  2. // This code illustrates how to use IAP to make APROM 201h as a byte of
  3. // Data Flash when user code is executed in APROM.
  4. //******************************************************************************
  5. #define PAGE_ERASE_AP 0x22
  6. #define BYTE_PROGRAM_AP 0x21
  7. /*Data Flash, as part of APROM, is read by MOVC. Data Flash can be defined as
  8. 128-element array in “code” area from absolute address 0x0200 */
  9. volatile unsigned char code Data_Flash[128] _at_ 0x0200;
  10. Main (void)
  11. {
  12. TA = 0xAA; //CHPCON is TA protected
  13. TA = 0x55;
  14. CHPCON |= 0x01; //IAPEN = 1, enable IAP mode
  15. TA = 0xAA; //IAPUEN is TA protected
  16. TA = 0x55;
  17. IAPUEN |= 0x01; //APUEN = 1, enable APROM update
  18. IAPCN = PAGE_ERASE_AP; //Erase page 200h~27Fh
  19. IAPAH = 0x02;
  20. IAPAL = 0x00;
  21. IAPFD = 0xFF;
  22. TA = 0xAA; //IAPTRG is TA protected
  23. TA = 0x55;
  24. IAPTRG |= 0x01; //write ‘1’ to IAPGO to trigger IAP process
  25. IAPCN = BYTE_PROGRAM_AP; // Program 201h with 55h
  26. IAPAH = 0x02;
  27. IAPAL = 0x01;

  28. IAPFD = 0x55;

  29. TA = 0xAA;
  30. TA = 0x55;
  31. IAPTRG |= 0x01; //write ‘1’ to IAPGO to trigger IAP process
  32. TA = 0xAA; //IAPUEN is TA protected
  33. TA = 0x55;
  34. IAPUEN &= ~0x01; //APUEN = 0, disable APROM update
  35. TA = 0xAA; //CHPCON is TA protected
  36. TA = 0x55;
  37. CHPCON &= ~0x01; //IAPEN = 0, disable IAP mode
  38. P0 = Data_Flash[1]; //Read content of address 200h+1
  39. while(1);
  40. }


 楼主| dongnanxibei 发表于 2018-8-24 10:13 | 显示全部楼层
N76E003 APROM程序DATAFLASH为EEPROM方式
  1. #include <stdio.h>
  2. #include "N76E003.h"
  3. #include "Common.h"
  4. #include "Delay.h"
  5. #include "SFR_Macro.h"
  6. #include "Function_Define.h"

  7. bit BIT_TMP;

  8. //-------------------------------------------------------------------------
  9. UINT8 read_APROM_BYTE(UINT16 code *u16_addr)
  10. {
  11.     UINT8 rdata;
  12.     rdata = *u16_addr>>8;
  13.     return rdata;
  14. }
  15. //-------------------------------------------------------------------------


  16. /*****************************************************************************************************************
  17. write_DATAFLASH_BYTE :
  18. user can copy all this subroutine into project, then call this function in main.
  19. ******************************************************************************************************************/        
  20. void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
  21. {
  22.     UINT8 looptmp=0,u8_addrl_r;
  23.     unsigned char code *cd_longaddr;
  24.     unsigned char xdata *xd_tmp;
  25.    
  26. //Check page start address
  27.     u8_addrl_r = u16_addr;
  28.     if (u8_addrl_r<0x80)
  29.     {
  30.         u8_addrl_r = 0;
  31.     }
  32.     else
  33.     {
  34.         u8_addrl_r = 0x80;
  35.     }
  36. //Save APROM data to XRAM
  37.     xd_tmp = 0x80;
  38.     cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;   
  39.     while (xd_tmp !=0x100)
  40.     {
  41.         *xd_tmp = *cd_longaddr;
  42.         looptmp++;
  43.         xd_tmp++;
  44.         cd_longaddr++;
  45.     }
  46. // Modify customer data in XRAM
  47.     u8_addrl_r = u16_addr;
  48.     if (u8_addrl_r<0x80)
  49.     {
  50.         xd_tmp = u8_addrl_r+0x80;
  51.     }
  52.     else
  53.     {
  54.         xd_tmp = u8_addrl_r+0;
  55.     }
  56.     *xd_tmp = u8_data;
  57. //Erase APROM DATAFLASH page
  58.         IAPAL = u16_addr;
  59.         IAPAH = u16_addr>>8;
  60.         IAPFD = 0xFF;
  61.       set_IAPEN;
  62.         set_APUEN;
  63.     IAPCN = 0x22;         
  64.          set_IAPGO;
  65. //Save changed RAM data to APROM DATAFLASH
  66.     u8_addrl_r = u16_addr;
  67.     if (u8_addrl_r<0x80)
  68.     {
  69.         u8_addrl_r =0;
  70.     }
  71.     else
  72.     {
  73.         u8_addrl_r = 0x80;
  74.     }
  75.         xd_tmp = 0x80;
  76.       IAPAL = u8_addrl_r;
  77.     IAPAH = u16_addr>>8;
  78.         set_IAPEN;
  79.         set_APUEN;
  80.       IAPCN = 0x21;
  81.         while (xd_tmp !=0xFF)
  82.         {
  83.             IAPFD = *xd_tmp;
  84.             set_IAPGO;
  85.             IAPAL++;
  86.             xd_tmp++;
  87.         }
  88.         clr_APUEN;
  89.         clr_IAPEN;
  90. }   
  91. /******************************************************************************************************************/        


  92. void main (void)
  93. {
  94.         UINT8 datatemp;
  95. /* -------------------------------------------------------------------------*/
  96. /*  Dataflash use APROM area                                                                         */
  97. /*    APROM 0x3800~0x38FF demo as dataflash                                                         */
  98. /* Please use Memory window key in C:0x3800 to check earse result                      */         
  99. /* -------------------------------------------------------------------------*/
  100.    
  101. //call write byte
  102.         write_DATAFLASH_BYTE (0x3881,0x55);
  103.         write_DATAFLASH_BYTE (0x3882,0x56);
  104.         write_DATAFLASH_BYTE (0x3855,0xaa);
  105.         write_DATAFLASH_BYTE (0x3856,0x66);
  106. //call read byte
  107.         datatemp = read_APROM_BYTE(0x3882);
  108.     while(1);
  109. }


 楼主| dongnanxibei 发表于 2018-8-24 10:14 | 显示全部楼层
下面针对每一个调用函数进行讲解
  1. void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
  2. {
  3.     UINT8 looptmp=0,u8_addrl_r;
  4.     unsigned char code *cd_longaddr;
  5.     unsigned char xdata *xd_tmp;
  6.    
  7. //Check page start address
  8.     u8_addrl_r = u16_addr;
  9.     if (u8_addrl_r<0x80)
  10.     {
  11.         u8_addrl_r = 0;
  12.     }
  13.     else
  14.     {
  15.         u8_addrl_r = 0x80;
  16.     }
  17. //Save APROM data to XRAM
  18.     xd_tmp = 0x80;
  19.     cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;   
  20.     while (xd_tmp !=0x100)
  21.     {
  22.         *xd_tmp = *cd_longaddr;
  23.         looptmp++;
  24.         xd_tmp++;
  25.         cd_longaddr++;
  26.     }
  27. // Modify customer data in XRAM
  28.     u8_addrl_r = u16_addr;
  29.     if (u8_addrl_r<0x80)
  30.     {
  31.         xd_tmp = u8_addrl_r+0x80;
  32.     }
  33.     else
  34.     {
  35.         xd_tmp = u8_addrl_r+0;
  36.     }
  37.     *xd_tmp = u8_data;
  38. //Erase APROM DATAFLASH page
  39.         IAPAL = u16_addr;
  40.         IAPAH = u16_addr>>8;
  41.         IAPFD = 0xFF;
  42.         set_IAPEN;
  43.         set_APUEN;
  44.     IAPCN = 0x22;         
  45.          set_IAPGO;
  46. //Save changed RAM data to APROM DATAFLASH
  47.     u8_addrl_r = u16_addr;
  48.     if (u8_addrl_r<0x80)
  49.     {
  50.         u8_addrl_r =0;
  51.     }
  52.     else
  53.     {
  54.         u8_addrl_r = 0x80;
  55.     }
  56.         xd_tmp = 0x80;
  57.       IAPAL = u8_addrl_r;
  58.     IAPAH = u16_addr>>8;
  59.         set_IAPEN;
  60.         set_APUEN;
  61.       IAPCN = 0x21;
  62.         while (xd_tmp !=0xFF)
  63.         {
  64.             IAPFD = *xd_tmp;
  65.             set_IAPGO;
  66.             IAPAL++;
  67.             xd_tmp++;
  68.         }
  69.         clr_APUEN;
  70.         clr_IAPEN;
  71. }
上面这个函数,是对DATAFLASH  EEPROM进行读写,有主函数给出地址和数据,由该函数进行处理
  1. void write_DATAFLASH_BYTE(UINT16 u16_addr,UINT8 u8_data)
  2. {
  3.     UINT8 looptmp=0,u8_addrl_r;
  4.     unsigned char code *cd_longaddr;
  5.     unsigned char xdata *xd_tmp;
  6.    
  7. //Check page start address
  8.     u8_addrl_r = u16_addr;
  9.     if (u8_addrl_r<0x80)
  10.     {
  11.         u8_addrl_r = 0;
  12.     }
  13.     else
  14.     {
  15.         u8_addrl_r = 0x80;
  16.     }
  17. //Save APROM data to XRAM
  18.     xd_tmp = 0x80;
  19.     cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;   
  20.     while (xd_tmp !=0x100)
  21.     {
  22.         *xd_tmp = *cd_longaddr;
  23.         looptmp++;
  24.         xd_tmp++;
  25.         cd_longaddr++;
  26.     }
  27. // Modify customer data in XRAM
  28.     u8_addrl_r = u16_addr;
  29.     if (u8_addrl_r<0x80)
  30.     {
  31.         xd_tmp = u8_addrl_r+0x80;
  32.     }
  33.     else
  34.     {
  35.         xd_tmp = u8_addrl_r+0;
  36.     }
  37.     *xd_tmp = u8_data;
  38. //Erase APROM DATAFLASH page
  39.         IAPAL = u16_addr;
  40.         IAPAH = u16_addr>>8;
  41.         IAPFD = 0xFF;
  42.         set_IAPEN;
  43.         set_APUEN;
  44.     IAPCN = 0x22;         
  45.          set_IAPGO;
  46. //Save changed RAM data to APROM DATAFLASH
  47.     u8_addrl_r = u16_addr;
  48.     if (u8_addrl_r<0x80)
  49.     {
  50.         u8_addrl_r =0;
  51.     }
  52.     else
  53.     {
  54.         u8_addrl_r = 0x80;
  55.     }
  56.         xd_tmp = 0x80;
  57.       IAPAL = u8_addrl_r;
  58.     IAPAH = u16_addr>>8;
  59.         set_IAPEN;
  60.         set_APUEN;
  61.       IAPCN = 0x21;
  62.         while (xd_tmp !=0xFF)
  63.         {
  64.             IAPFD = *xd_tmp;
  65.             set_IAPGO;
  66.             IAPAL++;
  67.             xd_tmp++;
  68.         }
  69.         clr_APUEN;
  70.         clr_IAPEN;
  71. }


 楼主| dongnanxibei 发表于 2018-8-24 10:16 | 显示全部楼层
标红部分涉及到两个寄存器IAPL与IAPH,这起什么作用呢?看一下手册
1318049-20180706115751824-1314939831.jpg
由此可知,这两个寄存器是写入16位地址字节的,也就是说u8_addrl_r这个变量的含义是给寄存器提供地址,因此,需要一些数据的分析和处理,
  1. u8_addrl_r = u16_addr;
  2.     if (u8_addrl_r<0x80)
  3.     {
  4.         u8_addrl_r = 0;
  5.     }
  6.     else
  7.     {
  8.         u8_addrl_r = 0x80;
  9.     }
  10. //Save APROM data to XRAM
  11.     xd_tmp = 0x80;
  12.     cd_longaddr = (u16_addr&0xff00)+u8_addrl_r;   
  13.     while (xd_tmp !=0x100)
  14.     {
  15.         *xd_tmp = *cd_longaddr;
  16.         looptmp++;
  17.         xd_tmp++;
  18.         cd_longaddr++;
  19.     }
Save APROM data to XRAM
首先查看N76E003的数据手册得知这颗芯片的XRAM的大小为:768字节i ,即大小为0x300,另外还可知道Flash每一页的大小为128字节即0x80。这段历程划分区域到0X100(256)。
  1. // Modify customer data in XRAM
  2.     u8_addrl_r = u16_addr;
  3.     if (u8_addrl_r<0x80)
  4.     {
  5.         xd_tmp = u8_addrl_r+0x80;
  6.     }
  7.     else
  8.     {
  9.         xd_tmp = u8_addrl_r+0;
  10.     }
  11.     *xd_tmp = u8_data;
  12. //Erase APROM DATAFLASH page
  13.         IAPAL = u16_addr;
  14.         IAPAH = u16_addr>>8;
  15.         IAPFD = 0xFF;
  16.         set_IAPEN;
  17.         set_APUEN;
  18.     IAPCN = 0x22;         
  19.          set_IAPGO;


 楼主| dongnanxibei 发表于 2018-8-24 10:16 | 显示全部楼层
Modify customer data in XRAM
在XRAM中修改客户数据
1318049-20180706164006302-975724197.jpg
1318049-20180706164106984-975066929.jpg
1318049-20180706164626080-875416407.jpg


1318049-20180706164535413-1527771063.jpg
  1. //Save changed RAM data to APROM DATAFLASH
  2.     u8_addrl_r = u16_addr;
  3.     if (u8_addrl_r<0x80)
  4.     {
  5.         u8_addrl_r =0;
  6.     }
  7.     else
  8.     {
  9.         u8_addrl_r = 0x80;
  10.     }
  11.         xd_tmp = 0x80;
  12.       IAPAL = u8_addrl_r;
  13.       IAPAH = u16_addr>>8;
  14.         set_IAPEN;
  15.         set_APUEN;
  16.       IAPCN = 0x21;
  17.         while (xd_tmp !=0xFF)
  18.         {
  19.             IAPFD = *xd_tmp;
  20.             set_IAPGO;
  21.             IAPAL++;
  22.             xd_tmp++;
  23.         }
  24.         clr_APUEN;
  25.         clr_IAPEN;
  26. }

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

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

zhuomuniao110 发表于 2018-8-24 11:36 | 显示全部楼层
搞清楚IAP的几个寄存器就OK了。
c475301174 发表于 2018-8-24 11:38 | 显示全部楼层
bootloader 程序应该怎么写
您需要登录后才可以回帖 登录 | 注册

本版积分规则

225

主题

3870

帖子

18

粉丝
快速回复 在线客服 返回列表 返回顶部