|
臨時抱佛腳,惡補(bǔ)了下ICCAVR,把Mega128的BootLoader成功改成了Mega1280,能以XModem協(xié)議通信刷機(jī),刷機(jī)過程看似正常,問題是刷機(jī)后的運行不正常,不知道是哪里的問題,請懂AVR的指點指點:
- /*****************************************************
- 采用串行接口實現(xiàn)Boot_load應(yīng)用的實例 華東師大電子系 馬 潮
- Compiler: ICC-AVR 7.22
- Target: Mega128 改 Mega1280
- Crystal: 16Mhz
- Used: T/C0,USART0
- 2024-5-13改部轉(zhuǎn)義字符 '/' 為 '\' 和部分錯誤
- 2024-5-18修改為Mega1280能通信刷機(jī),但刷完運行不正常
- *****************************************************/
- #include <iom1280v.h>
- #define SPM_PAGESIZE 256 //M128的一個Flash頁為256字節(jié)(128字)
- #define BAUD 19200 //波特率采用38400bps
- #define CRYSTAL 16000000 //系統(tǒng)時鐘16MHz
- //計算和定義M128的波特率設(shè)置參數(shù)
- #define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)
- #define BAUD_H (unsigned char)(BAUD_SETTING>>8)
- #define BAUD_L (unsigned char)(BAUD_SETTING)
- #define DATA_BUFFER_SIZE SPM_PAGESIZE //定義接收緩沖區(qū)長度
- //定義Xmoden控制字符
- #define XMODEM_NUL 0x00
- #define XMODEM_SOH 0x01
- #define XMODEM_STX 0x02
- #define XMODEM_EOT 0x04
- #define XMODEM_ACK 0x06
- #define XMODEM_NAK 0x15
- #define XMODEM_CAN 0x18
- #define XMODEM_EOF 0x1A
- #define XMODEM_RECIEVING_WAIT_CHAR 'C'
- //定義全局變量
- char data[DATA_BUFFER_SIZE];
- long address = 0;
- //擦除(code=0x03)和寫入(code=0x05)一個Flash頁
- void boot_page_ew(long p_address, char code)
- {
- asm("mov r30,r16\n"
- "mov r31,r17\n"
- "out 0x3b,r18\n"); //將頁地址放入Z寄存器和RAMPZ的Bit0中
- SPMCSR = code; //寄存器SPMCSR中為操作碼
- asm("spm\n"); //對指定Flash頁進(jìn)行操作
- }
- //填充Flash緩沖頁中的一個字
- void boot_page_fill(unsigned int address, int data)
- {
- asm("mov r30,r16\n"
- "mov r31,r17\n" //Z寄存器中為填沖頁內(nèi)地址
- "mov r0,r18\n"
- "mov r1,r19\n"); //r0R1中為一個指令字
- SPMCSR = 0x01;
- asm("spm\n");
- }
- //等待一個Flash頁的寫完成
- void wait_page_rw_ok(void)
- {
- while(SPMCSR & 0x40)
- {
- while(SPMCSR & 0x01);
- SPMCSR = 0x11;
- asm("spm\n");
- }
- }
- //更新一個Flash頁的完整處理
- void write_one_page(void)
- {
- int i;
- boot_page_ew(address, 0x03); //擦除一個Flash頁
- wait_page_rw_ok(); //等待擦除完成
- for(i = 0; i < SPM_PAGESIZE; i += 2) //將數(shù)據(jù)填入Flash緩沖頁中
- {
- boot_page_fill(i, data[i] + (data[i + 1] << 8));
- }
- boot_page_ew(address, 0x05); //將緩沖頁數(shù)據(jù)寫入一個Flash頁
- wait_page_rw_ok(); //等待寫入完成
- }
- //從RS232發(fā)送一個字節(jié)
- void uart_putchar(char c)
- {
- while(!(UCSR0A & 0x20));
- UDR0 = c;
- }
- //從RS232接收一個字節(jié)
- int uart_getchar(void)
- {
- unsigned char status, res;
- if(!(UCSR0A & 0x80)) return -1; //no data to be received
- status = UCSR0A;
- res = UDR0;
- if (status & 0x1c) return -1; // If error, return -1
- return res;
- }
- //等待從RS232接收一個有效的字節(jié)
- char uart_waitchar(void)
- {
- int c;
- while((c = uart_getchar()) == -1);
- return (char)c;
- }
- //計算CRC
- int calcrc(char *ptr, int count)
- {
- int crc = 0;
- char i;
- while (--count >= 0)
- {
- crc = crc ^ (int) * ptr++ << 8;
- i = 8;
- do
- {
- if (crc & 0x8000)
- crc = crc << 1 ^ 0x1021;
- else
- crc = crc << 1;
- }
- while(--i);
- }
- return (crc);
- }
- //退出Bootloader程序,從0x0000處執(zhí)行應(yīng)用程序
- void quit(void)
- {
- //uart_putchar('O');
- //uart_putchar('K');
- //while(!(UCSR0A & 0x20)); //等待結(jié)束提示信息回送完成
- MCUCR = 0x01;
- MCUCR = 0x00; //將中斷向量表遷移到應(yīng)用程序區(qū)頭部
- RAMPZ = 0x00; //rAMPZ清零初始化
- asm("jmp 0x0000\n"); //跳轉(zhuǎn)到Flash的0x0000處,執(zhí)行用戶的應(yīng)用程序
- }
- //UART0 initialize
- // desired baud rate: 19200
- // actual: baud rate:19231 (0.2%)
- // char size: 8 bit
- // parity: Disabled
- void uart0_init(void)
- {
- UCSR0B = 0x00; //disable while setting baud rate
- UCSR0A = 0x00;
- UCSR0C = 0x06;
- UBRR0H = BAUD_H;
- UBRR0L = BAUD_L; //Set baud rate
- UCSR0B = 0x18;
- }
- //TIMER0 initialize - prescale:1024
- // desired value: 15mSec
- // actual value: 14.976mSec (0.2%)
- void timer0_init(void)
- {
- TCCR0B = 0x00; //stop
- TCNT0 = 0x16; //set count
- OCR0A = 0xEA;
- TCCR0A = 0x00; //start timer
- TCCR0B = 0x05; //start timer
- }
- //主程序
- void main(void)
- {
- int i = 0;
- unsigned char timercount = 0;
- unsigned char packNO = 1;
- int bufferPoint = 0;
- unsigned int crc;
- uart0_init();
- timer0_init();
- //3秒種等待PC下發(fā)"d",否則退出Bootloader程序,從0x0000處執(zhí)行應(yīng)用程序
- while(1)
- {
- if(uart_getchar() == 'd')
- {
- uart_putchar(XMODEM_RECIEVING_WAIT_CHAR);
- break;
- }
- if (TIFR0 & 0x02) //timer0 over flow
- {
- if (++timercount > 200)
- quit(); //200*15ms = 3s
- TIFR0 = TIFR0 | 0x02;
- }
- }
- //每秒向PC機(jī)發(fā)送一個控制字符"C",等待控制字〈soh?
- while(uart_getchar() != XMODEM_SOH) //receive the start of Xmodem
- {
- if(TIFR0 & 0x02) //timer0 over flow
- {
- if(++timercount > 80) //wait about 1 second
- {
- uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a "C"
- timercount = 0;
- }
- TIFR0 = TIFR0 | 0x02;
- }
- }
- //開始接收數(shù)據(jù)塊
- do
- {
- if ((packNO == uart_waitchar()) && (packNO == (~uart_waitchar())))
- {
- //核對數(shù)據(jù)塊編號正確
- for(i = 0; i < 128; i++) //接收128個字節(jié)數(shù)據(jù)
- {
- data[bufferPoint] = uart_waitchar();
- bufferPoint++;
- }
- crc = (uart_waitchar() << 8);
- crc += uart_waitchar(); //接收2個字節(jié)的CRC效驗字
- if(calcrc(&data[bufferPoint - 128], 128) == crc) //CRC校驗驗證
- {
- //正確接收128個字節(jié)數(shù)據(jù)
- while(bufferPoint >= SPM_PAGESIZE)
- {
- //正確接受256個字節(jié)的數(shù)據(jù)
- write_one_page(); //收到256字節(jié)寫入一頁Flash中
- address += SPM_PAGESIZE; //Flash頁加1
- bufferPoint = 0;
- }
- uart_putchar(XMODEM_ACK); //正確收到一個數(shù)據(jù)塊
- packNO++; //數(shù)據(jù)塊編號加1
- }
- else
- {
- uart_putchar(XMODEM_NAK); //要求重發(fā)數(shù)據(jù)塊
- }
- }
- else
- {
- uart_putchar(XMODEM_NAK); //要求重發(fā)數(shù)據(jù)塊
- }
- }
- while(uart_waitchar() != XMODEM_EOT); //循環(huán)接收,直到全部發(fā)完
- uart_putchar(XMODEM_ACK); //通知PC機(jī)全部收到
- if(bufferPoint) write_one_page(); //把剩余的數(shù)據(jù)寫入Flash中
- quit(); //退出Bootloader程序,從0x0000處執(zhí)行應(yīng)用程序
- }
復(fù)制代碼
|
|