找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 988|回復(fù): 0
收起左側(cè)

Mega1280的BootLoader故障

[復(fù)制鏈接]
ID:90212 發(fā)表于 2024-5-20 21:28 | 顯示全部樓層 |閱讀模式
臨時(shí)抱佛腳,惡補(bǔ)了下ICCAVR,把Mega128的BootLoader成功改成了Mega1280,能以XModem協(xié)議通信刷機(jī),刷機(jī)過(guò)程看似正常,問(wèn)題是刷機(jī)后的運(yùn)行不正常,不知道是哪里的問(wèn)題,請(qǐng)懂AVR的指點(diǎn)指點(diǎn):


  1. /*****************************************************
  2. 采用串行接口實(shí)現(xiàn)Boot_load應(yīng)用的實(shí)例 華東師大電子系 馬 潮
  3. Compiler: ICC-AVR 7.22
  4. Target: Mega128 改 Mega1280
  5. Crystal: 16Mhz
  6. Used: T/C0,USART0
  7. 2024-5-13改部轉(zhuǎn)義字符 '/' 為 '\' 和部分錯(cuò)誤
  8. 2024-5-18修改為Mega1280能通信刷機(jī),但刷完運(yùn)行不正常
  9. *****************************************************/
  10. #include <iom1280v.h>
  11. #define SPM_PAGESIZE 256 //M128的一個(gè)Flash頁(yè)為256字節(jié)(128字)
  12. #define BAUD 19200 //波特率采用38400bps
  13. #define CRYSTAL 16000000 //系統(tǒng)時(shí)鐘16MHz
  14. //計(jì)算和定義M128的波特率設(shè)置參數(shù)
  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 //定義接收緩沖區(qū)長(zhǎng)度
  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)和寫(xiě)入(code=0x05)一個(gè)Flash頁(yè)
  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"); //將頁(yè)地址放入Z寄存器和RAMPZ的Bit0中
  38.     SPMCSR = code; //寄存器SPMCSR中為操作碼
  39.     asm("spm\n"); //對(duì)指定Flash頁(yè)進(jìn)行操作
  40. }

  41. //填充Flash緩沖頁(yè)中的一個(gè)字
  42. void boot_page_fill(unsigned int address, int data)
  43. {
  44.     asm("mov r30,r16\n"
  45.         "mov r31,r17\n" //Z寄存器中為填沖頁(yè)內(nèi)地址
  46.         "mov r0,r18\n"
  47.         "mov r1,r19\n"); //r0R1中為一個(gè)指令字
  48.     SPMCSR = 0x01;
  49.     asm("spm\n");
  50. }

  51. //等待一個(gè)Flash頁(yè)的寫(xiě)完成
  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. //更新一個(gè)Flash頁(yè)的完整處理
  62. void write_one_page(void)
  63. {
  64.     int i;
  65.     boot_page_ew(address, 0x03); //擦除一個(gè)Flash頁(yè)
  66.     wait_page_rw_ok(); //等待擦除完成
  67.     for(i = 0; i < SPM_PAGESIZE; i += 2) //將數(shù)據(jù)填入Flash緩沖頁(yè)中
  68.     {
  69.         boot_page_fill(i, data[i] + (data[i + 1] << 8));
  70.     }
  71.     boot_page_ew(address, 0x05); //將緩沖頁(yè)數(shù)據(jù)寫(xiě)入一個(gè)Flash頁(yè)
  72.     wait_page_rw_ok(); //等待寫(xiě)入完成
  73. }

  74. //從RS232發(fā)送一個(gè)字節(jié)
  75. void uart_putchar(char c)
  76. {
  77.     while(!(UCSR0A & 0x20));
  78.     UDR0 = c;
  79. }

  80. //從RS232接收一個(gè)字節(jié)
  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接收一個(gè)有效的字節(jié)
  91. char uart_waitchar(void)
  92. {
  93.     int c;
  94.     while((c = uart_getchar()) == -1);
  95.     return (char)c;
  96. }
  97. //計(jì)算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處執(zhí)行應(yīng)用程序

  118. void quit(void)
  119. {
  120.     //uart_putchar('O');
  121.     //uart_putchar('K');
  122.     //while(!(UCSR0A & 0x20)); //等待結(jié)束提示信息回送完成
  123.     MCUCR = 0x01;
  124.     MCUCR = 0x00; //將中斷向量表遷移到應(yīng)用程序區(qū)頭部
  125.     RAMPZ = 0x00; //rAMPZ清零初始化
  126.     asm("jmp 0x0000\n"); //跳轉(zhuǎn)到Flash的0x0000處,執(zhí)行用戶的應(yīng)用程序
  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下發(fā)"d",否則退出Bootloader程序,從0x0000處執(zhí)行應(yīng)用程序
  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機(jī)發(fā)送一個(gè)控制字符"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.     //開(kāi)始接收數(shù)據(jù)塊
  192.     do
  193.     {
  194.         if ((packNO == uart_waitchar()) && (packNO == (~uart_waitchar())))
  195.         {
  196.             //核對(duì)數(shù)據(jù)塊編號(hào)正確
  197.             for(i = 0; i < 128; i++) //接收128個(gè)字節(jié)數(shù)據(jù)
  198.             {
  199.                 data[bufferPoint] = uart_waitchar();
  200.                 bufferPoint++;
  201.             }
  202.             crc = (uart_waitchar() << 8);
  203.             crc += uart_waitchar(); //接收2個(gè)字節(jié)的CRC效驗(yàn)字
  204.             if(calcrc(&data[bufferPoint - 128], 128) == crc) //CRC校驗(yàn)驗(yàn)證
  205.             {
  206.                 //正確接收128個(gè)字節(jié)數(shù)據(jù)
  207.                 while(bufferPoint >= SPM_PAGESIZE)
  208.                 {
  209.                     //正確接受256個(gè)字節(jié)的數(shù)據(jù)
  210.                     write_one_page(); //收到256字節(jié)寫(xiě)入一頁(yè)Flash中
  211.                     address += SPM_PAGESIZE; //Flash頁(yè)加1
  212.                     bufferPoint = 0;
  213.                 }
  214.                 uart_putchar(XMODEM_ACK); //正確收到一個(gè)數(shù)據(jù)塊
  215.                 packNO++; //數(shù)據(jù)塊編號(hào)加1
  216.             }
  217.             else
  218.             {
  219.                 uart_putchar(XMODEM_NAK); //要求重發(fā)數(shù)據(jù)塊
  220.             }
  221.         }
  222.         else
  223.         {
  224.             uart_putchar(XMODEM_NAK); //要求重發(fā)數(shù)據(jù)塊
  225.         }
  226.     }
  227.     while(uart_waitchar() != XMODEM_EOT); //循環(huán)接收,直到全部發(fā)完
  228.     uart_putchar(XMODEM_ACK); //通知PC機(jī)全部收到

  229.     if(bufferPoint) write_one_page(); //把剩余的數(shù)據(jù)寫(xiě)入Flash中
  230.     quit(); //退出Bootloader程序,從0x0000處執(zhí)行應(yīng)用程序
  231. }

復(fù)制代碼



回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表