求助:深入浅出AVR(IAP移植),谢谢
硬件:mega16L软件:ICC6.311、我使用书中的例程(boot基础事例程序)改写成mega16的程序,读取flash,可以看到flash被改写成“串口数据包计算助手”生成的数据。
但我,根据例程(实例18_ATmega48在线程序更新_闪烁方式1)修改后,mega48在线下载后台软件可以下载成功程序,但程序运行的不是IAP下载的程序。不知道是怎么回事。
谢谢。
程序如下:
#include "iom16v.h"
#include "macros.h"
#definemclk 16000000
#define Con_true 1
#define CmdByte IapBuffer
#define PageAddrL IapBuffer
#define PageAddrH IapBuffer
void Iap (void);
union Char_Int
{
unsigned char chr_dat;
unsigned int Int_dat;
};
#define CHAR_H 1
#define CHAR_L 0
void Delay_mS(unsigned int Time)
{
unsigned char n;
while(Time>0)
{
for (n=1;n<187;n++)
{
asm("nop");
}
Time--;
}
}
void main (void)
{
DDRC = 0xFF;
PORTC = 0xFF;
DDRB = 0x00; //PB端口输入状态
PORTB = 0xFF; //PB端口开启内建上拉
uart_init(9600);
// uart_putchar('a') ;
/*
while(PINB&0x01)
{
PORTC ^= 0xFF;
Delay_mS(500);
}
*/
Iap();
}
#pragma text:boot_zone
/*******************************************
函数名称: Uart_init
功 能: 异步串口初始化
参 数: 无
返回值: 无
/********************************************/
void uart_init(unsigned int baud)
{
UCSRB=0x00;
UCSRA=0x00; //控制寄存器清零
UCSRC=(1<<URSEL)|(0<<UPM0)|(3<<UCSZ0); //选择UCSRC,异步模式,禁止
baud=mclk/16/baud-1 ; // 校验,1位停止位,8位数据位
UBRRL=baud; //波特率最大为65K
UBRRH=baud>>8; //设置波特率
UCSRB=(1<<TXEN)|(1<<RXEN); //接收、发送使能,接收中断使能
// SREG|=0x80; //全局中断开放
DDRD|=0X02; //配置TX为输出(很重要)
}
//从RS232发送一个字节
void uart_putchar(char c)
{
while(!(UCSRA & 0x20));
UDR = c;
}
//从RS232接收一个字节
int uart_getchar(void)
{
unsigned char status,res;
if(!(UCSRA & 0x80)) return -1; //no data to be received
status = UCSRA;
res = UDR;
if (status & 0x1c) return -1; // If error, return -1
return res;
}
unsigned char Iap_Receive (void)
{
unsigned int counter;
counter = 30000;
while(!(UCSRA&(1<<RXC)))
{
if (counter==0)
{
PORTC ^= (1<<5);
counter = 30000;
}
counter--;
};
return UDR;
}
void Iap_OK () //发送应答包 AA 05 50 55 55
{
unsigned char Iap_Pack_OK;
unsigned char i;
Iap_Pack_OK = 0xAA;
Iap_Pack_OK = 0x05;
Iap_Pack_OK = 0x50;
Iap_Pack_OK = 0x55;
Iap_Pack_OK = 0x55;
for (i = 0 ; i < 5 ; i++)
{
uart_putchar(Iap_Pack_OK);
}
}
void Fill_Tb (unsigned int dat, unsigned int addr)
{
asm("movw R30,R18");
asm("movw R0,R16");
asm("ldi R16,0x01");
asm("sts 0x57,R16");
asm("spm");
while(SPMCR&(1<<SPMEN));
}
void Erase_Page (unsigned int addr)
{
asm("movw R30,R18");
asm("ldi R16,0x03");
asm("sts 0x57,R16");
asm("spm");
while(SPMCR&(1<<SPMEN));
}
void Prog_Page (unsigned int addr)
{
asm("movw R30,R18");
asm("ldi R16,0x05");
asm("sts 0x57,R16");
asm("spm");
while(SPMCR&(1<<SPMEN));
}
#pragma ctask Iap
void Iap (void)
{
unsigned char counter,IapStatu,CheckSum, i;
unsigned char IapBuffer;
union Char_Int Iap_dat,Iap_addr;
CLI(); //整个IAP过程中都将禁止中断
DDRC = (1<<5); //PC5端口上的发光二极管闪烁以指示IAP状态
// uart0_init(); //重新初始化串口模块
IapStatu = 1; //进入IAP状态
// uart_putchar('b') ;
// Iap_OK();
while (IapStatu)
{
while(Iap_Receive() != 0xAA); //等待包头到来,包头不参与校验计算,可不存储
IapBuffer = Iap_Receive(); //接收包长度字节
for (counter = 0 ; counter < (IapBuffer-2) ; counter++)
{
IapBuffer = Iap_Receive(); //依长度字节指示,循环接收所有数据
}
/*
if(CmdByte==0x09)
{
IapStatu = 0;
continue;
}
*/
CheckSum = 0;
for (i = 0 ; i < (IapBuffer-2) ; i++)
{
CheckSum ^= (IapBuffer);
}
/*
for (i = 0 ; i < (IapBuffer-2) ; i++)
{
uart_putchar(IapBuffer);
}
*/
// CheckSum ^= (IapBuffer-2]);
//uart_putchar('a') ;
if (CheckSum!= 0x00)
{
continue; //校验失败,返回等待下一次通讯
}
// uart_putchar('c') ;
if (CmdByte != 'P') //接到退出下载命令,退出IAP状态 'P'=0x50
{
// uart_putchar('d') ;
IapStatu = 0;
continue;
}
Iap_OK();
Iap_addr.chr_dat = PageAddrH;
Iap_addr.chr_dat = PageAddrL;
for(counter = 0 ; counter < 64 ; counter++) //缓冲页面填充
{
Iap_dat.chr_dat = IapBuffer[(counter*2)+4];
Iap_dat.chr_dat = IapBuffer[(counter*2)+5];
Fill_Tb(Iap_dat.Int_dat, (unsigned int)(Iap_addr.Int_dat+(counter*2)));
}
Erase_Page(Iap_addr.Int_dat); //页面擦除
Prog_Page(Iap_addr.Int_dat); //页面写入
// uart_putchar('c') ;
// break;
}
uart_putchar('b') ;
asm("rjmp __start"); //软件实现的从新启动
} 难道没人喜欢IAP下载程序?那我自己坐沙发了。{:victory:}一定会调试通过的。 1、你不能说通讯成功了就是写Flash成功了
2、调试的时候是否检查过跳转到应用区的汇编是正确的
3、书中介绍的的IAP写法并不是最优的--以现在的眼光看来。
回头我给你看Snail Bootloader的工程
页:
[1]