arm开发tq2440上的c++裸奔程序

AVR实验做到LCD的时候,就发现proteus上没有现成合适的显示模块,网上找的模块不是按一般方法封装的,想来自己还有一块arm9开发板,大概大三、大四时候买的,已经搁置三年了。毕业这两年已经从51玩到AVR,虽然大多在proteus上玩,但对如何开发嵌入式有了基本,准确的认识。现在应该可以转到arm平台上来了吧?

 

首先是开发工具,走了很大的弯路最终才发现只能用RealViewMDK。放弃IAR是因为IAR无法移植TQ2440中对各段地址的引用,类似 |Image$$RW_RAM1$$ZI$$Limit|,这使得我无法安排各段在内存中的位置。即使硬编码到代码中,也无法配置成从NAND flash启动,IAR的链接器太简陋了。

 

我花了很长时间看TQ2440init.s这个启动文件,最后还是看了TQ论坛上的一篇文章才真正移植成功的(用Keil MDK开发TQ2440裸机程序入门教程2(移植TQ2440测试程序).doc),这才发现自己移植的是链接上出了问题,没有用--sort=CallTree,map文件中可以看到使用前nand.o在4k外,使用后在4k内,这就是代码烧到板子上后起不来的根本原因。

 

看了一段时间TQ2440的测试代码,觉得后面用到具体某个驱动的时候再回来看,现在可以开发裸奔游戏了。第一个问题是我想用c++来开发,全局的方法和更接近底层的方法可以用c来实现,自己写的c++框架后面的开发可能用得着,用c++语言配合面向对象方式的思考要比用C来的简单,至少对我这个用java工作的人来说是这样。目前刚把c代码转换成c++代码,主要还是nand.o的链接问题,这回不能用Main函数了,c++编译器不认识,改回main后会把nand.o挤出4K地址范围,试了所有的sort方法都不行。网上曾经看到有人说为什么不把nand的代码直接放到TQ2440init.s中,用--asm编译出nand.s,再把它整个拷贝到启动代码末尾,编译后nand的代码就在4K内了。

 

哈哈!有意思的事才刚开始 !!

 

2012.08.19

接下来的问题是不能使用STL中的容器类,会报data abort。原因是没有初始化c++运行时库,模仿着MDK中的c++例子,把Main替换成__main,这样在进main()函数之前会初始化c++必要的库。还用到了__user_initial_stackheap,stack指针可以配置成功,heap指针没有配置成功,不过已无大碍。

 

昨天刚解决一个困扰我四五天的,内存相关的data abort问题。描述如下:

有个引擎类的成员是STL容器类,LCD屏幕的初始化也是这个引擎类完成,结果在使用容器类成员的时候,打log发现容器类的数据被破坏了。在类初始化的时候数据还是对的,LCD屏幕初始化完毕后数据就出错了。从log看到stack指针和我配置的不同,修改启动代码后解决,但还是有data abort。最终通过不懈的打log调试,发现是视频缓冲这个全局数据和容器类对象在RW段上数据发生了覆盖。所以因初始化顺序的不同,会造成显示异常或容器类数据被破坏。

 

原因找到了,解决方案就很容易想到了,之前试过64M内存可以随意存取,不用管堆或栈的溢出。所以我把视频缓冲的地址强制设置到远离RW段的地方,运行,一切OK啦!

附上源码:https://files.cnblogs.com/PrajnaKit/BoxPorter.zip

 

2012.08.29

显示模块初步完成后,我开始声音模块的开发和调试。遇到的问题是真机播放声音时无法触发DMA中断,导致声音刚播放了一点就停止了,直接下载到内存运行时一点问题也没有。我排查错误花了三四天,结果还是没找到原因。不过我基本明白了DMA和UDA1341的工作原理,可这个bug过不去的话我的“裸奔游戏”远景就无法实现了。因为刚刚移植好的TQ2440测试程序播放声音是没问题的,那我就一步一步的改,直到声音无法播放。由于改的匆忙,事后回想整理的时候顺序可能有错误,不过要点应该都讲到了。

 

1.       把源码移植到Keil中。

2.       首先把Main改成main,启动文件和主文件需要修改,然后把主文件后缀变成cpp。一些c的函数需要包裹在extern C”中。

3.       变成cpp后拷贝nand flash的函数RdNF2SDRAM被挤出4K地址范围,通过集成汇编后的nand.asm到启动文件解决。

4.       使用scatter文件来配置RW段和ZI段,由于STL容器类对象数据地址不太对的原因,需要把ZI段定义在远离RW段的地方,否则stl容器对象数据会覆盖ZI段全局数据。因此也需要修改启动文件中ZI数据初始化的代码中ZI段的地址。注意linker页签中要去掉"Use memory layout from Target dialog"勾选,不然无法指定ZI段地址。

5.       Uart_Printf()方法在使用通配符的时候会出问题(%d, %s, %p…),具体原因没有深究,不过从现象上看可能是由于没有链接相应的库,也可能是没有初始化运行时库。

6.       data或者prefetch abort问题需要实现__user_initial_stackheap()方法,不然堆和栈的地址没有初始化。启动文件跳转地址改为__main

注意使用__main()的话,无法使用c++的类,不然无法进入到main函数。

:更新的源码现在使用__main()进行跳转,这样运行时库也就能初始化,同时STL库也能正常工作。

7.       armthumb混合模式关闭,需要修改配置页签和启动文件中nand.asm数据段的断言。

 

启动文件中增加user栈指针设置,最后还是启动文件写的有问题啊。。。终于查出来了,我把栈指针初始化开头的” bic        r0, r0, #CONTROLMASK”注释掉了,结果就有data abort

 

源码已更新,屏幕背景所在的内存区域没有零初始化,所以背景的颜色是不确定的。

 

 

 

posted on 2012-08-10 07:46  Prajna  阅读(894)  评论(1编辑  收藏  举报

导航