搜索
bottom↓
回复: 14

如何实现MEGA64单片机FLASH特殊存储格式?

[复制链接]

出0入0汤圆

发表于 2009-7-3 18:12:53 | 显示全部楼层 |阅读模式
马潮老师
    您好!我无事不登三宝殿,有一个技术问题,需要请教一下您!
        我的问题比较特殊,请您看我说来:由于一些特殊的原因,我需要在MEGA64单片机的FLASH的某些位置,比如0X7F,0XFF,0X17F,0X1FF,0X27F,0X2FF,0X37F,0X3FF…等些个地方分别定义一个无用的字节(预留一个无用的字节,这个字节对程序的正常运行没有任何影响),请问应该如何实现?
我目前的想法是这样做的,我想通过汇编语言的ORG(定义代码起始位置),DB(在程序存储器中定义字节常数)伪指令来实现,比如
.ORG 0x7F //将FLASH程序存储器定位到0X7F位置
.DB 0 //定义这一位的值为0
        由于我的程序是用C语言写的,在WINAVR+AVRSTUDIO环境下编译,因此要在C程序中嵌入汇编,我是这样写的:
        asm volatile(".org 0x007f;.db 0" : :);
        但是这样写后,编译器编译报错,如果我将0X007F改成0X1100,它就不报错,我想可能是因为0X007F是中断向量存放的地址。我是将如下的函数加入到单片机的初始化函数中来实现的,我觉得这样肯定是不对的,但是由于水平有限,我不知道应该怎么写。
        void mapping_init(void)
{         asm volatile(".org 0x1100;.db 0x55,0xAA" : :);
}
        另外,也有网友提出,在WINAVR+AVRSTUDIO环境下,用C语言就可以定义FLASH中某一位置字节的值,如下:
        *((unsigned char PROGMEM *)0x7f) = 1;//将FLASH中0X7F位置的值设成1。
但是编译通不过,错误为:
        ../include/mtumsg.h:25: error: syntax error before "unsigned"
        我看了一些资料,查了avr-libc-manual.pdf,看了心艺和马潮老师的书等等,我自己对这个存储格式的实现不是抱很大的希望,我觉得理论上可能可以说得通,只要编译的时候在特殊位置预留几个这样的字节就可以,但是实际上不然,比如中断向量表的位置就不可能预留这样的字节(我自己认为)。
        我知道,我这个要求非常之特殊,但是说起为什么要这样做的原因来话就长了。由于我们的产品有1000多台有这个毛病,而补救的办法只有将程序存储器中的数据存储格式改成我如上要求的格式,如果没有特殊的原因,我们也不会这样去转牛角尖了。
        由于我水平有限,恳请您抽出宝贵的时间,帮我看一下这个问题,并帮我提出一个妥善的解决办法,或者实在不可能实现我以上的存储格式,那就请说明一个理由,谢谢,我感激不尽…
     期待您的回复,谢谢!

出0入0汤圆

发表于 2009-7-3 18:17:24 | 显示全部楼层
你说下为什么要这样做...
不要在一颗树上XX...

出0入0汤圆

发表于 2009-7-3 18:26:00 | 显示全部楼层
iccavr中可以,但也挺麻烦...
你先讲讲为什么要这样做...

出0入0汤圆

发表于 2009-7-3 20:53:04 | 显示全部楼层
确实不明白为什么这样做?
原来程序已经编译好的指令,被你中间插入了未知指令,你不担心出问题(出问题是必然的)?
如果非要这样搞的话(暴力),我觉得可以到boot区去将程序 读出-> 改写 ->写入
这样应该可以满足你的要求,而且boot区的程序也很简单,不需要完成升级的功能。

出0入0汤圆

 楼主| 发表于 2009-7-4 09:21:39 | 显示全部楼层
为什么要在FLASH的特殊位置定义这样无意义的字符呢?我大致说一下:
由于我们的设备用在电信的CDMA网络监控上,在特殊情况下,需要通过CDMA网络对MEGA64主控制器升级,我们是这样实现升级的:为了稳定,在CDMA模块与MEGA64单片机之间再接一个MEGA32单片机,CDMA模块与MEGA32单片机用UART串口连接,MEGA32与MEGA64之间用SPI口连接。这样在要升级时,MEGA32获取从CDMA上下发的数据,MEGA32再通过SPI口将数据以128字节每页烧写进MEGA64单片机,问题主要出在CDMA模块与MEGA32单片机UART通信这里。
在升级时,CDMA模块(106版本)与升级服务器之间通过TCP建立连接,一旦建立TCP句柄,服务器会自动以128字节升级数据为单位向下发送数据包,CDMA的串口冒出来的升级数据包格式如下:
%TCPRECV: 1, 128

UPGRADE START0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
OK
十六进制显示格式如下:
25 54 43 50 52 45 43 56 3A 20 31 2C 20 31 32 38 0A 0D 0A
55 50 47 52 41 44 45 20 53 54 41 52 54 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0D 0A 4F 4B 0D 0A 0D 0A 0D 0A
这里“%TCPRECV: 1, 128“是模块自动冒出的TCP数据包包头,“UPGRADE START0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000”是服务器下发的升级数据包,后面再跟一个“OK”。可以看到包头和包体之间有3个字节(0A,0D,0A),我的MEGA32升级程序通过定位来实现,在收到包头后,我从最后一个字节开始数,数3个字节,定位到“UPGRADE”的”U”这个字符这里,从这里开始往后数128字节,数到128字节,我就将这个128字节烧写到MEGA64的FLASH中,每次收到一个128字节,我都会以这样的方式定位,然后数128字节,将其烧进FLASH。
本来我已经实现了这个功能,但是后来这个模块升级了,升成108版本,而且我们在升级后没有对通过CDMA模块用MEGA32对MEGA64升级功能进行测试,而出货出了1000多台,现在已经安装在现场了,后来由于功能要求有变化,需要对设备进行升级才发现有问题。
新版本模块与老版本模块之间的区别在于:升级数据包包头和包体之间的字节数变了,以前是3个字节(0A,0D,0A),现在变成了只有两个字节(0D,0A),这是我最郁闷的地方。
这样按照老程序,服务器下发相同的数据包,我永远也辨别不出来这个是升级数据包了,我在想补救措施。
        我想能不能以这样的方式来实现:
        每次服务器下发的依旧是128字节,但是这个128字节的包体开头处多一个字节,假设为’U’,这样的话,128字节包体中其实只有127个字节是真正有效地,是我需要写进FLASH中的,如下:
        %TCPRECV: 1, 128
UUPGRADE START000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000(128字节)
这样的话,包头和“UPGRADE START…“之间依旧是3个字节,我的MEGA32程序收到升级包包头后,依旧会跳过3个字节,定位到“UPGRADE START。。。”的’U’处,而不会定位到第一个无用的’U’处,从这里开始往后数128字节,
UPGRADE START000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000(127字节)+1个字节
数到128字节后烧写,其实从上面看到只能烧写127个有效数据,第128个字节是一个无效的数据,或者是一个任意数。因此,我现在想能不能通过在C语言中嵌入汇编,比如
0RG  0X7F(第128字节)
DB   0X00
0RG  0XFF(第256字节)
DB   0X00
……
以这样的方式,让程序编译时,就将bin文件编译成每个128字节的最后一个字节(第128字节)为无效数据,或者说是预留的一个FLASH字节?如果编译器有这样的功能,那我觉得我这个方法也是可行的?
我是这样理解的,我觉得目前我们的产品已经在运行了,如果这样不能升级,只有将其拆回来重新升级,1000多台设备的工程量难以想象,我也没有想出更好的办法,来实现升级。
谢谢大家给我建议!期待大家的回复,谢谢。
                                                           王军华
                                                         2009.07.04

出0入0汤圆

发表于 2009-7-4 09:54:29 | 显示全部楼层
修改bootloader是正途...
lz当初没设计bootloader自升级功能?

出0入0汤圆

 楼主| 发表于 2009-7-4 09:55:32 | 显示全部楼层
我们怕bootloader不稳定,所以没有用bootloader功能,而是用MEGA32对MEGA64进行SPI口烧写

出10入120汤圆

发表于 2009-7-4 10:10:01 | 显示全部楼层
看玩了楼主的要求,几乎是没有办法实现的,除非整个系统用汇编来做。

一般来说,编译系统很难按照要求依照绝对定位方式定义这么多常量

出0入0汤圆

发表于 2009-7-4 10:16:45 | 显示全部楼层
SPI烧写,必须一次烧128字节?

出0入0汤圆

 楼主| 发表于 2009-7-4 13:42:40 | 显示全部楼层
shi a ,通过SPI口烧写的话,就是一次烧写128字节,你可以看一下SPI口编程原理,就是这样的

出0入0汤圆

 楼主| 发表于 2009-7-4 13:45:17 | 显示全部楼层
snoopyzz同学,在ICCAVR中怎样设置可以实现这个功能呢 ?

出0入0汤圆

发表于 2009-7-4 13:57:11 | 显示全部楼层
很麻烦,
#pragma abs_address:0xXXXX
char spec1 = 0x55;
#pragma end_abs_address

#pragma text:my_text
void Init_Port(void);
#pragma text:text

基本上程序要全部重新安排,给每个常量和程序段绝对定位
而且必须重写C语言自身的启动代码
=================
简单的作法是先编译好程序,然后看你必须空出来的字节是否有用
有用的话,在前面若干字节开始的代码放到程序空白段,然后rjmp过去
再rjmp到下一个位置
就是说,手动将这些地方空出来....

修改工具呢,用winhex修改bin文件...

=================
当然,如果是中断向量,肯定无能为力...
=================
另外,我大学毕业有几年了...

出0入0汤圆

 楼主| 发表于 2009-7-4 15:56:15 | 显示全部楼层
en ,谢谢snoopyzz君,我照你说的方法试试,看看可不可行,谢谢

出0入0汤圆

发表于 2009-10-22 17:49:25 | 显示全部楼层
哪有MEGA64的FLASH实例代码

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-2 14:46

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

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