搜索
bottom↓
回复: 38

求读取AVR中唯一序列号的函数,加密用的.....

[复制链接]

出0入0汤圆

发表于 2012-7-12 12:12:31 | 显示全部楼层 |阅读模式
从手册上看ATMEGA48PA,88PA,168AP是有一个序列号可以在程序空间的代码中进行读取用来加密的.搞了两天了也没成功读取....
求这样的函数....
谢谢大家.

出0入0汤圆

发表于 2012-7-12 12:19:55 | 显示全部楼层
不知道的頂一下。

出0入0汤圆

 楼主| 发表于 2012-7-12 12:33:52 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2012-7-12 13:34:34 | 显示全部楼层
顶一下...

出0入0汤圆

 楼主| 发表于 2012-7-12 15:15:15 | 显示全部楼层
顶一下.

出0入296汤圆

发表于 2012-7-12 15:44:41 | 显示全部楼层
读14开始的10个字节……

出0入0汤圆

 楼主| 发表于 2012-7-12 16:07:03 | 显示全部楼层
Gorgon_Meducer 发表于 2012-7-12 15:44
读14开始的10个字节……

大神来啦!
求大神给个代码的例子.....我写了两天多了.......无法搞定.....

出0入0汤圆

发表于 2012-7-12 18:11:00 | 显示全部楼层
关注中……

出0入0汤圆

发表于 2012-7-12 18:27:32 | 显示全部楼层
boot.h的头文件有。boot_signature_byte_get(addr)

出0入0汤圆

 楼主| 发表于 2012-7-12 20:51:17 | 显示全部楼层
weuser 发表于 2012-7-12 18:27
boot.h的头文件有。boot_signature_byte_get(addr)

试了.不行啊...
直接提示../main.c:191: error: 'SIGRD' undeclared (first use in this function)

出0入0汤圆

发表于 2012-7-12 21:25:09 | 显示全部楼层
Gorgon_Meducer 发表于 2012-7-12 15:44
读14开始的10个字节……

大师级的还没讲话,都不要急

出0入0汤圆

 楼主| 发表于 2012-7-12 21:53:21 | 显示全部楼层
weuser 发表于 2012-7-12 18:27
boot.h的头文件有。boot_signature_byte_get(addr)

翻了N久的手删没有看到SIGRD这个位的定义在哪个地方.手册中那里是第一次出现这个词.前面也没有描述过.求大侠指点.

出0入0汤圆

发表于 2012-7-12 22:50:35 | 显示全部楼层
R_OSCCAL        =OSCCAL;

出0入0汤圆

发表于 2012-7-13 12:08:08 | 显示全部楼层
本帖最后由 weuser 于 2012-7-13 12:39 编辑

MEGA48的 SIGRD位作为保留位了,我把这个位跳过去试读。
我修改了boot.h文件
#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
改成下面的。

#if defined(__AVR_ATmega48__)
#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE))
#else
#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
#endif

然后
       Signature[0] = boot_signature_byte_get(0);
        Signature[1] = boot_signature_byte_get(2);
        Signature[2] = boot_signature_byte_get(4);
        Signature[3] = boot_signature_byte_get(1);

读出来 0x19 0xD9 0x32 0xC0  这个和ISP读出来的不一样。
MEGA48应该是不支持内部读的。


出0入0汤圆

发表于 2012-7-13 19:44:21 | 显示全部楼层
跟着走,找感觉

出425入0汤圆

发表于 2012-7-13 20:23:26 | 显示全部楼层
我有个产品,先给客户使用,全部付款以后,发短信给一串数字,输入数字就可以解除使用次数的限制。我想用这个序列号,实现这个功能,希望大家探讨一下。

出0入0汤圆

 楼主| 发表于 2012-7-13 20:51:31 | 显示全部楼层
weuser 发表于 2012-7-13 12:08
MEGA48的 SIGRD位作为保留位了,我把这个位跳过去试读。
我修改了boot.h文件
#define __BOOT_SIGROW_READ  ...

48没有,你读48PA试试!

出0入0汤圆

 楼主| 发表于 2012-7-13 21:03:46 | 显示全部楼层
以后做产品一定要用PA后缀的,强大的一B,有唯一序列号,还内建温度传感器!!!!!

出0入0汤圆

发表于 2012-7-13 21:11:43 | 显示全部楼层
guolun 发表于 2012-7-13 20:23
我有个产品,先给客户使用,全部付款以后,发短信给一串数字,输入数字就可以解除使用次数的限制。我想用这 ...


       不需要你去   要涨(账)了

出0入296汤圆

发表于 2012-7-13 23:59:53 | 显示全部楼层
feiben 发表于 2012-7-12 21:25
大师级的还没讲话,都不要急

还是那句话:只要芯片数据手册说能通过bootloader读取Signature Byte,就能通过这个手段读14开始的10个字节……这就是芯片的唯一ID。
如果你知道如何通过ISP时序读取Signature Byte,那么同样道理,你肯定能读取到地址14开始的10个字节……

出0入0汤圆

发表于 2012-7-14 00:52:22 | 显示全部楼层
喔  ,,,avr也有这功能

出0入0汤圆

发表于 2012-7-14 17:49:18 | 显示全部楼层
sibtck 发表于 2012-7-13 21:03
以后做产品一定要用PA后缀的,强大的一B,有唯一序列号,还内建温度传感器!!!!! ...

mega88PA 真有温度内部传感器么?
我原来一直以为只加了唯一序列号。 我是替换原来的老型号,加的功能基本没有注意。

出0入0汤圆

发表于 2012-7-14 18:02:49 | 显示全部楼层
.我跟楼上刚好相反,我只注意到有内部温度传感器,没注意到唯一序列号。

出0入0汤圆

发表于 2012-7-14 20:25:29 | 显示全部楼层
看来真有内部温度传感器。
原来手头有一份更新英文文档,英文不好,就没有仔细看。

出0入0汤圆

发表于 2014-12-19 19:36:02 | 显示全部楼层
下载了,非常感谢

出0入0汤圆

发表于 2014-12-19 19:43:47 | 显示全部楼层
Gorgon_Meducer 发表于 2012-7-13 23:59
还是那句话:只要芯片数据手册说能通过bootloader读取Signature Byte,就能通过这个手段读14开始的10个字 ...

在ICCAVR下如何读出来呢,请大师指点一下

出0入296汤圆

发表于 2014-12-20 16:14:48 | 显示全部楼层
1139193886 发表于 2014-12-19 19:43
在ICCAVR下如何读出来呢,请大师指点一下

用asm() 写在线汇编

出0入0汤圆

发表于 2014-12-20 16:31:55 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-12-22 21:42:58 | 显示全部楼层

求大神指点啊,汇编下如何写呢,不懂汇编,可以帮忙写这个代码吗?谢谢。

出0入296汤圆

发表于 2014-12-22 22:27:41 | 显示全部楼层
1139193886 发表于 2014-12-22 21:42
求大神指点啊,汇编下如何写呢,不懂汇编,可以帮忙写这个代码吗?谢谢。 ...

我没有写过ICC的汇编……

出0入296汤圆

发表于 2014-12-22 22:28:43 | 显示全部楼层

只要能读这个,就可以继续向后读取隐藏的signature row,里面有很多有趣的信息。我记得大约偏移量是14的地方,连续10个字节就是UID

出0入0汤圆

发表于 2014-12-22 22:29:13 | 显示全部楼层
Gorgon_Meducer 发表于 2014-12-22 22:27
我没有写过ICC的汇编……

汇编应该是通用的吧,其它编译器下面的汇编也应该可以编过去吧。

出0入296汤圆

发表于 2014-12-22 22:37:03 | 显示全部楼层
1139193886 发表于 2014-12-22 22:29
汇编应该是通用的吧,其它编译器下面的汇编也应该可以编过去吧。

不同编译器语法不同的。

出0入0汤圆

发表于 2014-12-22 22:47:06 | 显示全部楼层
Gorgon_Meducer 发表于 2014-12-22 22:37
不同编译器语法不同的。

哦,谢谢。我再想想办法吧

出0入0汤圆

发表于 2014-12-26 10:58:13 | 显示全部楼层
Gorgon_Meducer 发表于 2014-12-22 22:37
不同编译器语法不同的。


  可以请再帮个忙吗,其它编译环境下的汇编代码可以帮忙写下吗,我转到icc下用。实在不知道这个SN读的顺序和操作方法。,主要看指令和执行的流程,或者让画个时序图都行。

出0入296汤圆

发表于 2014-12-26 13:29:28 | 显示全部楼层
1139193886 发表于 2014-12-26 10:58
可以请再帮个忙吗,其它编译环境下的汇编代码可以帮忙写下吗,我转到icc下用。实在不知道这个SN读的顺 ...

  1. /***********************************************************
  2. *   函数库说明:Bootloader底层操作函数库                   *
  3. *   版本:      v1.00beta                                  *
  4. *   作者:      王卓然                                     *
  5. *   创建日期:  2008年8月31日                              *
  6. * -------------------------------------------------------- *
  7. *  [支 持 库]                                              *
  8. *   支持库名称:                                           *
  9. *   需要版本:                                             *
  10. *   声明库说明:                                           *
  11. * -------------------------------------------------------- *
  12. *  [版本更新]                                              *
  13. *   修改:                                                 *
  14. *   修改日期:                                             *
  15. *   版本:                                                 *
  16. * -------------------------------------------------------- *
  17. *  [版本历史]                                              *
  18. * -------------------------------------------------------- *
  19. *  [使用说明]                                              *
  20. ***********************************************************/


  21. /********************
  22. * 头 文 件 配 置 区 *
  23. ********************/
  24. # include "RD_MacroAndConst.h"
  25. # include "BL_Config.h"
  26. # include "PF_Config.h"

  27. /********************
  28. *   系 统 宏 定 义  *
  29. ********************/

  30. /*------------------*
  31. *   常 数 宏 定 义  *
  32. *------------------*/
  33. #ifndef SIGRD
  34.     # define SIGRD              5
  35. #endif

  36. # define SPM_ENBALE_RWW         (BIT(RWWSRE)|BIT(SPMEN))
  37. # define SPM_PAGE_WRITE         (BIT(PGWRT)|BIT(SPMEN))
  38. # define SPM_PAGE_ERASE         (BIT(PGERS)|BIT(SPMEN))
  39. # define SPM_FUSE_AND_LOCK_BITS (BIT(BLBSET)|BIT(SPMEN))
  40. # define SPM_WRITE_BUFFER       BIT(SPMEN)
  41. # define SPM_READ_SIGNATURE     (BIT(SIGRD)|BIT(SPMEN))


  42. #ifndef FLASH_PAGE_SIZE
  43.     # error No define FLASH_PAGE_SIZE
  44. #endif



  45. #ifndef SPMCSR
  46.     # define SPMCSR     SPMCR
  47. #endif
  48. #ifndef EEPE
  49.    # define EEPE        EEWE
  50. #endif

  51. /*------------------*
  52. *   动 作 宏 定 义  *
  53. *------------------*/

  54. /********************
  55. *  模块结构体定义区 *
  56. ********************/

  57. /********************
  58. *   函 数 声 明 区  *
  59. ********************/
  60. #if BL_USE_PAGE_VERIFY == ENABLE
  61. BOOL Bootloader_Flash_Page_Verify
  62.         (
  63.             BYTE *pchDataBuffer,
  64.             #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  65.             UINT32 dwAddress
  66.             #else
  67.             UINT16 wAddress
  68.             #endif
  69.         );
  70. #endif
  71. #if BL_USE_LOAD_PAGE == ENABLE
  72. #if defined(BOOTLOADER_USE_CRC16)
  73. UINT16 Bootloader_Load_Page_Buffer
  74. #elif defined(BOOTLOADER_USE_XOR)
  75. UINT8 Bootloader_Load_Page_Buffer
  76. #else
  77. void Bootloader_Load_Page_Buffer
  78. #endif
  79.         (
  80.             BYTE chDataBuffer[FLASH_PAGE_SIZE],
  81.             #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  82.             UINT32 dwAddress
  83.             #else
  84.             UINT16 wAddress
  85.             #endif
  86.         );
  87. #endif   
  88. BOOL Bootloader_Write_Page
  89.             (
  90.                 void *pData,
  91.                 UINT16 wLength,
  92.                 #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  93.                 UINT32 dwAddress
  94.                 #else
  95.                 UINT16 wAddress
  96.                 #endif
  97.             );
  98. void Bootloader_Put_INT_Vector_Into_APPS(void);
  99. void Bootloader_Put_INT_Vector_Into_BLS(void);

  100. #if BL_USE_READ_FUSE_AND_LOCK_BITS == ENABLE
  101. UINT8 Bootloader_Read_Fuse(UINT16 wIndex);
  102. #endif
  103. #if BL_USE_READ_FUSE_AND_LOCK_BITS == ENABLE
  104. UINT8 Bootloader_Read_Signature(UINT16 wIndex);
  105. #endif
  106. #if BL_USE_WRITE_LOCK_BITS == ENABLE
  107. void Bootloader_Write_Lock_Bits(UINT8 chLockBits);
  108. #endif
  109. #if defined(BOOTLOADER_USE_CRC16) || (BL_CRC16_SERVICE_SUPPORT == ENABLE)
  110. UINT16 CRC16_Check(UINT16 *pwCRCValue,BYTE chData);
  111. #endif
  112. #if BL_USE_CHIP_ERASE == ENABLE
  113. #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  114. void Bootloader_Chip_Erase(UINT32 dwMaxAddress);
  115. #else
  116. void Bootloader_Chip_Erase(UINT16 wMaxAddress);
  117. #endif
  118. #endif
  119. /********************
  120. *   模块函数声明区  *
  121. ********************/
  122. static void Do_Boot_Loader_Action(UINT8 chFunction);

  123. static BOOL Fill_Page_Buffer
  124.             (
  125.                 BYTE chDataBuffer[FLASH_PAGE_SIZE],
  126.                 #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  127.                 UINT32 dwAddress
  128.                 #else
  129.                 UINT16 wAddress
  130.                 #endif
  131.             );
  132.      
  133. /********************
  134. *   模块变量声明区  *
  135. ********************/

  136. /********************
  137. *   全局变量声明区  *
  138. ********************/

  139. #if defined(BOOTLOADER_USE_CRC16) || (BL_CRC16_SERVICE_SUPPORT == ENABLE)
  140. /***********************************************************
  141. *   函数说明:  CRC16单数据处理函数                        *
  142. *   输入:      保存CRC校验值的地址,新的数据              *
  143. *   输出:      CRC交验                                    *
  144. *   调用函数:  无                                         *
  145. ***********************************************************/
  146. UINT16 CRC16_Check(UINT16 *pwCRCValue,BYTE chData)
  147. {
  148.     UINT16 wCRC = (*pwCRCValue);
  149.    
  150.     chData ^= (UINT8)((UINT16)wCRC & 0x00FF);
  151.     chData ^= chData << 4;
  152.     (*pwCRCValue) = ((((uint16)chData << 8) | (wCRC >> 8)) ^ (uint8)(chData >> 4)  
  153.                  ^ ((uint16)chData << 3));
  154.                  
  155.     return (*pwCRCValue);
  156. }
  157. #endif


  158. /***********************************************************
  159. *   函数说明:  等待SPM指令执行结束函数                    *
  160. *   输入:      需要执行的功能                             *
  161. *   输出:      无                                         *
  162. *   调用函数:  无                                         *
  163. ***********************************************************/
  164. static void Do_Boot_Loader_Action(UINT8 chFunction)
  165. {
  166.     /* 等待上次操作结束 */
  167.     while(SPMCSR & BIT(SPMEN))
  168.     {
  169.         asm("wdr");
  170.     }
  171.    
  172.     SAFE_CODE_PERFORMANCE
  173.     (
  174.         while(EECR & BIT(EEWE))
  175.         {
  176.             asm("wdr");
  177.         }
  178.         SPMCSR = chFunction;
  179.         asm("spm");
  180.     )
  181. }

  182. #if BL_USE_CHIP_ERASE == ENABLE
  183. /***********************************************************
  184. *   函数说明:  片擦除函数                                 *
  185. *   输入:      擦除时不能越过的地址                       *
  186. *   输出:      无                                         *
  187. *   调用函数:  Do_Boot_Loader_Action                      *
  188. ***********************************************************/
  189. #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  190. void Bootloader_Chip_Erase(UINT32 dwMaxAddress)
  191. #else
  192. void Bootloader_Chip_Erase(UINT16 wMaxAddress)
  193. #endif
  194. {
  195.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  196.     UINT32 dwAddress;
  197.     UINT8 TRAMPZ = RAMPZ;
  198.     for (
  199.             dwAddress = 0;
  200.             dwAddress < dwMaxAddress;
  201.             dwAddress += FLASH_PAGE_SIZE
  202.         )
  203.     {
  204.         UINT16 wAddress = dwAddress;
  205.         RAMPZ = dwAddress>>16;
  206.         asm("movw r30,%wAddress");        
  207.         Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  208.         Do_Boot_Loader_Action(SPM_ENBALE_RWW);
  209.         WDR();
  210.     }
  211.     RAMPZ = TRAMPZ;
  212.    
  213.     #else
  214.     UINT16 wAddress;   
  215.     for (
  216.             wAddress = 0;
  217.             wAddress < wMaxAddress;
  218.             wAddress += FLASH_PAGE_SIZE
  219.         )
  220.     {
  221.         /* 将地址保存到Z寄存器 */
  222.         asm("movw r30,%wAddress");
  223.         WDR();
  224.         Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  225.         Do_Boot_Loader_Action(SPM_ENBALE_RWW);
  226.     }
  227.     #endif
  228. }
  229. #endif

  230. #if BL_USE_LOAD_PAGE == ENABLE
  231. /*-----------------------------------------------------------------------------*
  232. *  Function Description:                                                      *
  233. *      Load a specified page to a page buffer.                                *
  234. *  Parameters:                                                                *
  235. *      chDataBuffer        the page buffer.                                   *
  236. *      dwAddress/wAddress  the target page address.                           *
  237. *  Return                                                                     *
  238. *      CRC16 / XOR / None                                                     *
  239. *----------------------------------------------------------------------------*/
  240. #if defined(BOOTLOADER_USE_CRC16)
  241. UINT16 Bootloader_Load_Page_Buffer
  242. #elif defined(BOOTLOADER_USE_XOR)
  243. UINT8 Bootloader_Load_Page_Buffer
  244. #else
  245. void Bootloader_Load_Page_Buffer
  246. #endif
  247.         (
  248.             UINT8 chDataBuffer[FLASH_PAGE_SIZE],
  249.             #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  250.             UINT32 dwAddress
  251.             #else
  252.             UINT16 wAddress
  253.             #endif
  254.         )
  255. {
  256.     UINT16 wCounter = FLASH_PAGE_SIZE;
  257.     #if defined(BOOTLOADER_USE_CRC16)
  258.     UINT16 wTempCRC = CRC_INIT;
  259.     UINT8 chData;
  260.     #elif defined(BOOTLOADER_USE_XOR)
  261.     UINT8 chXOR = 0;
  262.     #endif
  263.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  264.     UINT8 TRAMPZ = RAMPZ;
  265.     #endif
  266.    
  267.     #if !defined(BOOTLOADER_USE_CRC16) && !defined(BOOTLOADER_USE_XOR)
  268.     if (chDataBuffer == NULL)
  269.     {
  270.         //! in none checking model, a null buffer means nothing.
  271.         return ;
  272.     }
  273.     #endif
  274.    
  275.     //! Enable RWW write
  276.     while(SPMCSR & BIT(RWWSB))
  277.     {
  278.         Do_Boot_Loader_Action(SPM_ENBALE_RWW);
  279.     }
  280.     asm("push r30");
  281.     asm("push r31");
  282.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  283.     RAMPZ = dwAddress >> 16;
  284.     #endif
  285.     //! load address to z register
  286.     asm("movw r30,r18");
  287.     //! load buffer address to x register
  288.     asm("movw r26,r16");
  289. #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  290.    
  291.     if (chDataBuffer != NULL)
  292.     {
  293.         #ifdef BOOTLOADER_USE_XOR
  294.         //! Initialize the xor checking result register
  295.         asm("ldi r1,0");
  296.         #endif
  297.         if (RAMPZ)
  298.         {
  299.             while(wCounter--)
  300.             {
  301.                 WDR();
  302.                 //! load value from flash (addressed by z register)
  303.                 asm("elpm r0,z+");
  304.                 //! save the value to sram (address by x register)
  305.                 asm("st x+,r0");
  306.                 //! do checking function if necessary
  307.                 #if defined(BOOTLOADER_USE_CRC16)
  308.                 //! use chData as a temporary variable
  309.                 asm("mov %chData,r0");
  310.                 //! calculate the crc16 value
  311.                 CRC(wTempCRC,chData);
  312.                 #elif defined (BOOTLOADER_USE_XOR)
  313.                 //! xor
  314.                 asm("eor r1,r0");
  315.                 #endif
  316.             }
  317.         }
  318.         else
  319.         {
  320.             while(wCounter--)
  321.             {
  322.                 WDR();
  323.                 //! load value from flash (addressed by z register)
  324.                 asm("lpm r0,z+");
  325.                 //! save the value to sram (address by x register)
  326.                 asm("st x+,r0");
  327.                 //! do checking function if necessary
  328.                 #if defined(BOOTLOADER_USE_CRC16)
  329.                 //! use chData as a temporary variable
  330.                 asm("mov %chData,r0");
  331.                 //! calculate the crc16 value
  332.                 CRC(wTempCRC,chData);
  333.                 #elif defined (BOOTLOADER_USE_XOR)
  334.                 //! xor
  335.                 asm("eor r1,r0");
  336.                 #endif
  337.             }
  338.         }
  339.         #ifdef BOOTLOADER_USE_XOR
  340.         //! save the xor checking result to variable chXOR
  341.         asm("mov %chXOR,r1");
  342.         #endif
  343.     }
  344.     else
  345.     {
  346.         //! do checking function if necessary
  347.         #if defined(BOOTLOADER_USE_CRC16)
  348.         if (RAMPZ)
  349.         {
  350.             while(wCounter--)
  351.             {
  352.                 WDR();
  353.                 //! load value from flash (addressed by z register)
  354.                 asm("elpm r0,z+");
  355.                 //! use chData as a temporary variable
  356.                 asm("mov %chData,r0");
  357.                 //! calculate the crc16 value
  358.                 CRC(wTempCRC,chData);
  359.             }
  360.         }
  361.         else
  362.         {
  363.             while(wCounter--)
  364.             {
  365.                 WDR();
  366.                 //! load value from flash (addressed by z register)
  367.                 asm("lpm r0,z+");
  368.                 //! use chData as a temporary variable
  369.                 asm("mov %chData,r0");
  370.                 //! calculate the crc16 value
  371.                 CRC(wTempCRC,chData);
  372.             }
  373.         }
  374.         #elif defined (BOOTLOADER_USE_XOR)
  375.         //! Initialize the xor checking result register
  376.         if (RAMPZ)
  377.         {
  378.             asm("ldi r1,0");
  379.             while(wCounter--)
  380.             {
  381.                 WDR();
  382.                 //! load a byte from flash to r0 (addressed by z register)
  383.                 asm("elpm r0,z+");
  384.                 //! xor
  385.                 asm("eor r1,r0");
  386.             }
  387.             //! save the xor checking result to variable chXOR
  388.             asm("mov %chXOR,r1");
  389.         }
  390.         else
  391.         {
  392.             asm("ldi r1,0");
  393.             while(wCounter--)
  394.             {
  395.                 WDR();
  396.                 //! load a byte from flash to r0 (addressed by z register)
  397.                 asm("lpm r0,z+");
  398.                 //! xor
  399.                 asm("eor r1,r0");
  400.             }
  401.             //! save the xor checking result to variable chXOR
  402.             asm("mov %chXOR,r1");
  403.         }
  404.         #endif
  405.     }
  406.     RAMPZ = TRAMPZ;
  407.    
  408. #else
  409.     if (chDataBuffer != NULL)
  410.     {
  411.         #ifdef BOOTLOADER_USE_XOR
  412.         //! Initialize the xor checking result register
  413.         asm("ldi r1,0");
  414.         #endif
  415.         while(wCounter--)
  416.         {
  417.             WDR();
  418.             //! load value from flash (addressed by z register)
  419.             asm("lpm r0,z+");
  420.             //! save the value to sram (address by x register)
  421.             asm("st x+,r0");
  422.             //! do checking function if necessary
  423.             #if defined(BOOTLOADER_USE_CRC16)
  424.             //! use chData as a temporary variable
  425.             asm("mov %chData,r0");
  426.             //! calculate the crc16 value
  427.             CRC(wTempCRC,chData);
  428.             #elif defined (BOOTLOADER_USE_XOR)
  429.             //! xor
  430.             asm("eor r1,r0");
  431.             #endif
  432.         }
  433.         #ifdef BOOTLOADER_USE_XOR
  434.         //! save the xor checking result to variable chXOR
  435.         asm("mov %chXOR,r1");
  436.         #endif
  437.     }
  438.     else
  439.     {
  440.         //! do checking function if necessary
  441.         #if defined(BOOTLOADER_USE_CRC16)
  442.         while(wCounter--)
  443.         {
  444.             WDR();
  445.             //! load value from flash (addressed by z register)
  446.             asm("lpm r0,z+");
  447.             //! use chData as a temporary variable
  448.             asm("mov %chData,r0");
  449.             //! calculate the crc16 value
  450.             CRC(wTempCRC,chData);
  451.         }
  452.         #elif defined (BOOTLOADER_USE_XOR)
  453.         //! Initialize the xor checking result register
  454.         asm("ldi r1,0");
  455.         while(wCounter--)
  456.         {
  457.             WDR();
  458.             //! load a byte from flash to r0 (addressed by z register)
  459.             asm("lpm r0,z+");
  460.             //! xor
  461.             asm("eor r1,r0");
  462.         }
  463.         //! save the xor checking result to variable chXOR
  464.         asm("mov %chXOR,r1");
  465.         #endif
  466.     }
  467. #endif
  468.     asm("pop r31");
  469.     asm("pop r30");
  470.    
  471.     #if defined(BOOTLOADER_USE_CRC16)
  472.     return wTempCRC;
  473.     #elif defined(OOTLOADER_USE_XOR)
  474.     return chXOR;
  475.     #endif
  476. }
  477. #endif


  478. //#pragma abs_address: BL_VECTOR_FREE_TEXT_ADDRESS

  479. /***********************************************************
  480. *   函数说明:  向页缓冲区写入数据函数                     *
  481. *   输入:      缓冲区指针,要写入的地址                   *
  482. *   输出:      写入是否成功                               *
  483. *   调用函数:  无                                         *
  484. ***********************************************************/
  485. static BOOL Fill_Page_Buffer
  486.             (
  487.                 BYTE chDataBuffer[FLASH_PAGE_SIZE],
  488.                 #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  489.                 UINT32 dwAddress
  490.                 #else
  491.                 UINT16 wAddress
  492.                 #endif
  493.             )
  494. {
  495.     UINT8 chCounter = (FLASH_PAGE_SIZE>>1);
  496.    
  497.     if (chDataBuffer == NULL)
  498.     {
  499.         return FALSE;
  500.     }
  501.    
  502.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  503.     dwAddress &= ~((UINT32)(FLASH_PAGE_SIZE - 1));
  504.     #else
  505.     wAddress &= ~((UINT16)(FLASH_PAGE_SIZE - 1));
  506.     #endif
  507.     //! load zero value to z register
  508.     asm("ldi r30,0");
  509.     //! load the page buffer address to x register
  510.     asm("movw r26,r16");
  511.     while(chCounter--)
  512.     {
  513.         WDR();
  514.         //! load half word(2bytes) from sram to R0 register (addressed by x register)
  515.         asm("ld r0,x+");
  516.         asm("ld r1,x+");
  517.         //! save the half word to flash page buffer
  518.         Do_Boot_Loader_Action(SPM_WRITE_BUFFER);
  519.         //! increase the flash page buffer writing pointer.
  520.         asm("adiw r30,2");
  521.     }
  522.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  523.     RAMPZ = dwAddress >> 16;
  524.     #endif
  525.     //! save a address to z register
  526.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  527.     {
  528.         UINT8 A = ((UINT8 *)&dwAddress)[0];
  529.         UINT8 B = ((UINT8 *)&dwAddress)[1];
  530.         asm("mov r30,%A");
  531.         asm("mov r31,%B");
  532.     }
  533.     #else
  534.     asm("movw r30,r18");
  535.     #endif

  536.     return TRUE;
  537. }
  538. //#pragma end_abs_address

  539. #if BL_USE_PAGE_VERIFY == ENABLE
  540. /***********************************************************
  541. *   函数说明:  页面校验函数                               *
  542. *   输入:      源页面缓冲区,目标地址                     *
  543. *   输出:      校验是否成功                               *
  544. *   调用函数:  无                                         *
  545. ***********************************************************/
  546. BOOL Bootloader_Flash_Page_Verify
  547.         (
  548.             BYTE *pchDataBuffer,
  549.             #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  550.             UINT32 dwAddress
  551.             #else
  552.             UINT16 wAddress
  553.             #endif
  554.         )
  555. {
  556.     UINT16 wCounter = FLASH_PAGE_SIZE;
  557.     UINT8 chDataA;
  558.     UINT8 chDataB;
  559.    
  560.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  561.     UINT8 TRAMPZ = RAMPZ;
  562.     #endif
  563.     if (pchDataBuffer == NULL)
  564.     {
  565.         //! have nothing to do with...
  566.         return FALSE;
  567.     }
  568.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  569.     RAMPZ = dwAddress >> 16;
  570.     #endif
  571.     //! load the address to z register
  572.     asm("movw r30,r18");
  573.     //! load the buffer address to x register
  574.     asm("movw r26,r16");
  575.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  576.     if (RAMPZ)
  577.     {
  578.         while(wCounter--)
  579.         {
  580.             //! load a byte from flash (addressed by z register)
  581.             asm("elpm r0,z+");
  582.             //! employ a temporary variable chDataA
  583.             asm("mov %chDataA,r0");
  584.             //! load a byte from sram (addressed by x register)
  585.             asm("ld r0,x+");
  586.             //! employ a temporary variable chDataB
  587.             asm("mov %chDataB,r0");
  588.             //! checking...
  589.             if (chDataA != chDataB)
  590.             {
  591.                 RAMPZ = TRAMPZ;
  592.                 return FALSE;        
  593.             }
  594.             WDR();
  595.         }
  596.     }
  597.     else
  598.     {
  599.         while(wCounter--)
  600.         {
  601.             //! load a byte from flash (addressed by z register)
  602.             asm("lpm r0,z+");
  603.             //! employ a temporary variable chDataA
  604.             asm("mov %chDataA,r0");
  605.             //! load a byte from sram (addressed by x register)
  606.             asm("ld r0,x+");
  607.             //! employ a temporary variable chDataB
  608.             asm("mov %chDataB,r0");
  609.             //! checking...
  610.             if (chDataA != chDataB)
  611.             {
  612.                 RAMPZ = TRAMPZ;
  613.                 return FALSE;        
  614.             }
  615.             WDR();
  616.         }
  617.     }
  618.     RAMPZ = TRAMPZ;
  619.     #else
  620.     while(wCounter--)
  621.     {
  622.         //! load a byte from flash (addressed by z register)
  623.         asm("lpm r0,z+");
  624.         //! employ a temporary variable chDataA
  625.         asm("mov %chDataA,r0");
  626.         //! load a byte from sram (addressed by x register)
  627.         asm("ld r0,x+");
  628.         //! employ a temporary variable chDataB
  629.         asm("mov %chDataB,r0");
  630.         //! checking...
  631.         if (chDataA != chDataB)
  632.         {
  633.             return FALSE;        
  634.         }
  635.     }
  636.     #endif
  637.     return TRUE;
  638. }
  639. #endif

  640. /***********************************************************
  641. *   函数说明:  写入页面函数                               *
  642. *   输入:      缓冲区地址,目标地址                       *
  643. *   输出:      操作是否成功                               *
  644. *   调用函数:                                             *
  645. ***********************************************************/
  646. BOOL Bootloader_Write_Page
  647.             (
  648.                 void *pData,
  649.                 UINT16 wLength,
  650.                 #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  651.                 UINT32 dwAddress
  652.                 #else
  653.                 UINT16 wAddress
  654.                 #endif
  655.             )
  656. {
  657.     BYTE *pchData = pData;
  658.     BYTE *pchBuffer = NULL;
  659.     #if BL_USE_LOAD_PAGE != ENABLE
  660.     UINT16 wCounter;
  661.     #endif
  662.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  663.     UINT8 TRAMPZ = RAMPZ;
  664.     #endif
  665.     if (pData == NULL)
  666.     {
  667.         return FALSE;
  668.     }
  669.    
  670.     asm("wdr");
  671.    
  672.     #if BL_CANCEL_AUTO_FORMAT_ADDRESS == ENABLE
  673.     //! do not snap the input flash address to page address
  674.     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  675.     if ((dwAddress & (FLASH_PAGE_SIZE - 1)) != 0)
  676.     #else
  677.     if ((wAddress & (FLASH_PAGE_SIZE - 1)) != 0)
  678.     #endif
  679.     {
  680.         UINT8 chBuffer[FLASH_PAGE_SIZE];
  681.         
  682.         //! get to know how many bytes are there before a normal page accessing.
  683.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  684.         UINT8 chTempCounter = FLASH_PAGE_SIZE - (dwAddress & (FLASH_PAGE_SIZE - 1));
  685.         #else
  686.         UINT8 chTempCounter = FLASH_PAGE_SIZE - (wAddress & (FLASH_PAGE_SIZE - 1));
  687.         #endif
  688.         if (wLength < chTempCounter)
  689.         {
  690.             chTempCounter = wLength;
  691.         }
  692.         wLength -= chTempCounter;
  693.         
  694.         #if BL_USE_LOAD_PAGE == ENABLE
  695.         Bootloader_Load_Page_Buffer
  696.             (
  697.                 chBuffer,
  698.                 #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  699.                 dwAddress & (~((UINT32)FLASH_PAGE_SIZE - 1))
  700.                 #else
  701.                 wAddress & (~((UINT16)FLASH_PAGE_SIZE - 1))
  702.                 #endif
  703.             );
  704.         #else
  705.         for (wCounter = 0;wCounter < UBOUND(chBuffer);wCounter++)
  706.         {
  707.             chBuffer[wCounter] = 0xFF;
  708.         }
  709.         #endif
  710.         //! copy the data
  711.         //! need to read the page before writing
  712.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  713.         pchBuffer = chBuffer + (dwAddress & (FLASH_PAGE_SIZE - 1));
  714.         #else
  715.         pchBuffer = chBuffer + (wAddress & (FLASH_PAGE_SIZE - 1));
  716.         #endif
  717.         while(chTempCounter--)
  718.         {
  719.             *pchBuffer = *pchData;
  720.             pchBuffer++;
  721.             pchData++;
  722.         }
  723.         
  724.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  725.         SAFE_CODE_PERFORMANCE
  726.         (
  727.             Fill_Page_Buffer(chBuffer,dwAddress);
  728.             Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  729.             Do_Boot_Loader_Action(SPM_PAGE_WRITE);
  730.             Do_Boot_Loader_Action(SPM_ENBALE_RWW);            
  731.         )
  732.         RAMPZ = TRAMPZ;
  733.         #else
  734.         SAFE_CODE_PERFORMANCE
  735.         (
  736.             Fill_Page_Buffer(chBuffer,wAddress);
  737.             Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  738.             Do_Boot_Loader_Action(SPM_PAGE_WRITE);
  739.             Do_Boot_Loader_Action(SPM_ENBALE_RWW);            
  740.         )
  741.         
  742.         #endif
  743.         
  744.         
  745.         WDR();
  746.         #if BL_USE_PAGE_VERIFY == ENABLE
  747.         //! verify the page
  748.         if (
  749.             !Bootloader_Flash_Page_Verify
  750.                 (
  751.                     chBuffer,
  752.                     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  753.                     dwAddress & (~((UINT32)FLASH_PAGE_SIZE - 1))
  754.                     #else
  755.                     wAddress & (~((UINT16)FLASH_PAGE_SIZE - 1))
  756.                     #endif
  757.                 )
  758.            )
  759.         {
  760.             //! failed in verifying...
  761.             return FALSE;
  762.         }
  763.         #endif
  764.         
  765.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  766.         dwAddress += FLASH_PAGE_SIZE;
  767.         dwAddress &= (~((UINT32)FLASH_PAGE_SIZE - 1));        
  768.         #else
  769.         wAddress += FLASH_PAGE_SIZE;
  770.         wAddress &= (~((UINT16)FLASH_PAGE_SIZE - 1));
  771.         #endif
  772.         
  773.     }
  774.     #endif

  775.     //! normal page writing access
  776.     while(wLength > FLASH_PAGE_SIZE)
  777.     {
  778.         //! do a page write sequence...
  779.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  780.         SAFE_CODE_PERFORMANCE
  781.         (
  782.             Fill_Page_Buffer(pchData,dwAddress);
  783.             Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  784.             Do_Boot_Loader_Action(SPM_PAGE_WRITE);
  785.             Do_Boot_Loader_Action(SPM_ENBALE_RWW);            
  786.         )
  787.         RAMPZ = TRAMPZ;
  788.         #else
  789.         SAFE_CODE_PERFORMANCE
  790.         (
  791.             Fill_Page_Buffer(pchData,wAddress);
  792.             Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  793.             Do_Boot_Loader_Action(SPM_PAGE_WRITE);
  794.             Do_Boot_Loader_Action(SPM_ENBALE_RWW);            
  795.         )
  796.         #endif
  797.         
  798.         #if BL_USE_PAGE_VERIFY == ENABLE
  799.         //! verify the page
  800.         if (
  801.             !Bootloader_Flash_Page_Verify
  802.                 (
  803.                     pchData,
  804.                     #if BL_CANCEL_AUTO_FORMAT_ADDRESS == ENABLE
  805.                     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  806.                     dwAddress
  807.                     #else
  808.                     wAddress
  809.                     #endif
  810.                     #else
  811.                     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  812.                     dwAddress & (~((uint32_t)FLASH_PAGE_SIZE - 1))
  813.                     #else
  814.                     wAddress & (~((uint16_t)FLASH_PAGE_SIZE - 1))
  815.                     #endif
  816.                     #endif
  817.                 )
  818.            )
  819.         {
  820.             //! failed in verifying
  821.             return FALSE;
  822.         }
  823.         #endif
  824.         pchData += FLASH_PAGE_SIZE;
  825.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  826.         dwAddress += FLASH_PAGE_SIZE;
  827.         #else
  828.         wAddress += FLASH_PAGE_SIZE;
  829.         #endif
  830.         wLength -= FLASH_PAGE_SIZE;
  831.     }
  832.    
  833.     if (wLength)
  834.     {
  835.         #if BL_USE_LOAD_PAGE == ENABLE
  836.         UINT8 chBuffer[FLASH_PAGE_SIZE];
  837.         #else
  838.         UINT8 chBuffer[FLASH_PAGE_SIZE];
  839.         #endif
  840.         if (wLength < FLASH_PAGE_SIZE)
  841.         {
  842.             //! need to read the page before writing
  843.             pchBuffer = chBuffer;
  844.         
  845.             #if BL_USE_LOAD_PAGE == ENABLE
  846.             Bootloader_Load_Page_Buffer
  847.                 (
  848.                     chBuffer,
  849.                     #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  850.                     dwAddress
  851.                     #else
  852.                     wAddress
  853.                     #endif
  854.                 );
  855.             #else
  856.             for (wCounter = 0;wCounter < UBOUND(chBuffer);wCounter++)
  857.             {
  858.                 chBuffer[wCounter] = 0xFF;
  859.             }
  860.             #endif
  861.         
  862.             //! copy the data
  863.             while(wLength--)
  864.             {
  865.                 *pchBuffer = *pchData;
  866.                 pchBuffer++;
  867.                 pchData++;
  868.             }
  869.             pchBuffer = chBuffer;
  870.         }
  871.         else
  872.         {
  873.             pchBuffer = pchData;
  874.         }
  875.    
  876.         //! bootloader sequence
  877.         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  878.         SAFE_CODE_PERFORMANCE
  879.         (
  880.             Fill_Page_Buffer(pchBuffer,dwAddress);
  881.             Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  882.             Do_Boot_Loader_Action(SPM_PAGE_WRITE);
  883.             Do_Boot_Loader_Action(SPM_ENBALE_RWW);            
  884.         )
  885.         RAMPZ = TRAMPZ;
  886.         #else
  887.         SAFE_CODE_PERFORMANCE
  888.         (
  889.             Fill_Page_Buffer(pchBuffer,wAddress);
  890.             Do_Boot_Loader_Action(SPM_PAGE_ERASE);
  891.             Do_Boot_Loader_Action(SPM_PAGE_WRITE);
  892.             Do_Boot_Loader_Action(SPM_ENBALE_RWW);            
  893.         )
  894.         #endif
  895.         #if BL_USE_PAGE_VERIFY == ENABLE
  896.         //! verify the page
  897.         if (
  898.             !Bootloader_Flash_Page_Verify
  899.                 (
  900.                         pchBuffer,
  901.                         #if BL_CANCEL_AUTO_FORMAT_ADDRESS == ENABLE
  902.                         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  903.                         dwAddress
  904.                         #else
  905.                         wAddress
  906.                         #endif
  907.                         #else
  908.                         #if BL_USE_EXTEND_ADDRESS_SPACE == ENABLE
  909.                         dwAddress & (~((uint32_t)FLASH_PAGE_SIZE - 1))
  910.                         #else
  911.                         wAddress & (~((uint16_t)FLASH_PAGE_SIZE - 1))
  912.                         #endif
  913.                         #endif
  914.                 )
  915.         )
  916.         {
  917.             //! failed in verifying
  918.             return FALSE;
  919.         }
  920.         #endif
  921.     }


  922.     return TRUE;
  923. }


  924. /***********************************************************
  925. *   函数说明:  将中断向量表放置到Bootloader Section       *
  926. *   输入:      无                                         *
  927. *   输出:      无                                         *
  928. *   调用函数:  无                                         *
  929. ***********************************************************/
  930. void Bootloader_Put_INT_Vector_Into_BLS(void)
  931. {
  932. #if defined(ATMega32) || defined(ATMega16)
  933.     GICR |= BIT(IVCE);
  934.     GICR = (GICR & (~BIT(IVCE))) | BIT(IVSEL);
  935. #else
  936.     MCUCR |= BIT(IVCE);
  937.     MCUCR = (MCUCR & (~BIT(IVCE))) | BIT(IVSEL);  
  938. #endif
  939. }

  940. /***********************************************************
  941. *   函数说明:  将中断向量表放置到Application Section      *
  942. *   输入:      无                                         *
  943. *   输出:      无                                         *
  944. *   调用函数:  无                                         *
  945. ***********************************************************/
  946. void Bootloader_Put_INT_Vector_Into_APPS(void)
  947. {
  948. #if defined(ATMega32) || defined(ATMega16)
  949.     GICR |= BIT(IVCE);
  950.     GICR = GICR & (~(BIT(IVCE) | BIT(IVSEL)));
  951. #else
  952.     MCUCR |= BIT(IVCE);
  953.     MCUCR = MCUCR & (~(BIT(IVCE) | BIT(IVSEL)));
  954. #endif
  955. }

  956. #if BL_USE_WRITE_LOCK_BITS == ENABLE
  957. /***********************************************************
  958. *   函数说明:  写Lockbits指令                             *
  959. *   输入:      要写入Lockbits的内容                       *
  960. *   输出:      无                                         *
  961. *   调用函数:  Do_Boot_Loader_Action()                    *
  962. ***********************************************************/
  963. void Bootloader_Write_Lock_Bits(UINT8 chLockBits)
  964. {
  965.     // 读取LockBits到r0
  966.     asm("mov r0,r16");
  967.     //向Z指针写入0x0001,以保持兼容性
  968.     asm("ldi r30,0x01");
  969.     asm("ldi r31,0x00");
  970.    
  971.     Do_Boot_Loader_Action(SPM_FUSE_AND_LOCK_BITS);
  972. }
  973. #endif

  974. #if BL_USE_READ_SIGNATURE == ENABLE
  975. /***********************************************************
  976. *   函数说明:  读取芯片Signature                          *
  977. *   输入:      Signature地址                              *
  978. *   输出:      读取到的字节                               *
  979. *   调用函数:  无                                         *
  980. ***********************************************************/
  981. UINT8 Bootloader_Read_Signature(UINT16 wIndex)
  982. {
  983.     UINT8 chData;
  984.    
  985.     //将地址保存到Z指针
  986.     asm("movw r30,r16");
  987.    
  988.     /* 等待上次操作结束 */
  989.     while(SPMCSR & BIT(SPMEN))
  990.     {
  991.         asm("wdr");
  992.     }
  993.    
  994.     SAFE_CODE_PERFORMANCE
  995.     (
  996.         while(EECR & BIT(EEWE))
  997.         {
  998.             asm("wdr");
  999.         }
  1000.         SPMCSR = SPM_READ_SIGNATURE;
  1001.         asm("lpm %chData,z");
  1002.     )
  1003.    
  1004.     return chData;
  1005. }
  1006. #endif

  1007. #if BL_USE_READ_FUSE_AND_LOCK_BITS == ENABLE
  1008. /***********************************************************
  1009. *   函数说明:  Fuse和Lock Bits读取函数                    *
  1010. *   输入:      Fuse和Lock Bits的地址                      *
  1011. *   输出:      读取到的字节                               *
  1012. *   调用函数:  无                                         *
  1013. ***********************************************************/
  1014. UINT8 Bootloader_Read_Fuse(UINT16 wIndex)
  1015. {
  1016.     UINT8 chData;
  1017.    
  1018.     //将地址保存到Z指针
  1019.     asm("movw r30,r16");
  1020.    
  1021.     /* 等待上次操作结束 */
  1022.     while(SPMCSR & BIT(SPMEN))
  1023.     {
  1024.         asm("wdr");
  1025.     }
  1026.    
  1027.     SAFE_CODE_PERFORMANCE
  1028.     (
  1029.         while(EECR & BIT(EEWE))
  1030.         {
  1031.             asm("wdr");
  1032.         }
  1033.         SPMCSR = SPM_FUSE_AND_LOCK_BITS;
  1034.         asm("lpm %chData,z");
  1035.     )
  1036.    
  1037.     return chData;
  1038. }
  1039. #endif


复制代码

出0入0汤圆

发表于 2014-12-26 23:14:44 | 显示全部楼层

万分感谢!

出0入0汤圆

发表于 2014-12-28 08:58:45 | 显示全部楼层
好东西

出0入0汤圆

发表于 2015-3-2 11:32:45 | 显示全部楼层
楼主,这个序列号是唯一的吗?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-7 09:07

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表