打印
[AVR单片机]

[转]AVR自编程(mega128)Bootloader程序

[复制链接]
5540|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laslison|  楼主 | 2010-4-10 21:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
该程序需要自己做上位机,思路是mega128复位后从Bootload区启动, 运行Bootload区的程序,判断串口有在规定时间内有没有收到升级指令,如果收到,则进入编程模式,否则跳到0x0000处执行应用程序。 ( 芯片从Bootload区启动,这个是要烧写芯片配置位的,因为新买的芯片好像是从0x0000处开处执行的,),
程序没有经过整理,比较乱,分两个文件,一个asm文件,一个C文件

asm文件



.text

SPMCR = 0x68 ;RWW区忙标志,读RWW区允许,允许写程序存储区

; void write_page (unsigned int adr, unsigned char function);
; bits 8:15 adr addresses the page...(must setup RAMPZ beforehand!!!)
_write_page::
XCALL __WAIT_SPMEN__
movw r30, r16 ;z pointer (R31 = ZH, R30 = ZL)
STS SPMCR, R18 ;argument 2 decides function
SPM ;perform pagewrite
RET

;-----------------------------------------

; void fill_temp_buffer (unsigned int data, unsigned int adr);
; bits 7:1 in adr addresses the word in the page... (2=first word, 4=second word etc..)
_fill_temp_buffer::
XCALL __WAIT_SPMEN__
movw r30, r18 ;move adress to z pointer (R31=ZH R30=ZL)
movw r0, r16 ;move data to reg 0 and 1
LDI R19, 0x01
STS SPMCR, R19
SPM ;Store program memory
RET

;-----------------------------------------

;unsigned char read_flash(unsigned int add);
_read_flash::
mov r31,r17
mov r30,r16
lpm r16,z
clr r17
ret

;unsigned int read_program_memory (unsigned int adr ,unsigned char cmd);
_read_program_memory::
movw r30, r16 ;move adress to z pointer
SBRC R18, 0 ;read lockbits? (second argument = 0x09)
STS SPMCR, R18 ;if so, place second argument in SPMEN register
LPM r16, Z+
LPM r17, Z
RET

;-----------------------------------------

_enableRWW::
XCALL __WAIT_SPMEN__
LDI R27,0x11
STS SPMCR,R27
SPM
RET

;-----------------------------------------

__WAIT_SPMEN__:
LDS R27,SPMCR ; load SPMCR to R27
SBRC R27,0 ; check SPMEN flag
RJMP __WAIT_SPMEN__ ; wait for SPMEN flag cleared
RET

;-----------------------------------------





C文件

asm头文件就没有贴了,就是函数定义





/******************************************************************************
bootload area : 1K BOOTSZ1=1,BOOTSZ0=0 (1表示未编程,0表示已编程)
配置: SUT0=0,SUT1=1()
CKSEL0=0,CKSEL0=1,CKSEL0=1,CKSEL0=1 (外部时钟)
/*****************************************************************************/
#include <macros.h>
#include "asm.h"
#include "iom128v.h"

//芯片类型
#define ChipType Atmega128
//*********************************************************
//选择BOOT区大小
#define BootSize Ɖ'
//1024

//选择BootLoad版本号
#define BootVer Ƈ'
//1.0版本

//**********************************************************
//7.3728时钟下的波特率设置
#define BAUDRATE 25 //51 9600 //12 38400 [url=]//7@57600[/url] [url=]//3@115200[/url]
//3#115200
//*****************************************************************************
#define PageByte 256


void FlashLoad (void);
unsigned char GetPageNumber (void);
void ExecCode (void);
char GetPage (void);
void WriteFlash (void);
char CheckFlash (void);
void SendChar (unsigned char c);
void delay (void); //1ms延时函数
unsigned char RecChar (void);

unsigned char PageBuffer[PageByte];
long PageAddress;
unsigned int nTimeOut; //接收超时计数器



/*****************************************************************************/
//Flash编程
/*****************************************************************************/
void FlashLoad(void)

SendChar('!');
while (1)

if(GetPageNumber()==0) return;//接收不超时则为1,超时为0

if (GetPage())

WriteFlash();
if (CheckFlash()) SendChar('!');
else SendChar('@');

else

SendChar('@');
return;




/*****************************************************************************/
unsigned char GetPageNumber(void)

unsigned char PageAddressH;
unsigned char PageAddressL;
unsigned int OUT;
nTimeOut=0;
PageAddressH = RecChar();

// PageAddressL = RecChar();
while(!(UCSR0A & 0x80))

nTimeOut++;
if(nTimeOut>60000)//接收第二个字节有超时限制
return 0;

PageAddressL=UDR0;

// PageAddressL=RecChar();
if (PageAddressH) RAMPZ = 1;
else RAMPZ = 0;

OUT=(int)((PageAddressH << 8) + PageAddressL);
if(OUT==0xffff) return 0; //判断如果页地址大于1FF则退出
PageAddress=((int)((PageAddressH << 8) + PageAddressL))<<8;
return 1;


/*****************************************************************************/
char GetPage(void)

unsigned int i;
unsigned char LocalCheckSum = 0;
unsigned char CheckSum = 0;

for (i=0;i<256;i++) //接收一个页面数据

while(!(UCSR0A & 0x80))

nTimeOut++;
if(nTimeOut>60000)//接收有超时限制
return 0;


PageBuffer=UDR0;
LocalCheckSum += PageBuffer;


CheckSum = RecChar();
// SendChar(CheckSum);
// SendChar(LocalCheckSum);
if (LocalCheckSum == CheckSum) return 1;
else return 0;


/*****************************************************************************/
//写一个页面
void WriteFlash(void)

unsigned int i;
unsigned int TempInt;


for (i=0;i<256;i+=2)

TempInt=PageBuffer+(PageBuffer[i+1]<<8);
fill_temp_buffer(TempInt,i);



write_page(PageAddress,0x03); //擦除页
write_page(PageAddress,0x05); //写页数据
enableRWW();


/****************************************************************************/
// 校验FLASH,

char CheckFlash(void)

unsigned int i;
unsigned int TempInt;
unsigned int TempInt2;

for (i=0;i<256;i+=2)

TempInt = read_program_memory(PageAddress + i,0x00);
TempInt2 = PageBuffer +(PageBuffer[i+1]<<8);
if (TempInt != TempInt2) return 1;

return 1;


/*****************************************************************************/
/* 字符输入函数 */
unsigned char RecChar(void)

while(!(UCSR0A & 0x80));
return UDR0;


/*****************************************************************************/
/* 字符输入函数带超时标志 */
unsigned char RecChar_T(void)

while(!(UCSR0A & 0x80))

nTimeOut++;
if(nTimeOut>10000)//
return 0;

return UDR0;




/*****************************************************************************/
void SendChar(unsigned char c)

while (!(UCSR0A&0x20));// wait for empty transmit buffer
UDR0=c;

void delay(void)

unsigned int i;
for (i=0;i<65530;i++);


/*****************************************************************************/
void ExecCode(void)


RAMPZ = 0; //选中前64K
MCUCR=0X01; //中断向量表移位允许
MCUCR=0X00; //中断向量指向应用程序区
asm("jmp 0x0000");

/********************************************************************
系统时钟8M的毫秒级延时函数
********************************************************************/
void Delay_1ms(void) //1ms延时函数

unsigned int i;
for (i=0;i<7680;i++);


void Delay_nms(unsigned int n) //N ms延时函数

unsigned int i=0;
for (i=0;i<n;i++)

Delay_1ms();





void main(void)


UCSR0C=0x86; //8位数据+1位停止
UCSR0B = 0x18; //允许串口发送和接收
UBRR0H = 0x00;
UBRR0L = BAUDRATE; //设置波特率

SendChar('>'); //通知PC机,BOOT下载准备就绪
delay(); //延时等待
while (1)

switch (RecChar_T()) //等待接收命令,时间需要修改

case 'W':
FlashLoad();
SendChar('K');
break;
case 'E':
SendChar('E'); //通知PC机,进入运用程序区
Delay_1ms();
ExecCode(); //退出bootloader
break;
case '<':
SendChar(ChipType);
SendChar(BootSize);
SendChar(BootVer);
break;
default :
break;


相关帖子

沙发
麻辣鸭脖子| | 2010-4-10 22:09 | 只看该作者
不错,顶了

使用特权

评论回复
板凳
虎虎生威| | 2010-4-10 22:19 | 只看该作者
收藏了

使用特权

评论回复
地板
laslison|  楼主 | 2010-4-15 16:28 | 只看该作者
:)

使用特权

评论回复
5
几米时代| | 2010-4-15 17:34 | 只看该作者
顶了!

使用特权

评论回复
6
fenglifeng1987| | 2010-5-15 16:35 | 只看该作者
make

使用特权

评论回复
7
chuxh| | 2010-5-15 20:39 | 只看该作者
好长的程序……

使用特权

评论回复
8
smckay| | 2013-8-20 11:42 | 只看该作者
貌似看到SPEC講到BL也可以升級

使用特权

评论回复
9
smckay| | 2013-8-20 11:42 | 只看该作者
可以嘗試一下

使用特权

评论回复
10
wmslecz| | 2014-10-5 21:32 | 只看该作者
非常不错..顶一个..

使用特权

评论回复
11
anran莫莫| | 2014-10-9 13:56 | 只看该作者

使用特权

评论回复
12
afei9527| | 2014-10-21 17:53 | 只看该作者
非常不错..顶一个..

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

791

帖子

1

粉丝