搜索
bottom↓
回复: 2

求助:深入浅出AVR(IAP移植),谢谢

[复制链接]

出0入4汤圆

发表于 2012-12-18 15:09:56 | 显示全部楼层 |阅读模式
硬件:mega16L  软件:ICC6.31
1、我使用书中的例程(boot基础事例程序)改写成mega16的程序,读取flash,可以看到flash被改写成“串口数据包计算助手”生成的数据。
但我,根据例程(实例18_ATmega48在线程序更新_闪烁方式1)修改后,mega48在线下载后台软件可以下载成功程序,但程序运行的不是IAP下载的程序。不知道是怎么回事。
谢谢。

程序如下:
#include "iom16v.h"
#include "macros.h"

#define  mclk   16000000

#define Con_true        1
#define CmdByte IapBuffer[1]
#define PageAddrL IapBuffer[2]
#define PageAddrH IapBuffer[3]

void Iap (void);

union Char_Int
{
        unsigned char chr_dat[2];
        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[5];
    unsigned char i;
   
    Iap_Pack_OK[0] = 0xAA;
    Iap_Pack_OK[1] = 0x05;
    Iap_Pack_OK[2] = 0x50;
    Iap_Pack_OK[3] = 0x55;
    Iap_Pack_OK[4] = 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[1800];
        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[0] = Iap_Receive();               //接收包长度字节

        for (counter = 0 ; counter < (IapBuffer[0]-2) ; counter++)
        {
            IapBuffer[counter+1] = Iap_Receive();       //依长度字节指示,循环接收所有数据
        }
                /*
        if(CmdByte==0x09)
                {
            IapStatu = 0;
            continue;
                }
                */
        CheckSum = 0;
        
        for (i = 0 ; i < (IapBuffer[0]-2) ; i++)
        {
            CheckSum ^= (IapBuffer);
        }
                /*
        for (i = 0 ; i < (IapBuffer[0]-2) ; i++)
    {
       uart_putchar(IapBuffer);
    }
        */
       
       // CheckSum ^= (IapBuffer[IapBuffer[0]-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[CHAR_H] = PageAddrH;
            Iap_addr.chr_dat[CHAR_L] = PageAddrL;

            for(counter = 0 ; counter < 64 ; counter++)     //缓冲页面填充
            {     
                    Iap_dat.chr_dat[CHAR_L] = IapBuffer[(counter*2)+4];
                    Iap_dat.chr_dat[CHAR_H] = 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");                                //软件实现的从新启动
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入4汤圆

 楼主| 发表于 2012-12-19 01:06:36 | 显示全部楼层
难道没人喜欢IAP下载程序?那我自己坐沙发了。一定会调试通过的。

出0入296汤圆

发表于 2012-12-19 02:00:12 | 显示全部楼层
1、你不能说通讯成功了就是写Flash成功了
2、调试的时候是否检查过跳转到应用区的汇编是正确的
3、书中介绍的的IAP写法并不是最优的--以现在的眼光看来。

回头我给你看Snail Bootloader的工程
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 14:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表