標(biāo)題:
Mega1280的BootLoader故障
[打印本頁]
作者:
gongzhu
時間:
2024-5-20 21:28
標(biāo)題:
Mega1280的BootLoader故障
臨時抱佛腳,惡補(bǔ)了下ICCAVR,把Mega128的BootLoader成功改成了Mega1280,能以XModem協(xié)議通信刷機(jī),刷機(jī)過程看似正常,問題是刷機(jī)后的運(yùn)行不正常,不知道是哪里的問題,請懂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)義字符 '/' 為 '\' 和部分錯誤
2024-5-18修改為Mega1280能通信刷機(jī),但刷完運(yùn)行不正常
*****************************************************/
#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效驗(yàn)字
if(calcrc(&data[bufferPoint - 128], 128) == crc) //CRC校驗(yàn)驗(yàn)證
{
//正確接收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ù)制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1