avr的bootloader问题

等待巴蒂   2010-6-29 18:44 楼主
这个通过串口自升级应用程序的问题我弄了好久,还是不能往flash里面写入数据。求各位大虾帮忙!assembly.h文件:
void write_page (unsigned int adr, unsigned char function);
void fill_temp_buffer (unsigned int data,unsigned int adr);
unsigned int read_program_memory (unsigned int adr,unsigned char cmd);
void write_lock_bits (unsigned char val);
void enableRWW(void);


assembly.s文件内容:
        .text
               
;*********************************************************
; Place a 1 for the processor you want use
;*********************************************************

MEGATYPE8   =  0
MEGATYPE16  =  0
MEGATYPE32  =  0
MEGATYPE64  =  0
MEGATYPE128 =  1
MEGATYPE162 =  0
MEGATYPE169 =  0
MEGATYPE8515 = 0
MEGATYPE8535 = 0
MEGATYPE2313 = 0
MEGATYPE48   = 0
MEGATYPE88   = 0
MEGATYPE168  = 0
MEGATYPE165  = 0
MEGATYPE3250 = 0
MEGATYPE6450 = 0
MEGATYPE3290 = 0
MEGATYPE6490 = 0
MEGATYPE406  = 0
MEGATYPE640  = 0
MEGATYPE1280 = 0
MEGATYPE2560 = 0
MEGATYPE1128 = 0  

;*********************************************************
;*********************************************************
;*********************************************************
;*********************************************************
; DO NOT CHANGE ANYTHING BELOW THIS LINE !!!!!!!
;*********************************************************
;*********************************************************
;*********************************************************
;*********************************************************

.if MEGATYPE64 | MEGATYPE128
    SPMCR = 0x68
.else
    SPMCR = 0x57
.endif

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

; 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        ;move address to 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 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
.if MEGATYPE128
    ELPM    r16, Z+         ;read LSB
    ELPM    r17, Z          ;read MSB
.else
    LPM     r16, Z+
    LPM     r17, Z
.endif
    RET
       
;-----------------------------------------

;void write_lock_bits (unsigned char val);
_write_lock_bits::
     MOV     R0, R16   
     LDI     R17, 0x09     
     STS     SPMCR, R17
     SPM                ;write lockbits
     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
       
;-----------------------------------------


uart.h文件内容:
void port_init(void);
void timer0_init(void);
void uart0_init(void);
void init_devices(void);
void PutString(unsigned char *str,unsigned char n);

uart.c文件内容:
//ICC-AVR application builder : 2010-6-20 下午 08:43:47
// Target : M128
// Crystal: 7.3728Mhz

#include
#include

unsigned char data;
unsigned char uart_event=0;
unsigned char timer2_event=0;
static unsigned char timeNum=0;
void port_init(void)
{
PORTA = 0x00;
DDRA  = 0x00;
PORTB = 0x00;
DDRB  = 0x00;
PORTC = 0x00; //m103 output only
DDRC  = 0x00;
PORTD = 0x00;
DDRD  = 0x00;
PORTE = 0x00;
DDRE  = 0x00;
PORTF = 0x00;
DDRF  = 0x00;
PORTG = 0x00;
DDRG  = 0x00;
}



//UART0 initialize
// desired baud rate: 2400
// actual: invalid baud rate
// char size: 8 bit
// parity: Even
void uart0_init(void)
{
UCSR0B = 0x00; //disable while setting baud rate
UCSR0A = 0x00;
UCSR0C = 0x26;
UBRR0L = 0xbf; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi
UCSR0B = 0x98;
}

//TIMER0 initialize - prescale:Stop
// WGM: Normal
// desired value: 1mSec
// actual value: Out of range

void timer0_init(void)
{
TCCR0 = 0x00; //stop
ASSR  = 0x00; //set async mode
TCNT0 = 0x00;/*INVALID SETTING*/ //set count
OCR0  = 0xff;/*INVALID SETTING*/
TCCR0 = 0x17; //start timer
}

//TIMER2 initialize - prescale:1024
// WGM: CTC
// desired value: 1Sec
// actual value: Out of range
void timer2_init(void)
{
TCCR2 = 0x00; //stop
TCNT2 = 0x00; /*INVALID SETTING*/ //setup
OCR2  = 0xff;/*INVALID SETTING*/
TCCR2 = 0x00; //start//shut down time2
}
#pragma interrupt_handler timer2_comp_isr:10
void timer2_comp_isr(void)
{
//compare occured TCNT2=OCR2
TCNT2 = 0x00;
//PutString("timer2_interrut\n",17);

if(timeNum>10)
{
  timer2_event=1;
}
timeNum++;
}

#pragma interrupt_handler uart0_rx_isr:19
void uart0_rx_isr(void)
{
//uart has received a character in UDR
data=UDR0;
TCCR2 = 0x00;
TCNT2 = 0x00;   
uart_event=1;
timeNum=0;
}
/*
#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{
TCNT0 = 0x00 ; //reload counter value
}*/

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
XDIV  = 0x00; //xtal divider
XMCRA = 0x00; //external memory
port_init();
timer0_init();
uart0_init();

MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EICRB = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 0x00; //timer interrupt sources
TIMSK|=0x80;
ETIMSK = 0x00; //extended timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}

/********************************************
//function:      DelayIR()
//input:tt:      ms want to delay
//output:        NULL
//Describtion:
*********************************************/
void DelayIR(unsigned int tt)
{
    unsigned char i;

    while(tt--)
{
     for (i=8000; i>0; i--)
  {
      asm(" nop");      
  }
}
}
void PutString(unsigned char *str,unsigned char n)
{
unsigned char i;
for(i=0;i {
  UDR0=str;
  while(!(UCSR0A&0x40));
  UCSR0A|=0x40;
}
}
main.c文件内容:
#include "uart.h"

#include "assembly.h"
#include
#include

#define SPM_PAGESIZE 128  //flash的每页的大小为128字节

void WriteFlash(void);
void quit(void);


unsigned int address=0x0080;
extern unsigned char data;
extern unsigned char uart_event;
extern unsigned char timer2_event;
unsigned char f_data[128];

void WriteFlash(void)
{
unsigned int i;
unsigned int temp;

for(i=0;i {
  temp=f_data+f_data[i+1];
  fill_temp_buffer(temp,i);
}
write_page(address,0x03);
write_page(address,0x05);

enableRWW();
}


void quit(void)
{
  while(!(UCSR0A & 0x20));       //等待结束提示信息回送完成
  MCUCR = 0x01;
  MCUCR = 0x00;             //将中断向量表迁移到应用程序区头部
  RAMPZ = 0x00;             //RAMPZ清零初始化
  asm("jmp 0x0000\n");     //跳转到Flash的0x0000处,执行用户的应用程序
}


void main(void)
{  
   unsigned char num;
   unsigned char dataCount=0;
   unsigned char timecount=0;
   
   init_devices();
   DelayIR(1000);
   PutString("input U to update!\n",20);
   while(1)
   {
           if(data=='u')
        {
         uart_event=0;
         break;
        }
         if(TIFR & 0x02)
         {
         if(timecount>200)         
         {
           quit();
         }
         
         TIFR|=0x02;
         timecount++;
         }
   }
   while(1)
   {
       
        if(uart_event==1&&timer2_event==0)
         {
          f_data[dataCount]=data;
          uart_event=0;
          TCCR2 = 0x05;  //打开定时器2

         if(dataCount>=SPM_PAGESIZE)
          {
           PutString("NEW\n",4);
           WriteFlash(); //收到256字节写入一页Flash中
       address += SPM_PAGESIZE;          //Flash页加1
       memset(f_data,128,0);
           dataCount=0;
          }
          dataCount++;
          }
          if(timer2_event==1&&dataCount>0)
          {
           PutString("timer2A\n",8);
           PutString("spm_over\n",10);
           WriteFlash();     //收到256字节写入一页Flash中
           PutString("quitA\n",6);
           quit();
          }
          if(timer2_event==1)
          {
           quit();
          }
  }
}

回复评论 (7)

熔丝位我设定为:
EXTENDED=0xFF
HIGH=0xdd
LOW=0xFF。
串口波特率为2400,奇校验。数据位8位
点赞  2010-6-29 18:46
望哪位大哥帮我解决这个问题呀!
点赞  2010-6-29 18:46
木有人呀?除了熔丝位,还有别的什么需要设置的么?木有人来救救我呀!
点赞  2010-6-30 09:20
帮你顶

我不熟悉avr , avr 没有官方的demo 么?

写入flash 前,要擦除flash,好像没看到你擦
点赞  2010-6-30 10:04

6楼 nec 

已经有擦除了。在writeflash函数里面有擦除
点赞  2010-6-30 10:26
flash的缓冲区在什么地方?flash里面还是ram里面?每次写一个字还是一个字节?
点赞  2010-6-30 15:49
楼主解决了吗?我的也是写不进去。不知道是什么问题
点赞  2017-8-5 17:09
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复