|
臨時(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):
- /*****************************************************
- 采用串行接口實(shí)現(xiàn)Boot_load應(yīng)用的實(shí)例 華東師大電子系 馬 潮
- Compiler: ICC-AVR 7.22
- Target: Mega128 改 Mega1280
- Crystal: 16Mhz
- Used: T/C0,USART0
- 2024-5-13改部轉(zhuǎn)義字符 '/' 為 '\' 和部分錯(cuò)誤
- 2024-5-18修改為Mega1280能通信刷機(jī),但刷完運(yùn)行不正常
- *****************************************************/
- #include <iom1280v.h>
- #define SPM_PAGESIZE 256 //M128的一個(gè)Flash頁(yè)為256字節(jié)(128字)
- #define BAUD 19200 //波特率采用38400bps
- #define CRYSTAL 16000000 //系統(tǒng)時(shí)鐘16MHz
- //計(jì)算和定義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ū)長(zhǎng)度
- //定義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)和寫(xiě)入(code=0x05)一個(gè)Flash頁(yè)
- void boot_page_ew(long p_address, char code)
- {
- asm("mov r30,r16\n"
- "mov r31,r17\n"
- "out 0x3b,r18\n"); //將頁(yè)地址放入Z寄存器和RAMPZ的Bit0中
- SPMCSR = code; //寄存器SPMCSR中為操作碼
- asm("spm\n"); //對(duì)指定Flash頁(yè)進(jìn)行操作
- }
- //填充Flash緩沖頁(yè)中的一個(gè)字
- void boot_page_fill(unsigned int address, int data)
- {
- asm("mov r30,r16\n"
- "mov r31,r17\n" //Z寄存器中為填沖頁(yè)內(nèi)地址
- "mov r0,r18\n"
- "mov r1,r19\n"); //r0R1中為一個(gè)指令字
- SPMCSR = 0x01;
- asm("spm\n");
- }
- //等待一個(gè)Flash頁(yè)的寫(xiě)完成
- void wait_page_rw_ok(void)
- {
- while(SPMCSR & 0x40)
- {
- while(SPMCSR & 0x01);
- SPMCSR = 0x11;
- asm("spm\n");
- }
- }
- //更新一個(gè)Flash頁(yè)的完整處理
- void write_one_page(void)
- {
- int i;
- boot_page_ew(address, 0x03); //擦除一個(gè)Flash頁(yè)
- wait_page_rw_ok(); //等待擦除完成
- for(i = 0; i < SPM_PAGESIZE; i += 2) //將數(shù)據(jù)填入Flash緩沖頁(yè)中
- {
- boot_page_fill(i, data[i] + (data[i + 1] << 8));
- }
- boot_page_ew(address, 0x05); //將緩沖頁(yè)數(shù)據(jù)寫(xiě)入一個(gè)Flash頁(yè)
- wait_page_rw_ok(); //等待寫(xiě)入完成
- }
- //從RS232發(fā)送一個(gè)字節(jié)
- void uart_putchar(char c)
- {
- while(!(UCSR0A & 0x20));
- UDR0 = c;
- }
- //從RS232接收一個(gè)字節(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接收一個(gè)有效的字節(jié)
- char uart_waitchar(void)
- {
- int c;
- while((c = uart_getchar()) == -1);
- return (char)c;
- }
- //計(jì)算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ā)送一個(gè)控制字符"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;
- }
- }
- //開(kāi)始接收數(shù)據(jù)塊
- do
- {
- if ((packNO == uart_waitchar()) && (packNO == (~uart_waitchar())))
- {
- //核對(duì)數(shù)據(jù)塊編號(hào)正確
- for(i = 0; i < 128; i++) //接收128個(gè)字節(jié)數(shù)據(jù)
- {
- data[bufferPoint] = uart_waitchar();
- bufferPoint++;
- }
- crc = (uart_waitchar() << 8);
- crc += uart_waitchar(); //接收2個(gè)字節(jié)的CRC效驗(yàn)字
- if(calcrc(&data[bufferPoint - 128], 128) == crc) //CRC校驗(yàn)驗(yàn)證
- {
- //正確接收128個(gè)字節(jié)數(shù)據(jù)
- while(bufferPoint >= SPM_PAGESIZE)
- {
- //正確接受256個(gè)字節(jié)的數(shù)據(jù)
- write_one_page(); //收到256字節(jié)寫(xiě)入一頁(yè)Flash中
- address += SPM_PAGESIZE; //Flash頁(yè)加1
- bufferPoint = 0;
- }
- uart_putchar(XMODEM_ACK); //正確收到一個(gè)數(shù)據(jù)塊
- packNO++; //數(shù)據(jù)塊編號(hào)加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ù)寫(xiě)入Flash中
- quit(); //退出Bootloader程序,從0x0000處執(zhí)行應(yīng)用程序
- }
復(fù)制代碼
|
|