原创 不同编译器对FLASH的操作

2009-8-26 19:27 2048 2 2 分类: MCU/ 嵌入式

1.  keil for MSC51


关键字code


code unsigned char array[8]={}


2.  IAR for AVR(摘抄)


FLASH常用类型的具体操作方法


(1) FLASH 区域数据存储。
用关键字 __flash 控制来存放, __ flash 关键字写在数据类型前后效果一样
__flash unsigned char a;//定义一个变量存放在flash空间
unsigned char __flash a;//效果同上
__flash unsigned char p[];//定义一个数组存放在flash空间
对于flash空间的变量的读操作同SRAM数据空间的操作方法一样,编译器会自动用
LPM,ELPM 指令来操作。
例:
#i nclude<iom8.h>
__flash unsigned char p[];
__flash unsigned char a;
void main(void)
{PORTB=p[1];// 读flash 数组变量的操作
PORTB=a;// 读flash 变量的操作
}
由于在正常的程序中,flash 空间是只读的,所以没有赋值的变量是没有意义的。定义常数在flash 空间,只要给变量赋与初值就可以了。由于常数在flash空间的地址是随机分配的,读取变量才可以读取到常数值。
IAR-AVR –C 编译器简要指南
__flash unsigned char a="9";//定义一个常数存放在flash空间。
__flash unsigned char p[]={1,2,3,4,5,6,7,8};
//定义一个组常数存放在flash 空间。
例:
#i nclude<iom8.h>
__flash unsigned char p[]={1,2,3,4,5,6,7,8};
__flash unsigned char a="9";
void main(void)
{
   PORTB="a";//读取flash 空间值9
   PORTC="p"[0]; //读取flash 空间值
}


(2)flash 空间绝对地址定位:
__flash unsigned char a @ 0x8;//定义变量存放在flash 空间0X08单元__flash unsigned char p[] @ 0x22//定义数组存放在flash 空间,开始地址为0X22单元
__flash unsigned char a @ 0x08=9;//定义常数存放在flash 空间0X08单元
__flash unsigned char p[] @ 0x22={1,2,3,4,5,6,7,8};
//定义一个组常数存放在EEPROM空间开始地址为0X22单元
由于常数在flash 空间的地址是已经分配的,读取flash 空间值可以用变量和地址。


(3) 与 __flash 有关的指针操作。 __flash 关键字控制指针的存放和类型。
指向flash 空间的SRAM指针(控制类型属性)
unsigned char __flash * p;//定义指向flash 空间地址的指针,8位。
unsigned int __flash * p;//定义个指向flash 空间地址的指针,16位。
unsigned int __farflash * p;//定义指向flash 空间地址的指针,24位。
unsigned int __hugeflash * p;//定义指向flash 空间地址的指针,24位。
unsigned char __flash * p;//定义一个指向flash 空间地址的指针,指针本身存放在SRAM中。P的值代表flash 空间的某一地址。*p表示flash 空间该地址单元存放的内容。例:假定p=10,表示flash空间地址10单元,而flash 空间10单元的内容就用*p来读取。
例:
#i nclude<iom8.h>
char __flash t @ 0x10 ;
char __flash *p ;
void main(void)
{
PORTB=*p;//读取flash 空间10单元的值
PORTB=*(p+3);//读取flash 空间0x13单元的值
}


存储于flash 空间的指针数据指针
就象存储与flash 空间的数据一样控制存储属性
__flash unsigned char * p; //定义指向SARMM空间地址的指针,指针本身存放在flash 中。


控制数据和指针存放的__flash 定义必须是全局变量,控制类型属性(好像只有指针)可以是局部变量。
#i nclude<iom8.h>
__flash unsigned char p;//控制存放
void main(void)
{
unsigned char __flash * t;//控制属性
PORTB=p;
PORTB=*t;
}


(4) __root 关键字保证没有使用的函数或者变量也能够包含在目标代码中.
定义存放在__flash 空间的数据在程序编译时会自动生成代码嵌入到flash代码中,对于程序没有使用也要求编译的数据(比如可以在代码中嵌入你的版本号,时间等)必须加关键字__root 限制。
例:
#i nclude<iom8.h>
__root __flash unsigned char p @ 0x10 =0x56;
void main(void)
{}
程序没有使用P变量,编译也会生成该代码。
:020000020000FC
:1000000016C018951895189518951895189518955F
:10001000569518951895189518951895189518953A
:10002000189518951895089500008895FECF0FE94A
:100030000DBF00E00EBFC0E8D0E003D0F4DFF4DF76
:06004000F3CF01E008957A
:0400000300000000F9
:00000001FF


(5)flash 操作宏函数:在comp_a90.h intrinsics.h头文件里有详细说明。flash 空间具正常情况下有只读性能,对于读flash 数据编译器会自动编译对应的LPM,ELPM指令,但对于flash 空间的自编程写命令SPM就没有对应的C指令了,这里不讲解详细的自编程方法,只是讲解一下对flash 的读写函数。
直接在程序中读取flash 空间地址数据:要包含intrinsics.h头文件
__load_program_memory(const unsigned char __flash *);//64K空间
//从指定flash 空间地址读数据。该函数在intrinsics.h头文件里有详细说明。
在comp_a90.h文件有它的简化书写_LPM(ADDR)。注意汇编指令LPM Rd ,Z中的Z是一个指针。所以用(const unsigned char __flash *)来强制转换为指向flash空间地址指针。故该条宏函数的正确写法应该如下:
__load_program_memory((const unsigned char __flash *)ADDR);
例:
#i nclude<iom8.h>
#i nclude <intrinsics.h>
void main(void)
{PORTB=__load_program_memory((const unsigned char __flash *)0x12);
}
该条函数书写不方便,在comp_a90.h文件有简化:
#define _LPM(ADDR) __load_program_memory (ADDR)稍微方便一点。改为
#define _LPM(ADDR) __load_program_memory ((const unsigned char
__flash *)ADDR)就更方便了,直接使用数据就可以了。
例:
#i nclude<iom8.h>
#i nclude<comp_a90.h>
#i nclude<intrinsics.h>
void main(void)
{
PORTB=__LPM(0x12);// 从指定flash 空间地址单元0x12中读数据
}
__extended_load_program_memory(const unsigned char __farflash *);
//128K空间_ELPM(ADDR); //128K空间
参照上面的理解修改可以书写更简单。


(6)自编程函数:
_SPM_GET_LOCKBITS();//读取缩定位
_SPM_GET_FUSEBITS();//读取熔丝位
_SPM_ERASE(Addr);//16位页擦除
_SPM_FILLTEMP(Addr,Word);//16位页缓冲
_SPM_PAGEWRITE(Addr;)//16位页写入
_SPM_24_ERASE(Addr); //24位页擦除
_SPM_24_FILLTEMP(Addr,Data); //24位页缓冲
_SPM_24_PAGEWRITE(Addr) //24位页写入


3. AVR GCC for AVR


AVR具有三种存储器:FLASH,SRAM和EEPROM。AVR-GCC将程序代码放在FLASH,数据放在SRAM。
(1).程序存储器
如果要将数据(如常量,字符串,等等)放在FLASH里,用户需要指明数据类型__attribute__((progmem))。为了方便使用,AVR-GCC定义了一些更直观的符号,如下表所示。包含在头文件pgmspace.h中


#include<avr/pgmspace.h>
类型 定义
prog_void void __attribute__((progmem))
prog_char char __attribute__((progmem))
prog_int int __attribute__((progmem))
prog_long long __attribute__((progmem))
prog_long_long long long __attribute__((progmem))
PGM_P const prog_char *
PGM_VOID_P prog_void const*


example code: m16 timer1 project


const char NumberCode[12] PROGMEM ={'K','e','y', ' ' , ' ' , ' ' ,'N','u','m','b','e','r'};


PGM_P pstr="NumberCode";            //FLASH内存的数据类型为char,pstr是指向FLASH的指针,其值是16位


pgm_read_byte(pstr++)          //读FLASH内的数据,pstr内容是FLASH 16地址
提供的库函数有:
1.__elpm_inline
用法:uint8_t __elpm_inline(uint32_t addr);
说明:执行ELPM指令从FLASH里取数。参数为32位地址,返回一个8位数据。
2.__lpm_inline
用法:uint8_t __elpm_inline(uint16_t addr);
说明:执行LPM指令从FLASH里取数。参数为16位地址,返回一个8位数据。
3.memcpy_P
用法:void* memcpy_P(void* dst, PGM_VOID_P src, size_t n);
说明:memcpy的特殊版本。完成从FLASH取n个字节的任务。
4.PRG_RDB
用法:uint8_t PGR_RDB(uint16_t addr);
说明:此函数简单地调用__lpm_inline
5.PSTR
用法:PSTR(s);
说明:参数为字符串。功能是将其放在FLASH里并返回地址。
6.strcmp_P
用法:int strcmp(char const*, PGM_P);
说明:功能与strcmp()类似。第二个参数指向程序存储器内的字符串。
7.strcpy_P
用法:char* strcpy_P(char*, PGM_P);
说明:功能与strcpy()类似。第二个参数指向程序存储器内的字符串。
8.strlen_P
用法:size_t strlen_P(PGM_P);
说明:功能与strlen()类似。第二个参数指向程序存储器内的字符串。
9.strncmp_P
用法:size_t strncmp_P(char const*, PGM_P, size_t);
说明:功能与strncmp()类似。第二个参数指向程序存储器内的字符串。
10.strncpy_P
用法:size_t strncpy_P(char*, PGM_P, size_t);
说明:功能与strncpy()类似。第二个参数指向程序存储器内的字符串。


(2).EEPROM
AVR内部有EEPROM,但地址空间与SRAM的不相同。在访问时必须通过I/O寄存器来进行。EEPROM API封装了这些功能,为用户提供了高级接口。使用时要包含eeprom.h。在程序里定义EEPROM数据的例子如下:
static uint8_t variable_x __attribute__((section(".eeprom"))) = 0;
不同的AVR器件具有不同数目的EEPROM。链接器将针对不同的器件分配存储器空间。
1. eeprom_is_ready
用法:int eeprom_is_ready(void);
说明:此函数用于指示是否可以访问EEPROM。如果EEPROM正在执行写操作,则在4ms内无法访问。此函数查询相应的状态位来指示现在是否可以访问EEPROM。
2. eeprom_rb
用法:uint8_t eeprom_rb(uint16_t addr);
说明:从EEPROM里读出一个字节的内容。参数addr用于指示要读出的地址。_EEGET(addr)调用此函数。
3. Eeprom_read_block
用法:void eeprom_read_block(void* buf, uint16_t addr, size_t n);
说明:读出一块EEROM的内容。参数addr为起始地址,n表明要读取的字节数。数据被读到SRAM的buf里。
4. eeprom_rw
用法:unint16_t eeprom_rw(uint16_t addr);
说明:从EEPROM里读出一个16位的数据。低字节为低8位,高字节为高8位。参数addr为地址。
5. eeprom_wb
用法:void eeprom_wb(uint16_t addr, uint8_t val);
说明:将8位数据val写入地址为addr的EEPROM存储器里。_EEPUT(addr,val)调用此函数。


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
2
关闭 站长推荐上一条 /3 下一条