找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 964|回复: 0
收起左侧

Mega1280的BootLoader故障

[复制链接]
ID:90212 发表于 2024-5-20 21:28 | 显示全部楼层 |阅读模式
临时抱佛脚,恶补了下ICCAVR,把Mega128的BootLoader成功改成了Mega1280,能以XModem协议通信刷机,刷机过程看似正常,问题是刷机后的运行不正常,不知道是哪里的问题,请懂AVR的指点指点:


  1. /*****************************************************
  2. 采用串行接口实现Boot_load应用的实例 华东师大电子系 马 潮
  3. Compiler: ICC-AVR 7.22
  4. Target: Mega128 改 Mega1280
  5. Crystal: 16Mhz
  6. Used: T/C0,USART0
  7. 2024-5-13改部转义字符 '/' 为 '\' 和部分错误
  8. 2024-5-18修改为Mega1280能通信刷机,但刷完运行不正常
  9. *****************************************************/
  10. #include <iom1280v.h>
  11. #define SPM_PAGESIZE 256 //M128的一个Flash页为256字节(128字)
  12. #define BAUD 19200 //波特率采用38400bps
  13. #define CRYSTAL 16000000 //系统时钟16MHz
  14. //计算和定义M128的波特率设置参数
  15. #define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)
  16. #define BAUD_H (unsigned char)(BAUD_SETTING>>8)
  17. #define BAUD_L (unsigned char)(BAUD_SETTING)
  18. #define DATA_BUFFER_SIZE SPM_PAGESIZE //定义接收缓冲区长度
  19. //定义Xmoden控制字符
  20. #define XMODEM_NUL 0x00
  21. #define XMODEM_SOH 0x01
  22. #define XMODEM_STX 0x02
  23. #define XMODEM_EOT 0x04
  24. #define XMODEM_ACK 0x06
  25. #define XMODEM_NAK 0x15
  26. #define XMODEM_CAN 0x18
  27. #define XMODEM_EOF 0x1A
  28. #define XMODEM_RECIEVING_WAIT_CHAR 'C'
  29. //定义全局变量

  30. char data[DATA_BUFFER_SIZE];
  31. long address = 0;

  32. //擦除(code=0x03)和写入(code=0x05)一个Flash页
  33. void boot_page_ew(long p_address, char code)
  34. {
  35.     asm("mov r30,r16\n"
  36.         "mov r31,r17\n"
  37.         "out 0x3b,r18\n"); //将页地址放入Z寄存器和RAMPZ的Bit0中
  38.     SPMCSR = code; //寄存器SPMCSR中为操作码
  39.     asm("spm\n"); //对指定Flash页进行操作
  40. }

  41. //填充Flash缓冲页中的一个字
  42. void boot_page_fill(unsigned int address, int data)
  43. {
  44.     asm("mov r30,r16\n"
  45.         "mov r31,r17\n" //Z寄存器中为填冲页内地址
  46.         "mov r0,r18\n"
  47.         "mov r1,r19\n"); //r0R1中为一个指令字
  48.     SPMCSR = 0x01;
  49.     asm("spm\n");
  50. }

  51. //等待一个Flash页的写完成
  52. void wait_page_rw_ok(void)
  53. {
  54.     while(SPMCSR & 0x40)
  55.     {
  56.         while(SPMCSR & 0x01);
  57.         SPMCSR = 0x11;
  58.         asm("spm\n");
  59.     }
  60. }

  61. //更新一个Flash页的完整处理
  62. void write_one_page(void)
  63. {
  64.     int i;
  65.     boot_page_ew(address, 0x03); //擦除一个Flash页
  66.     wait_page_rw_ok(); //等待擦除完成
  67.     for(i = 0; i < SPM_PAGESIZE; i += 2) //将数据填入Flash缓冲页中
  68.     {
  69.         boot_page_fill(i, data[i] + (data[i + 1] << 8));
  70.     }
  71.     boot_page_ew(address, 0x05); //将缓冲页数据写入一个Flash页
  72.     wait_page_rw_ok(); //等待写入完成
  73. }

  74. //从RS232发送一个字节
  75. void uart_putchar(char c)
  76. {
  77.     while(!(UCSR0A & 0x20));
  78.     UDR0 = c;
  79. }

  80. //从RS232接收一个字节
  81. int uart_getchar(void)
  82. {
  83.     unsigned char status, res;
  84.     if(!(UCSR0A & 0x80)) return -1; //no data to be received
  85.     status = UCSR0A;
  86.     res = UDR0;
  87.     if (status & 0x1c) return -1; // If error, return -1
  88.     return res;
  89. }

  90. //等待从RS232接收一个有效的字节
  91. char uart_waitchar(void)
  92. {
  93.     int c;
  94.     while((c = uart_getchar()) == -1);
  95.     return (char)c;
  96. }
  97. //计算CRC
  98. int calcrc(char *ptr, int count)
  99. {
  100.     int crc = 0;
  101.     char i;
  102.     while (--count >= 0)
  103.     {
  104.         crc = crc ^ (int) * ptr++ << 8;
  105.         i = 8;
  106.         do
  107.         {
  108.             if (crc & 0x8000)
  109.                 crc = crc << 1 ^ 0x1021;
  110.             else
  111.                 crc = crc << 1;
  112.         }
  113.         while(--i);
  114.     }
  115.     return (crc);
  116. }
  117. //退出Bootloader程序,从0x0000处执行应用程序

  118. void quit(void)
  119. {
  120.     //uart_putchar('O');
  121.     //uart_putchar('K');
  122.     //while(!(UCSR0A & 0x20)); //等待结束提示信息回送完成
  123.     MCUCR = 0x01;
  124.     MCUCR = 0x00; //将中断向量表迁移到应用程序区头部
  125.     RAMPZ = 0x00; //rAMPZ清零初始化
  126.     asm("jmp 0x0000\n"); //跳转到Flash的0x0000处,执行用户的应用程序
  127. }
  128. //UART0 initialize
  129. // desired baud rate: 19200
  130. // actual: baud rate:19231 (0.2%)
  131. // char size: 8 bit
  132. // parity: Disabled
  133. void uart0_init(void)
  134. {
  135.     UCSR0B = 0x00; //disable while setting baud rate
  136.     UCSR0A = 0x00;
  137.     UCSR0C = 0x06;
  138.     UBRR0H = BAUD_H;
  139.     UBRR0L = BAUD_L; //Set baud rate
  140.     UCSR0B = 0x18;
  141. }
  142. //TIMER0 initialize - prescale:1024
  143. // desired value: 15mSec
  144. // actual value: 14.976mSec (0.2%)
  145. void timer0_init(void)
  146. {
  147.     TCCR0B = 0x00; //stop
  148.     TCNT0 = 0x16; //set count
  149.     OCR0A = 0xEA;
  150.     TCCR0A = 0x00; //start timer
  151.     TCCR0B = 0x05; //start timer
  152. }
  153. //主程序
  154. void main(void)
  155. {
  156.     int i = 0;
  157.     unsigned char timercount = 0;
  158.     unsigned char packNO = 1;
  159.     int bufferPoint = 0;
  160.     unsigned int crc;

  161.     uart0_init();
  162.     timer0_init();

  163.     //3秒种等待PC下发"d",否则退出Bootloader程序,从0x0000处执行应用程序
  164.     while(1)
  165.     {
  166.         if(uart_getchar() == 'd')
  167.         {
  168.             uart_putchar(XMODEM_RECIEVING_WAIT_CHAR);
  169.             break;
  170.         }
  171.         if (TIFR0 & 0x02) //timer0 over flow
  172.         {
  173.             if (++timercount > 200)
  174.                 quit(); //200*15ms = 3s
  175.             TIFR0 = TIFR0 | 0x02;
  176.         }
  177.     }

  178.     //每秒向PC机发送一个控制字符"C",等待控制字〈soh?
  179.     while(uart_getchar() != XMODEM_SOH) //receive the start of Xmodem
  180.     {
  181.         if(TIFR0 & 0x02) //timer0 over flow
  182.         {
  183.             if(++timercount > 80) //wait about 1 second
  184.             {
  185.                 uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a "C"
  186.                 timercount = 0;
  187.             }
  188.             TIFR0 = TIFR0 | 0x02;
  189.         }
  190.     }

  191.     //开始接收数据块
  192.     do
  193.     {
  194.         if ((packNO == uart_waitchar()) && (packNO == (~uart_waitchar())))
  195.         {
  196.             //核对数据块编号正确
  197.             for(i = 0; i < 128; i++) //接收128个字节数据
  198.             {
  199.                 data[bufferPoint] = uart_waitchar();
  200.                 bufferPoint++;
  201.             }
  202.             crc = (uart_waitchar() << 8);
  203.             crc += uart_waitchar(); //接收2个字节的CRC效验字
  204.             if(calcrc(&data[bufferPoint - 128], 128) == crc) //CRC校验验证
  205.             {
  206.                 //正确接收128个字节数据
  207.                 while(bufferPoint >= SPM_PAGESIZE)
  208.                 {
  209.                     //正确接受256个字节的数据
  210.                     write_one_page(); //收到256字节写入一页Flash中
  211.                     address += SPM_PAGESIZE; //Flash页加1
  212.                     bufferPoint = 0;
  213.                 }
  214.                 uart_putchar(XMODEM_ACK); //正确收到一个数据块
  215.                 packNO++; //数据块编号加1
  216.             }
  217.             else
  218.             {
  219.                 uart_putchar(XMODEM_NAK); //要求重发数据块
  220.             }
  221.         }
  222.         else
  223.         {
  224.             uart_putchar(XMODEM_NAK); //要求重发数据块
  225.         }
  226.     }
  227.     while(uart_waitchar() != XMODEM_EOT); //循环接收,直到全部发完
  228.     uart_putchar(XMODEM_ACK); //通知PC机全部收到

  229.     if(bufferPoint) write_one_page(); //把剩余的数据写入Flash中
  230.     quit(); //退出Bootloader程序,从0x0000处执行应用程序
  231. }

复制代码



回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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