9279|15

26

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

求助avr单片机bootloader [复制链接]

5芯积分
网上的通用xmega的bootloader移植出来的,但是发送XModem并不能完成升级。求指教!
  1. #include "usart.h"
  2. #include "bootcfg.h"
  3. #include "sp_driver.h"
  4. #include "XMODEM.h"
  5. #include "LED.h"
  6. #include "timer.h"
  7. #include "clksys_driver.h"


  8. #define Test_The_Uart  1 //如果这个标志为1那么程序只发送字符,用于测试串口 正常设置为0
  9. /*
  10. Xmega Bootloaber 移植AVRUBD
  11. 上位机,AVRUDB
  12. 系统时钟:内部RC32MHZ,波特率38400 (32M 时钟时,波特率误差较小)
  13. */
  14. //使用UARTD0  定义下载串口
  15. #define USART      USARTD0
  16. #define USART_PORT PORTD
  17. #define USART_TX   PIN3_bm
  18. #define USART_RX   PIN2_bm

  19. // SPM_PAGESIZE/PROG_START 已经在avr/io.h里面定义了

  20. #define BUFSIZE  SPM_PAGESIZE
  21. //用户程序起始地
  22. #define PROG_START  PROGMEM_START

  23. //串口打印字符
  24. #define borad_massage "Xmega Bootload Programer Is Runing..."
  25. #define MCU_massage   "Replant by chiplab7.com(lisn3188@163.com)"

  26. //----------------------------------------------------------------------------
  27. //接收缓冲区
  28. unsigned char buf[BUFSIZE];
  29. unsigned char ReadBuffer[BUFSIZE];
  30. unsigned int bufptr, pagptr;
  31. unsigned char ch, cl;
  32. //当前Flash地址指针
  33. unsigned long int FlashAddr;
  34. //----------------------------------------------------------------------------
  35. void putstr(const char *str);
  36. void repay_sysclk();
  37. void Timer_initial(void);
  38. void Timer_Stop(void);
  39. //----------------------------------------------------------------------------
  40. //更新一个Flash页
  41. void write_one_page(unsigned char *buf)
  42. {
  43.     //数据填入Flash缓冲页
  44.         /* Load the flashbuffer with the test buffer. */
  45.         SP_LoadFlashPage(buf);
  46.                 /* Perform page erase. *///将缓冲页数据写入一个Flash页
  47.         SP_EraseWriteApplicationPage(FlashAddr);
  48.         /* Wait for NVM to finish. */
  49.         SP_WaitForSPM();//等待页编程完成                     
  50. }
  51. //----------------------------------------------------------------------------
  52. //跳转到用户程序
  53. void quit()
  54. {
  55.   //SP_LockSPM();                            //locks the SPM instruction 如果这个开启,那么一但执行,bootloader只能等待下一个复位才能对flash写
  56.   putstr(msg7);                             //提示进入Application
  57.   repay_sysclk();                            //把系统时钟返回为内部2M RC (XMEGA 复位后系统运行在内部2M RC )
  58.   (*((void(*)(void))PROG_START))();            //跳转,这样比'jmp 0'节省空间
  59. }
  60. //----------------------------------------------------------------------------
  61. //串口初始化38400,8,N,1,@32M CPU时钟
  62. void USART_initial(void)
  63. {
  64.         /* (TXD) as output. */
  65.         USART_PORT.DIRSET = USART_TX;
  66.         /* (RXD) as input. */
  67.         USART_PORT.DIRCLR = USART_RX;
  68.         /* USART, 8 Data bits, No Parity, 1 Stop bit. */
  69.         USART_Format_Set(&USART, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, 0);
  70.         /* Set Baudrate to 38400 bps:
  71.          * Use the default I/O clock fequency that is 32 MHz.
  72.          * Do not use the baudrate scale factor
  73.          * Baudrate select = (1/(16*(((I/O clock frequency)/Baudrate)-1)
  74.          *                 = 25
  75.          */
  76.         USART_Baudrate_Set(&USART, 25 , 0);  //38400
  77.         /* Enable both RX and TX. */
  78.         USART_Rx_Enable(&USART);
  79.         USART_Tx_Enable(&USART);
  80. }
  81. //----------------------------------------------------------------------------
  82. //写入数据到串口
  83. void WriteCom(unsigned char data)
  84. {
  85.                  do{
  86.                 /* Wait until it is possible to put data into TX data register.
  87.                  * NOTE: If TXDataRegister never becomes empty this will be a DEADLOCK. */
  88.                 }while(!USART_IsTXDataRegisterEmpty(&USART));
  89.                 USART_PutChar(&USART, data);
  90. }
  91. //----------------------------------------------------------------------------
  92. //发送字符串并添加回车
  93. void putstr(const char *str)
  94. {
  95.   while(*str)
  96.     WriteCom(*str++);

  97.   WriteCom(0x0D);
  98.   WriteCom(0x0A);  //发送回车
  99. }
  100. //----------------------------------------------------------------------------
  101. //等待串口数据
  102. unsigned char WaitCom(void)
  103. {
  104.   do{
  105.   /* Wait until data received */
  106.   }while(!USART_IsRXComplete(&USART));
  107.   return(USART_GetChar(&USART));
  108. }
  109. //----------------------------------------------------------------------------
  110. //计算CRC校验:1021
  111. void crc16(uint8_t *ptr, int count)
  112. {
  113.         int crc = 0;
  114.         char i;
  115.         
  116.         while (--count >= 0)
  117.         {
  118.                 crc = crc ^ (int) *ptr++ << 8;
  119.                 i = 8;
  120.                 do
  121.                 {
  122.                         if (crc & 0x8000)
  123.                         crc = crc << 1 ^ 0x1021;
  124.                         else
  125.                         crc = crc << 1;
  126.                 } while(--i);
  127.         }
  128.         //return (crc);
  129.         ch = crc / 256;
  130.         cl = crc % 256;       //已定义全局变量
  131. }
  132. //设置系统时钟 为内部RC 32M
  133. //----------------------------------------------------------------------------
  134. void sysclk_initial()
  135. {
  136.                 /*  Enable internal 32 MHz ring oscillator and wait until it's
  137.                  *  stable. Divide clock by two with the prescaler C and set the
  138.                  *  32 MHz ring oscillator as the main clock source.
  139.                  */
  140.                 CLKSYS_Enable( OSC_RC32MEN_bm );
  141.                 CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_2_gc );  //Pc为2分频,T0工作在16M
  142.                 do {} while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 );
  143.                 CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc );
  144. }
  145. //设置系统时钟 为内部RC 2M
  146. //----------------------------------------------------------------------------
  147. void repay_sysclk()
  148. {
  149.                 /*  Select 2 MHz RC oscillator as main clock source and diable
  150.                  *  unused clock.
  151.                  */
  152.                 do {} while ( CLKSYS_IsReady( OSC_RC2MRDY_bm ) == 0 );
  153.                 CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );  
  154.                 CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC2M_gc );
  155.                 CLKSYS_Disable( OSC_PLLEN_bm );  //关掉PLL
  156. }
  157. //主程序
  158. //----------------------------------------------------------------------------
  159. int main(void)
  160. {
  161. unsigned char cnt,get_char,signal=0;
  162. unsigned char packNO;
  163. unsigned char crch, crcl;
  164. unsigned int i;

  165. sysclk_initial();   //设定系统时钟

  166. #if LED_En
  167. LED_initial();LED1_ON();
  168. #endif

  169. USART_initial();

  170. putstr((void*)borad_massage); //向串口打印字符
  171. putstr((void*)MCU_massage);

  172. #if Test_The_Uart  //如果置位,则是测试串口 发什么,回什么

  173. while(1){ //hold 用户可以通过串口助手等工具发送数据,看串口是否正常工作 38400 n,8,1
  174. get_char=WaitCom(); //接收数据
  175. WriteCom(get_char); //回送数据
  176. }
  177. #else  //不是测试串口,则编译bootloader
  178.   Timer_initial(); //初始化时间 200MS
  179. //---------------------------------------------
  180. //提示等待密码
  181.   putstr(msg1);
  182.   cnt = TimeOutCnt;
  183.   cl = 0;
  184.   while(1)
  185.   {
  186.     if(TC_GetOverflowFlag(&TCC0))    //T1溢出
  187.     {
  188.       TC_ClearOverflowFlag(&TCC0);

  189.       if(cl == CONNECTCNT)      //判断连接密码
  190.         break;                  //密码正确,跳出本次循环
  191. #if LED_En
  192.       LED1_T();                 //LED指示状态 闪动
  193. #endif
  194.       cnt--;
  195.       if(cnt == 0)              //连接超时
  196.       {
  197.         putstr(msg2);           //提示超时
  198.         quit();                 //退出bootloader
  199.       }
  200.     }

  201.     if(USART_IsRXComplete(&USART))             //接收到连接密码
  202.     {
  203.           get_char=USART_GetChar(&USART);
  204.       if( get_char== ConnectKey[cl])           //比较密码
  205.         cl++;
  206.       else
  207.         cl = 0;
  208.     }
  209.   }
  210.   putstr(msg3);                 //提示等待接收文件
  211. //进入等二环节
  212. //密码对上了,准备接收数据
  213. //------------------------------------------------------------------------------
  214. //每个时隙向PC机发送一个控制字符“C”,等待控制字〈soh〉
  215.   cnt = TimeOutCntC;
  216.   signal=0;
  217.   while(signal==0)
  218.   {
  219.     if(TC_GetOverflowFlag(&TCC0))  //T1溢出
  220.     {
  221.       TC_ClearOverflowFlag(&TCC0);
  222.       WriteCom(XMODEM_RWC) ;    //发送 "C"
  223. #if LED_En
  224.       LED1_T();                 //LED指示状态 闪动
  225. #endif
  226.       cnt--;
  227.       if(cnt == 0)              //超时
  228.       {
  229.         putstr(msg2);           //提示超时
  230.         quit();                 //退出 bootloader
  231.       }
  232.     }
  233.     if(USART_IsRXComplete(&USART)) //收到字符
  234.     {
  235.           get_char=USART_GetChar(&USART);
  236.       if(get_char == XMODEM_SOH)  //XMODEM命令开始
  237.         {signal=1;break;}
  238.     }
  239.   }
  240. //已经收到一个起启字符了 开始更新Application
  241. //----------------------------------------------------------------
  242.   Timer_Stop(); //关闭定时器1
  243.   //开始接受数据
  244.   packNO = 0; //包序号
  245.   bufptr = 0;
  246.   cnt = 0;
  247.   FlashAddr = 0;       //初始地址设置为0
  248.   do
  249.   {
  250.     packNO++;          //包数量自增
  251.     ch =  WaitCom();                          //获取包序号
  252.     cl = ~WaitCom();                          //包序号的反码,XMODEM帧格式定义的
  253.     if ((packNO == ch) && (packNO == cl))    //包序号对上了!
  254.     {
  255.       for(i = BUFFERSIZE; i > 0; i--)      //接收完整一帧数据
  256.       {
  257.         buf[bufptr++] = WaitCom();
  258.       }
  259.       crch = WaitCom();                       //获取校验字节
  260.       crcl = WaitCom();
  261.       //crc16(&buf[bufptr - BUFFERSIZE]);       //计算校验
  262.           crc16(&buf[0],128);          //计算校验
  263.       if((crch == ch) && (crcl == cl))
  264.       {                                       //校验成功
  265. #if BootStart
  266.         if(FlashAddr < BootStart)             //避免写入Boot区 bootloader 不能自杀
  267.         {
  268. #endif
  269.                                             //后面的条件编译太多了,看得不太明白
  270. #if BUFFERSIZE <= SPM_PAGESIZE
  271.           if(bufptr >= SPM_PAGESIZE)          //缓冲区满,写入数据;否则继续接收
  272.           {                                   //接收多个帧,写入一页
  273.             write_one_page(buf);              //写入缓冲区内容到Flash中
  274.             FlashAddr += SPM_PAGESIZE;        //修改Flash页地址
  275.             bufptr = 0;
  276.           }
  277. #else
  278.           while(bufptr > 0)                   //接收一帧,写入多个页面
  279.           {
  280.             write_one_page(&buf[BUFSIZE - bufptr]);
  281.             FlashAddr += SPM_PAGESIZE;        //修改Flash页地址
  282.             bufptr -= SPM_PAGESIZE;
  283.           }
  284. #endif

  285. #if BootStart
  286.         }
  287.         else                                  //超过BootStart范围,忽略写操作
  288.         {
  289.           bufptr = 0;                         //重置接收指针
  290.         }
  291. #endif

  292. //读取写入的Flash内容并和缓冲区的内容做比较
  293. #if (ChipCheck > 0) && (BootStart > 0)
  294. #if (BUFFERSIZE < SPM_PAGESIZE)
  295.         if((bufptr == 0) && (FlashAddr < BootStart))
  296. #else
  297.         if(FlashAddr < BootStart)
  298. #endif
  299.         {
  300.           //boot_rww_enable();                  //允许读用户程序
  301.           cl = 1;                             //清除错误标志位
  302.                   SP_ReadFlashPage(ReadBuffer, FlashAddr-BUFSIZE);        //----------------------
  303.           for(pagptr = 0; pagptr < BUFSIZE; pagptr++)
  304.           {
  305.             if(ReadBuffer[pagptr] != buf[pagptr])
  306.             {
  307.               cl = 0;                         //设置错误标志位
  308.               break;
  309.             }
  310.           }
  311.           if(cl)                              //校验正确,发送正常反馈
  312.           {
  313.             WriteCom(XMODEM_ACK);
  314.                         
  315.             cnt = 0;
  316.           }
  317.           else
  318.           {
  319.                     
  320.             WriteCom(XMODEM_NAK);             //校验错误,请求重发
  321.             cnt++;                            //错误计数加1
  322.                         
  323.             FlashAddr -= BUFSIZE;             //修正FlashAddr地址
  324.           }
  325.         }
  326.         else                                  //不校验Boot区,直接发送正确回应
  327.         {
  328.           WriteCom(XMODEM_ACK);
  329.           cnt = 0;
  330.         }
  331. #else
  332.         WriteCom(XMODEM_ACK);                 //不校验,直接发送正确响应
  333.         cnt = 0;
  334. #endif

  335. #if LED_En
  336.        Display_Proess(packNO);                //LED提示正在升级 这里可以通过修改 LED.h 里面的程序达到不同的效果
  337. #endif

  338.       }
  339.       else //CRC
  340.       {
  341.         WriteCom(XMODEM_NAK);                 //要求重发数据
  342.         cnt++;   //出错计数 ++  因为没有通过效验                           
  343.       }
  344.     }
  345.     else //PackNo  包序号对不上!
  346.     {
  347.       WriteCom(XMODEM_NAK);                   //要求重发数据
  348.       cnt++;     //出错计数 ++  因为号的序号对不上
  349.     }

  350.     if(cnt > 3)                               //连续出错次数太多,中止升级
  351.       break;
  352.   }
  353.   while(WaitCom() != XMODEM_EOT);
  354.   WriteCom(XMODEM_ACK);
  355.   
  356. #if LED_En
  357.   Led_off();                             //LED 指示升级完成 LED灭
  358. #endif

  359. #if VERBOSE
  360.   if(cnt == 0)   //没有错误!
  361.   {
  362.     //升级成功
  363.     putstr(msg4);                             //提示升级成功
  364.   }
  365.   else
  366.   {
  367.     //升级失败
  368.     putstr(msg5);                             //提示升级失败

  369. #if (BootStart > 0)
  370.     (*((void(*)(void))(BootStart)))();        //跳转到 bootloader
  371. #endif
  372. #endif
  373.   }
  374.   quit();                                     //退出bootloader
  375.   return 0;

  376. #endif
  377. }

复制代码


yuemin851246724_1441532409578_50.jpg (57.71 KB, 下载次数: 0)

yuemin851246724_1441532409578_50.jpg

yuemin851246724_1441532423855_29.jpg (44.26 KB, 下载次数: 0)

yuemin851246724_1441532423855_29.jpg

最佳答案

查看完整内容

先用Bootloader下载,再用Jtag读出来,保存为bin格式,做一下二进制比较。

最新回复

我和版主使用的同一套代码,修改为xmega64d4的bootloader,我最近几次的仿真结果是: packNO = 1; CH = 0X41(0x41正好是密码的第一个字节) 经过多次仿真,我发现是AVRBUD工具,在发送完密码后,我板子已经解析,板子然后发送"C"字符,AVRUBD工具接收到"C",然后板子等待AVRUBN工具发送XMODEM协议的SOH(就是0x01,XMODEM的开始命令),然而AVRUBD工具还一直在发送密码,始终不发送XMODEM的SOH,不知道为什么  详情 回复 发表于 2018-5-16 17:11
点赞 关注(1)
 

回复
举报

26

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
XMEGA128A1U
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
xmega128a1u
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

4
 
  1. /* ========== Constants ========== */

  2. #define PROGMEM_START     (0x0000)
  3. #define PROGMEM_SIZE      (139264)
  4. #define PROGMEM_END       (PROGMEM_START + PROGMEM_SIZE - 1)

  5. #define APP_SECTION_START     (0x0000)
  6. #define APP_SECTION_SIZE      (131072)
  7. #define APP_SECTION_PAGE_SIZE (512)
  8. #define APP_SECTION_END       (APP_SECTION_START + APP_SECTION_SIZE - 1)

  9. #define APPTABLE_SECTION_START     (0x1E000)
  10. #define APPTABLE_SECTION_SIZE      (8192)
  11. #define APPTABLE_SECTION_PAGE_SIZE (512)
  12. #define APPTABLE_SECTION_END       (APPTABLE_SECTION_START + APPTABLE_SECTION_SIZE - 1)

  13. #define BOOT_SECTION_START     (0x20000)
  14. #define BOOT_SECTION_SIZE      (8192)
  15. #define BOOT_SECTION_PAGE_SIZE (512)
  16. #define BOOT_SECTION_END       (BOOT_SECTION_START + BOOT_SECTION_SIZE - 1)

  17. #define DATAMEM_START     (0x0000)
  18. #define DATAMEM_SIZE      (16777216)
  19. #define DATAMEM_END       (DATAMEM_START + DATAMEM_SIZE - 1)

  20. #define IO_START     (0x0000)
  21. #define IO_SIZE      (4096)
  22. #define IO_PAGE_SIZE (0)
  23. #define IO_END       (IO_START + IO_SIZE - 1)

  24. #define MAPPED_EEPROM_START     (0x1000)
  25. #define MAPPED_EEPROM_SIZE      (2048)
  26. #define MAPPED_EEPROM_PAGE_SIZE (0)
  27. #define MAPPED_EEPROM_END       (MAPPED_EEPROM_START + MAPPED_EEPROM_SIZE - 1)

  28. #define INTERNAL_SRAM_START     (0x2000)
  29. #define INTERNAL_SRAM_SIZE      (8192)
  30. #define INTERNAL_SRAM_PAGE_SIZE (0)
  31. #define INTERNAL_SRAM_END       (INTERNAL_SRAM_START + INTERNAL_SRAM_SIZE - 1)

  32. #define EEPROM_START     (0x0000)
  33. #define EEPROM_SIZE      (2048)
  34. #define EEPROM_PAGE_SIZE (32)
  35. #define EEPROM_END       (EEPROM_START + EEPROM_SIZE - 1)

  36. #define SIGNATURES_START     (0x0000)
  37. #define SIGNATURES_SIZE      (3)
  38. #define SIGNATURES_PAGE_SIZE (0)
  39. #define SIGNATURES_END       (SIGNATURES_START + SIGNATURES_SIZE - 1)

  40. #define FUSES_START     (0x0000)
  41. #define FUSES_SIZE      (6)
  42. #define FUSES_PAGE_SIZE (0)
  43. #define FUSES_END       (FUSES_START + FUSES_SIZE - 1)

  44. #define LOCKBITS_START     (0x0000)
  45. #define LOCKBITS_SIZE      (1)
  46. #define LOCKBITS_PAGE_SIZE (0)
  47. #define LOCKBITS_END       (LOCKBITS_START + LOCKBITS_SIZE - 1)

  48. #define USER_SIGNATURES_START     (0x0000)
  49. #define USER_SIGNATURES_SIZE      (512)
  50. #define USER_SIGNATURES_PAGE_SIZE (512)
  51. #define USER_SIGNATURES_END       (USER_SIGNATURES_START + USER_SIGNATURES_SIZE - 1)

  52. #define PROD_SIGNATURES_START     (0x0000)
  53. #define PROD_SIGNATURES_SIZE      (64)
  54. #define PROD_SIGNATURES_PAGE_SIZE (512)
  55. #define PROD_SIGNATURES_END       (PROD_SIGNATURES_START + PROD_SIGNATURES_SIZE - 1)

  56. #define FLASHSTART   PROGMEM_START
  57. #define FLASHEND     PROGMEM_END
  58. #define SPM_PAGESIZE 512
  59. #define RAMSTART     INTERNAL_SRAM_START
  60. #define RAMSIZE      INTERNAL_SRAM_SIZE
  61. #define RAMEND       INTERNAL_SRAM_END
  62. #define E2END        EEPROM_END
  63. #define E2PAGESIZE   EEPROM_PAGE_SIZE
复制代码
 
 
 

回复

1万

帖子

25

TA的资源

版主

5
 
xmega的bootloader没有研究。看看ATMEL的文档中有没有。
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

6
 
dcexpert 发表于 2015-9-10 10:38
xmega的bootloader没有研究。看看ATMEL的文档中有没有。

斑竹,我想疑问的是 xmodem协议的 “如果最后需要发送的数据不足128个字节,用填满一个数据块。”
1. avr收到的 怎么处理? a)收到仍然把往flash里写 b)把替换为0xff往里写。
2.如果一个flash的page大小是4个块,那如果只收到1个块的话  剩下的怎么处理

点评

AVR的flash是128的倍数,应该不存在不足的情况吧。不足128字节的情况还没有处理过,如果是规定那样,接收到0x1a后丢弃就行了,或者将0x1A转为0xFF,0xFF是无效指令,这样写入Flash才不会出错。 如果数据接收不全  详情 回复 发表于 2015-9-15 11:13
 
 
 

回复

1万

帖子

25

TA的资源

版主

7
 
285844685 发表于 2015-9-15 10:59
斑竹,我想疑问的是 xmodem协议的 “如果最后需要发送的数据不足128个字节,用填满一个数据块。”
1. av ...

AVR的flash是128的倍数,应该不存在不足的情况吧。不足128字节的情况还没有处理过,如果是规定那样,接收到0x1a后丢弃就行了,或者将0x1A转为0xFF,0xFF是无效指令,这样写入Flash才不会出错。

如果数据接收不全,那边升级就会失败,只能重新升级了。

点评

恩比如flash512 只收到一个块只有128 那后面的如何处理? 接收到1a后怎么判断是程序的一个1a 还是后面都是1a了  详情 回复 发表于 2015-9-15 11:21
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

8
 
  1. for(i=0;i<128;i++)
  2.                   {
  3.                           if((XmodemBuffer[i]==XMODEM_EOF)&&(XmodemBuffer[i]==XmodemBuffer[127]))      //如果最后需要发送的数据不足128个字节,用<eof>填满一个数据块。
  4.                              XmodemBuffer[i]=0xff;                                          
  5.                   }
复制代码
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

9
 
dcexpert 发表于 2015-9-15 11:13
AVR的flash是128的倍数,应该不存在不足的情况吧。不足128字节的情况还没有处理过,如果是规定那样,接收 ...

恩比如flash512  只收到一个块只有128   那后面的如何处理?

接收到1a后怎么判断是程序的一个1a  还是后面都是1a了

点评

xmega不太清楚,AVR中是这样,Flash是需要块写入的,但是块的大小与AVR的型号有关,不是每种都一样,从16字节到128直接都有。所以需要等收完一个块后,计算校验后才能写入flash。 正常情况下,是不会出现数据不足  详情 回复 发表于 2015-9-15 11:49
 
 
 

回复

1万

帖子

25

TA的资源

版主

10
 
285844685 发表于 2015-9-15 11:21
恩比如flash512  只收到一个块只有128   那后面的如何处理?

接收到1a后怎么判断是程序的一个1a  还是 ...

xmega不太清楚,AVR中是这样,Flash是需要块写入的,但是块的大小与AVR的型号有关,不是每种都一样,从16字节到128直接都有。所以需要等收完一个块后,计算校验后才能写入flash。

正常情况下,是不会出现数据不足128字节的。编译后生成的HEX文件,一般都会补足128字节。如果不足128字节,可以让上位机来补足,避免单片机去完成这个事情。毕竟底层的资源少。

点评

因为现在出现了jtag烧写可以正常跑 通过bootloader下到flash就程序跑飞 有什么手段能看到在flash里这两种下载方法烧进去的程序的区别吗  详情 回复 发表于 2015-9-15 13:09
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

11
 
dcexpert 发表于 2015-9-15 11:49
xmega不太清楚,AVR中是这样,Flash是需要块写入的,但是块的大小与AVR的型号有关,不是每种都一样,从16 ...

因为现在出现了jtag烧写可以正常跑   通过bootloader下到flash就程序跑飞  

有什么手段能看到在flash里这两种下载方法烧进去的程序的区别吗

点评

先用Bootloader下载,再用Jtag读出来,保存为bin格式,做一下二进制比较。  详情 回复 发表于 2015-9-15 13:31
 
 
 

回复

1万

帖子

25

TA的资源

版主

12
 
285844685 发表于 2015-9-15 13:09
因为现在出现了jtag烧写可以正常跑   通过bootloader下到flash就程序跑飞  

有什么手段能看到在flash ...

先用Bootloader下载,再用Jtag读出来,保存为bin格式,做一下二进制比较。

点评

问题解决! boot代码里是 每次收满512个才往flash里写一次,因为xmega128的每个page就是512bytes 而串口助手只是会以128字节为单元去补满,导致最后一个不满512的page丢失。 希望能帮到后来人。 再次感谢d  详情 回复 发表于 2015-9-17 08:59
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

13
 
dcexpert 发表于 2015-9-15 13:31
先用Bootloader下载,再用Jtag读出来,保存为bin格式,做一下二进制比较。

问题解决!

boot代码里是 每次收满512个才往flash里写一次,因为xmega128的每个page就是512bytes
而串口助手只是会以128字节为单元去补满,导致最后一个不满512的page丢失。

希望能帮到后来人。

再次感谢dcexpert斑竹!
 
 
 

回复

26

帖子

0

TA的资源

一粒金砂(中级)

14
 
  1. if(bufptr >= SPM_PAGESIZE)          //缓冲区满,写入数据;否则继续接收
  2.           {                                   //接收多个帧,写入一页
  3.             write_one_page(buf);              //写入缓冲区内容到Flash中
  4.             FlashAddr += SPM_PAGESIZE;        //修改Flash页地址
  5.             bufptr = 0;
  6.           }
复制代码
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

15
 
不知道版主在使用的是有有没有遇到我这样的问题,

我用的片子是xmega64d4,环境是AS7,使用的USARTD0,波特兰38400,熔丝位BOOTRST设置为:Boot Loader Reset,配置好串口,使用AVRUBD工具下载一个新hex,发现可以:
1.密码验证正确
2.有Waiting Flash Data打印
3.显示联机成功


跟踪到这里:
  putstr(msg3);                 //提示等待接收文件
//进入等二环节
//密码对上了,准备接收数据
//------------------------------------------------------------------------------
//每个时隙向PC机发送一个控制字符“C”,等待控制字〈soh〉
  cnt = TimeOutCntC;
  signal=0;
delay_us(1000);
  while(signal==0)
  {
    if(TC_GetOverflowFlag(&TCC0))  //T1溢出
    {
     ioport_set_pin_high(USARTC0_485_CONTROL_GPIO);
      TC_ClearOverflowFlag(&TCC0);
      WriteCom(XMODEM_RWC) ;    //发送 "C"
      cnt--;
      if(cnt == 0)              //超时
      {
        putstr(msg2);           //提示超时
        quit();                 //退出 bootloader
      }
    }
     delay_us(8000);
    ioport_set_pin_low(USARTC0_485_CONTROL_GPIO);//准备接收密码
    if(USART_IsRXComplete(&USART)) //收到字符?
    {
          get_char=USART_GetChar(&USART);
      if(get_char == XMODEM_SOH)  //XMODEM命令开始
        {signal=1;break;}
    }
  }
//已经收到一个起启字符了 开始更新Application

前面密码已经对上,此时AVRUBD应该发送“XMODEM_SOH”,然后我板子应该回复“C”,但是真实的情况是:
1.AVRUBD还在发送六次“41 56 52 55 42”
2.板子回复“C”
3.AVRUBD又发送六次“41 56 52 55 42”
4.板子回复“C”
5.然后AVRUBD工具显示:
V联机成功
X重复次数太多
X升级失败

哪里有AVRUBD工具的使用说明吗?这里为什么会这样,其实只要AVRUBD发送“XMODEN_SOH”,就可以跳转到下一个while里面?
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

16
 
我和版主使用的同一套代码,修改为xmega64d4的bootloader,我最近几次的仿真结果是:
packNO = 1;
CH = 0X41(0x41正好是密码的第一个字节)

经过多次仿真,我发现是AVRBUD工具,在发送完密码后,我板子已经解析,板子然后发送"C"字符,AVRUBD工具接收到"C",然后板子等待AVRUBN工具发送XMODEM协议的SOH(就是0x01,XMODEM的开始命令),然而AVRUBD工具还一直在发送密码,始终不发送XMODEM的SOH,不知道为什么
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表