mingtao8868 发表于 2007-12-29 14:53:22

avr 引导程序

您好马潮老师! 我想用avr 的单片机做个仿真机,可是书上有一些引导程序的资料,但是还是没有搞明白,用汇编的程序老是编译不过。
希望马老师给点帮助意见。这是我的程序:我的QQ54709686,E-mail; mingtao8868@163.com
;- 本例程将RAM 中的一页数据写入Flash
; Y 指针指向RAM 的第一个数据单元
;Z 指针指向Flash 的第一个数据单元
;- 本例程没有包括错误处理
;- 该程序必须放置于Boot 区( 至少Do_spm 子程序是如此)
; 在自编程过程中( 页擦除和页写操作) 只能读访问NRWW 区的代码
;- 使用的寄存器:r0、 r1、 temp1 (r16)、 temp2 (r17)、 looplo (r24)、
; loophi (r25)、 spmcrval (r20)
; 在程序中不包括寄存器内容的保护和恢复
; 在牺牲代码大小的情况下可以优化寄存器的使用
;- 假设中断向量表位于Boot loader 区, 或者中断被禁止。
.include "m16def.inc" ;引用器件I/O配置文件

;定义程序中使用的变量名(在寄存器空间)
.def spmcrval = r20 ;2ms到标志
.def temp2 = r17 ;临时变量
.def temp1 = r16 ;临时变量
.def looplo = r24 ;临时变量(中断中使用)
.def loophi = r25 ;临时变量(中断中使用)
.equ PAGESIZEB = PAGESIZE*2 ;PAGESIZEB 是以字节为单位的页大小,不是以字为单位
.org         $1E00
Write_page:
; 页擦除
        ldi spmcrval, (1<<PGERS) | (1<<SPMEN)
        call Do_spm
; 重新使能RWW 区
        ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
        call Do_spm
; 将数据从RAM 转移到Flash 页缓冲区
        ldi looplo, low(PAGESIZEB) ; 初始化循环变量
        ldi loophi, high(PAGESIZEB) ;PAGESIZEB<=256 时不需要此操作
Wrloop:
        ld r0, Y+
        ld r1, Y+
        ldi spmcrval, (1<<SPMEN)
        call Do_spm

        adiw ZH:ZL, 2
        sbiw loophi:looplo, 2   ;PAGESIZEB<=256 时请使用subi
        brne Wrloop
; execute page write
        subi ZL, low(PAGESIZEB) ; 复位指针
        sbci ZH, high(PAGESIZEB) ;PAGESIZEB<=256 时不需要此操作
        ldi spmcrval, (1<<PGWRT) | (1<<SPMEN)
        call Do_spm
; 重新使能RWW 区
        ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
        call Do_spm
; 读回数据并检查,为可选操作
        ldi looplo, low(PAGESIZEB) ; 初始化循环变量
        ldi loophi, high(PAGESIZEB) ;PAGESIZEB<=256 时不需要此操作
        subi YL, low(PAGESIZEB) ; 复位指针
        sbci YH, high(PAGESIZEB)
Rdloop:
        lpm r0, Z+
        ld r1, Y+
        cpse r0, r1
        jmp Error
        sbiw loophi:looplo, 1 ;PAGESIZEB<=256 时请使用subi
        brne Rdloop
; 返回到RWW 区
; 确保RWW 区已经可以安全读取
Return:
        in temp1, SPMCR
        sbrs temp1, RWWSB ; 若RWWSB 为"1",说明RWW 区还没有准备好
        ret

; 重新使能RWW 区
        ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
        call Do_spm
        rjmp Return
Do_spm:
; 检查先前的SPM 操作是否已经完成
Wait_spm:
        in temp1, SPMCR
        sbrc temp1, SPMEN
        rjmp Wait_spm
; 输入:spmcrval 决定了SPM 操作
; 禁止中断,保存状态标志
        in temp2, SREG
        cli
; 确保没有EEPROM 写操作
Wait_ee:
        sbic EECR, EEWE
        rjmp Wait_ee
; SPM 时间序列
        out SPMCR, spmcrval
        spm
; 恢复SREG ( 如果中断原本是使能的,则使能中断)
        out SREG, temp2
        ret

machao 发表于 2007-12-29 17:38:13

关于这些内容,在我编写的<M128>一书中第五章中有实例介绍.
页: [1]
查看完整版本: avr 引导程序