搜索
bottom↓
回复: 19

WINAVR关于片内eeprom写操作的一个BUG。。。

[复制链接]

出0入0汤圆

发表于 2010-9-28 03:26:55 | 显示全部楼层 |阅读模式
今天被mega16片内eeprom烦了一天,程序错误莫名其妙。让我感到抓狂的是我的程序是直接复制了用户手册上的C程序。程序如下:(Page19)

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
while(EECR & (1<<EEWE));    /* 等待上一次写操作结束 */

EEAR = uiAddress;           /* 设置地址和数据寄存器*/

EEDR = ucData;              /* 置位EEMWE */

EECR |= (1<<EEMWE);         /* 置位EEWE 以启动写操作*/

EECR |= (1<<EEWE);
}

去网上找资料,多为推荐使用winavr自带的函数。后来反复修改编译烧写一度使我的M16擦写寿命少了一百多次,依然无果。

后来再仿真的时候,忽然发现EEMWE和EEWE永远不可能会同时置位,也就是说,EEWE置位永远在EEMWE清零之后。

不管改成 EECR |= (1<<EEMWE)|(1<<EEWE);还是将两者换位都不行;
(虽然资料上说在EEMWE置位后4个周期就会被清零,所以EEWE必须在EEMWE置位后立即将EEWE置位,但是大家注意上面的程序这两句是上下行的。。)

于是上网搜类似的情况,终于发现有位仁兄和我有同样的疑问 http://bbs.avrvi.com/simple/t16903.html

按照他的说法“于是变半信半疑的用AVR Simulator看看EECR|=_BV(EEWE)这条语句所消耗的时间,一看发现其用了5个时钟周期,这时我便豁然开朗了,但是我还是想不通为什么EECR|=_BV(EEWE)这条语句会要5个时钟周期这么长,于是便看了这条语句的反汇编,发现Winavr读写I/O寄存器(包括EECR)全是用的LDI,STD指令,即把I/O寄存器当做SRAM处理,而没有用OUT指令,导致其需要花费5个时钟周期,这里要提醒大家注意,Winavr把所有的I/O寄存器都当做SRAM来处理,其花费的时钟周期较长。至此问题已经找出,于是便开始想解决办法,我想到的是在C里面嵌入汇编来做。”

就上下两行的程序,编译之后竟然要花大于4周期的时间。。。。。

于是我根据他的程序做了点修改,嵌入汇编,程序如下:

void EEPROM_Write(uint waddr,uchar wdata)
{
        while(EECR & (1 << EEWE));
        EEAR = waddr;
        EEDR = wdata;                                                                       
       
        asm volatile("PUSH R16" "\n\t"                       
                  "LDI R16,0x04" "\n\t"
                  "OUT 0x1C,R16" "\n\t"                //EECR |= (1 << EEMWE);
                  "LDI R16,0x06" "\n\t"
                  "OUT 0x1C,R16" "\n\t"                //EECR |= (1 << EEWE);
                  "POP R16");
}

就可以用了,由于没有学过AVR的指令集,结合了一些51的汇编,先将R16原来的压栈保护再谈栈,也不知写没写对,反正编译通过,可以正确写操作。说这个是BUG也许不恰当,但是对于初学者来说是相当悲剧的,明明是用户手册上的程序,写在ICC、IAR上可以用,在GCC上就不行给人一种编译器有问题的感觉、、、

关于eeprom的中断,做了之后发现,eeprom的中断貌似仅限于写操作的中断,假设I和EERIE置一后,只有当EEWE清零的时候的时候才会触发中断,即只有“写完”之后才会中断,而“读完”之后不会触发中断,这个只是作为初学者的个人理解,也许是错误的,仅供讨论。

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

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

出0入0汤圆

发表于 2010-9-28 03:32:37 | 显示全部楼层
开优化////os级别

出0入0汤圆

发表于 2010-9-28 08:52:16 | 显示全部楼层
不知道ICC是不是这样呢

出0入0汤圆

发表于 2010-9-28 09:12:46 | 显示全部楼层
while(EECR & (1 << EEWE));
asm("sbi 0x1C,2"); //EECR |= (1 << EEMWE);
asm("sbi 0x1C,1");//EECR |= (1 << EEWE);
while(EECR & (1 << EEWE));

出0入0汤圆

发表于 2010-9-28 10:22:04 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-9-28 10:33:11 | 显示全部楼层
我也正想求教winavr的问题,不过我用的是atmega128,在eeprom读写上倒是顺利,而目前是被32K地址限制问题搞死了。winavr不适合做大软件……

出0入0汤圆

发表于 2010-9-28 11:11:11 | 显示全部楼层
开优化……感觉是老生常谈的一句话了……开优化后就会用位操作和IO访问。

出0入0汤圆

 楼主| 发表于 2010-9-28 11:57:09 | 显示全部楼层
开完贴就睡觉去了。醒来看到了1楼和6楼的回答,马上试了一下。

看了一下程序的汇编后。。。。


优化-00的汇编 (原文件名:-00.jpg)


优化-01的汇编 (原文件名:-01.jpg)


优化-02以后的汇编 (原文件名:-02.jpg)

在测试之后发现-01似乎也不行,只有在优化-02及-02之后才会出来正确的写操作。

没想到两句之间优化和没有优化的编译结果竟然相差这么多!

出0入0汤圆

 楼主| 发表于 2010-9-28 11:59:41 | 显示全部楼层
回复【2楼】biansf2001 花溅泪
不知道icc是不是这样呢
-----------------------------------------------------------------------

使用手册上的程序ICC应该没有问题吧

出0入0汤圆

 楼主| 发表于 2010-9-28 12:10:02 | 显示全部楼层
回复【1楼】avr_c
开优化////os级别
-----------------------------------------------------------------------

回复【6楼】yyccaa
开优化……感觉是老生常谈的一句话了……开优化后就会用位操作和io访问。
-----------------------------------------------------------------------

虽然接触AVR时间不短,但是由于学业忙和自学的关系,现在还是新手。几乎每一本书每一个教学视频都会告诫新手要慎用优化和熔丝

位,所以才会去寻求其他解决方法而非优化,就如我和那个帖子的楼主,这样说来我发现的所谓BUG说起来倒是有点搞笑了

经过这次发现优化确实很重要,但是对我而言,优化造成的后果是不可预知的,我想问一般开了优化后,会优化哪些东西?而编写程序

该注意那些东西?

出0入0汤圆

发表于 2010-9-28 13:21:33 | 显示全部楼层
开优化主要就是注意正确使用volatile限定变量,不是不管三七二十一每个变量都加限定,而只是适当的变量加。
新手是要慎用优化,但始终不用优化,你在写代码方面就得长期停留在新手层面。
楼主比很多新手好的地方在于能花时间去读懂反汇编后的代码,这对于学习、了解编译器的优化方式很有好处。

出0入0汤圆

 楼主| 发表于 2010-9-28 17:22:58 | 显示全部楼层
回复【10楼】yyccaa
开优化主要就是注意正确使用volatile限定变量,不是不管三七二十一每个变量都加限定,而只是适当的变量加。
新手是要慎用优化,但始终不用优化,你在写代码方面就得长期停留在新手层面。
楼主比很多新手好的地方在于能花时间去读懂反汇编后的代码,这对于学习、了解编译器的优化方式很有好处。
-----------------------------------------------------------------------

争取脱离新手状态。。

出0入0汤圆

发表于 2010-11-16 14:14:08 | 显示全部楼层
奇怪,我使用EEAR编译无法通过,提示EEAR没有定义,使用EEARL即通过。WINAVR。

出0入0汤圆

发表于 2010-11-16 14:28:39 | 显示全部楼层
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=717674&bbs_page_no=1&search_mode=1&search_text=EEPROM&bbs_id=1000
m48只对EEARL操作。

出0入0汤圆

发表于 2010-11-16 22:13:08 | 显示全部楼层
回复【5楼】yyy71cj  
我也正想求教winavr的问题,不过我用的是atmega128,在eeprom读写上倒是顺利,而目前是被32k地址限制问题搞死了。winavr不适合做大软件……
-----------------------------------------------------------------------
ATmega128(L)-
        doc2467.pdf


– 128K Bytes of In-System Reprogrammable Flash
Endurance: 10,000 Write/Erase Cycles
– Optional Boot Code Section with Independent Lock Bits
In-System Programming by On-chip Boot Program
True Read-While-Write Operation
– 4K Bytes EEPROM
Endurance: 100,000 Write/Erase Cycles
– 4K Bytes Internal SRAM


– Up to 64K Bytes Optional External Memory Space  ---????

出0入0汤圆

发表于 2010-11-20 19:56:33 | 显示全部楼层
哈 楼主被耍了下  
那个优化必须要开的  就是调试时有些语句优化成几段 C中调试有些步都不走到 乱了
所以出了问题第一个看汇编

出0入0汤圆

发表于 2010-11-20 20:29:48 | 显示全部楼层
另外提一下,gcc对AVR优化一般选-Os,从大量经验来看,这个优化不仅获得的代码尺寸小,多数情况下,甚至速度也比 -O2级别要快。其实对单片机而言,尺寸优先更为重要,毕竟flash空间有限。

出0入0汤圆

发表于 2011-12-23 14:19:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-10 14:38:40 | 显示全部楼层
mark ^^^^^

出0入0汤圆

发表于 2012-9-19 08:58:47 | 显示全部楼层
mark asdfdsa
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-6-11 01:39

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

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