搜索
bottom↓
回复: 8

atmega 64 boot编程(附图)

[复制链接]

出0入0汤圆

发表于 2009-9-15 16:02:01 | 显示全部楼层 |阅读模式
/* 编译器:iccavr 6.31a
   M C U : ATmega64
   功 能 :将一个40*12的数组数据写入flash中
遇到的问题:1:程序运行后,40*12这个数组的数据确实能写入flash中,但是写入的地址不管我怎么改,都是从0x0050开始的,如下图 ;
            2:调用读flash函数,无法读出数据(读flash函数正确,我用其他方法验证过) ;
程序不长,如下,希望能够得到指点,非常感谢!!!
*/

#pragma abs_address:0xe000   //绝对地址定位到boot区

#include <iom64v.h>
#include <macros.h>

#define uchar        unsigned char
#define uint        unsigned int

#define PAGESIZEW                  128   //M16的一个Flash页为256字节(128字)
#define PAGESIZEB                  256   //M16的一个Flash页为256字节(128字)
                                          
//擦除(code=0x03)和写入(code=0x05)一个Flash页
void boot_page_ew(uint p_address,uchar code)
{
    asm("mov r30,r16");
    asm("mov r31,r17");
        asm("out 0x3b,r18");            //将页地址放入Z寄存器和RAMPZ的Bit0中
    SPMCSR = code;                //寄存器SPMCSR中为操作码
    asm("spm\n");                    //对指定Flash页进行操作
        //asm("ret");
}

//填充Flash缓冲页中的一个字
void boot_page_fill(uint address,uint data)
{
    asm("mov r30,r16");
    asm("mov r31,r17");            //Z寄存器中为填冲页内地址
    asm("mov r0,r18");
    asm("mov r1,r19");            //R0R1中为一个指令字
    SPMCSR = 0x01;
    asm("spm\n");
        //asm("ret");
}

//等待一个Flash页的写完成
void wait_page_rw_ok(void)
{
   while(SPMCSR & 0x40)
     {
         while(SPMCSR & 0x01);
         SPMCSR = 0x11;
         asm("spm\n");
                 //asm("ret");
     }
}

//更新一个Flash页的完整处理
void write_one_page(uint address,uchar data[])
{
    uint i;
        uint da[PAGESIZEW];
        uchar j;
    boot_page_ew(address,0x03);                    //擦除一个Flash页
    wait_page_rw_ok();                            //等待擦除完成
    for(i=0,j=0;i<PAGESIZEB;i+=2,j++)                //将数据填入Flash缓冲页中
    {   
            da[j] = data[i+1];
                da[j] = data+ (da[j] <<8 );
        boot_page_fill(i,da[j]);
    }
    boot_page_ew(address,0x05);                    //将缓冲页数据写入一个Flash页
    wait_page_rw_ok();                            //等待写入完成
}

uchar read_flash(uint address)    //从flash中读取一字节
{
  asm("mov r30,r16");
  asm("mov r31,r17");
  asm("lpm r16,z");
  //asm("ret");
}
#pragma end_abs_address  //结束绝对地址定位

#include <eeprom.h>
uint ADDRESS[10] = {0x0000,0x0200,0x0400,0x0600,0x0800,0x0A00,0X0C00,0X0E00,0X1000,0X1200}; //10页flash的首地址
uchar DATA[40][12] = {
        {0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11},
            {12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23},
                {24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35},  
                {36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47},
                {48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59},  
                {60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71},  
                {72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83},  
                {84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95},
                {96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107},
                {108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
                {120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131},
                {132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143},
                {144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155},
                {156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167},
                {168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179},
                {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191},
                {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203},
                {204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215},
                {216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227},
                {228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239},
                {0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,  11},
            {12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23},
                {24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35},  
                {36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47},
                {48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59},  
                {60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71},  
                {72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83},  
                {84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95},
                {96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107},
                {108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
                {120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131},
                {132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143},
                {144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155},
                {156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167},
                {168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179},
                {180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191},
                {192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203},
                {204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215},
                {216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227},
                {228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239}
                      };     //待写入的数据
                                          
uchar data1[40][12];   //读出数据存储


void write_one_xg(uint address,uchar data[40][12])
{
  uint i;
  uchar da1[PAGESIZEB];
  uchar j=0,k=0;
  for(i=0;i<240;i++)
    {
          da1 = data[j][k];
          k++;
          if(k>=12)
            {
                  k = 0;
                  j++;
                }
        }

  write_one_page(address,da1);
  address = address + 256;
  j = 20;k=0;
  for(i=0;i<240;i++)
    {
          da1 = data[j][k];
          k++;
          if(k>=12)
            {
                  k = 0;
                  j++;
                }
        }

  write_one_page(address,da1);
}

uchar read_one_xg(uint address,uchar data[40][12])
{
  uint i;
  uchar j=0,k=0;
  for(i=0;i<240;i++)
    {
      data[j][k] = read_flash(address+i);
          k++;
          if(k >=12) {j++;k =0;}
        }
       
  j=20;k=0;       
  for(i=0;i<240;i++)
    {
      data[j][k] = read_flash(address+i);
          k++;
          if(k >=12) {j++;k =0;}
        }        
}  

void main()
{
uint i;
CLI();
MCUCR = 0x00;
TIMSK = 0x00;
SEI();

write_one_xg(ADDRESS[1],DATA);
read_one_xg(ADDRESS[1],data1);

while(1);
}

程序运行后flash存储状况 (原文件名:QQ截图未命名.jpg)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-9-16 08:14:16 | 显示全部楼层
已经解决了

出0入0汤圆

发表于 2009-9-16 09:27:37 | 显示全部楼层
咋解决的啊,说说哈!

出0入0汤圆

 楼主| 发表于 2009-9-23 15:08:10 | 显示全部楼层
以上程序是对的,只要设置编译器program type :application ;boot:none 就行了

出0入0汤圆

发表于 2010-4-27 13:39:36 | 显示全部楼层
#pragma abs_address:0xe000   //绝对地址定位到boot区
是不是要定义到BOOT才能对应用程序区进行擦写啊?

出0入0汤圆

 楼主| 发表于 2010-4-27 15:44:28 | 显示全部楼层
应该是的,这段代码要在boot区才有效。

出0入0汤圆

发表于 2010-4-28 14:18:47 | 显示全部楼层
那我应用程序升级不是只有在BOOT区才能升级吗?

出0入0汤圆

 楼主| 发表于 2010-4-29 13:07:43 | 显示全部楼层
应用程序升级是通过调用boot区代码来实现的。

出0入0汤圆

发表于 2010-5-8 12:22:21 | 显示全部楼层
我要在应用程序运行时候,将更新应用程序代码写到应用区的高64k中,更新完成再到boot中从高64k的代码更新到低64k应用区。怎么处理啊!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-16 14:58

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

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