文章
博客 网店

 AVR单片机Flash自编程(当EEPROM使用)


AVR单片机在程序中写flash时必须从Flash中NRWW区执行写操作,页一般的用户程序都在RWW区,为此要在应用中写flash需要将写flash相关函数定位到NRWW区;

下面是一种应用案例,在bootloader程序中提供一个函数用于写flash页,在用户程序中调用;代码如下:

//用户程序写flash页接口函数 
//注:在makefile中指定.mysection段的开始地址,在用户程序中调用时函数地址为此指定地址除2
//注意该函数不能使用全局变量
void AppWriteFlashPage(uint32_t,uint8_t*) __attribute__((section(".mysection")));
void AppWriteFlashPage(uint32_t addr,uint8_t *buf)
{
  uint16_t j;
  uint16_t i;
  
  for(i=0;i   {
    //  页擦除操作
    boot_page_erase(addr);
    boot_spm_busy_wait ();//等待擦除完成
          
    //  填充缓冲页
    for(j = 0; j < DEV_PAGE_SIZE; j += 2)
        boot_page_fill((unsigned long)j,*((uint16_t *)(buf+i+j)));  
    
    //  页写操作  
    boot_page_write(addr);     // Store buffer in flash page.
    boot_spm_busy_wait();       // Wait until the memory is written.

    boot_rww_enable ();        // Reenable RWW-section again.        
  }  
  
}

该函数根据参数指定地址写入一个页到flash,定位是通过自定义段.mysection来实现的,在makefile中连接选项增加:

LDFLAGS += -Wl,--section-start=.mysection=0x1E670

这个地址可以是在nrww区内的任意地址,在本项目中我选择了一个boot未占用的地址0x1E670,


测试程序如下:

//mcu:atmega128 clk:11059200Hz
#include "avr/io.h"
#include 
#include "util/delay.h"
#include "string.h"

#define LED_TOGGLE PORTB^=_BV(PB6)

void (*WriteFlashPage)(uint32_t,uint8_t*)= 0xf338;//boot程序中将该函数定位到:0x1e670(RWW区写flash函数)

uint8_t g_Buffer[512];

void DelayMs(uint16_t t)
{
  uint16_t i;
  for(i=0;i   {
      _delay_loop_2(8*250);
  }
}

#define UART_BAUD 9600

void SendChar(uint8_t c)
{
    while(!(UCSR0A & (1<     UDR0=c;
}

int main(void)
{
  uint16_t i;
  uint32_t addr;
  uint8_t c;
  
  //IO口初始化
  DDRB=_BV(PB6); //LED
  
  //USART 初始化
  UBRR0H=((F_CPU/UART_BAUD/16)-1)/256;
  UBRR0L=((F_CPU/UART_BAUD/16)-1)%256;
  UCSR0B=_BV(TXEN0);
  
  DelayMs(1000);
  SendChar(0xBB);
  
  memset(g_Buffer,0x55,512);
    
  WriteFlashPage(0x10000,g_Buffer);  //0x10000为64k处
  
  memset(g_Buffer,0,512);
  
  DelayMs(5000);
  
  //读取并打印到串口
  addr=0x10000;
  for(i=0;i<50;i++)
  {
    c=pgm_read_byte_far(addr++);
    SendChar(c);
  }

  while(1)
  {
    DelayMs(500);
    LED_TOGGLE;
  }
}



注意bootloader和用户程序是分别编译的,该测试同时展示了不同的两个项目之间调用函数的方法。

芯艺工作室    蒙ICP备06005492号
Copyright© 2004-2025 ChipArt Studio All Rights Reserved