这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 2410启动代码和uc/os移植调试总结

共1条 1/1 1 跳转至

2410启动代码和uc/os移植调试总结

菜鸟
2006-01-19 17:07:22     打赏

2410启动代码和uc/os移植调试总结

前言

11月的时候详细看完了《嵌入式实时操作系统uc/osII》这本书,感觉写的比较通俗易懂,也让我第一次真正了解了实时操作系统的基本框架和实现原理,正好12月初的时候有个移植uc/os2410上的机会,在这之前我只大概看过LPCARM的东西,但对arm体系结构,ADS1.2编译环境不太熟,但是机会难得,我还是去试了试,非常感谢minix师兄给我这个机会,在这段时间中我熟悉了ARM的体系结构,ADS1.2的编译环境,启动代码的过程。

正文

这次主要任务是移植uc/os2410上,因为移植uc/os需要修改中断向量表,而原来2410上跑的是ppcboot,我对ppcboot不熟,感觉修改起来比较麻烦,所以打算用通用的2410简短的启动代码来进行启动;然后就是uc/os的移植了,因为2410是一款很流行的型号,所以很多人已经做过这些工作了,我于是就在www.uc/os-II.com上下了一个移植的源码,这样我的主要任务就是把启动代码和移植程序调通。

本来想写一个ADS1.2的编译环境,启动代码的过程等等总结,但看了truelyboy写的S3c2410软件调试总结(1)~(7),觉得我写的不会比他好,所以作罢,(大家可以看看trulyboy原帖,原帖 http://bbs.edw.com.cn/dispbbs.asp?boardID=20&ID=52020&page=1,原帖名字是“S3c2410软件调试总结”),在这里对trulyboy文中没有提到的“不用__main()初始化运行环境”进行说明。

在ADS1.2中__main()作为c语言的入口函数,它主要做了以下工作:

1.把RO,RW从他们的加载域复制到他们的运行域中去(可以用在LINKER中设置RO=,RW=,来确定,也可以用scatter文件来定义)

2.初始化ZI域

3.跳到__rt_entry.

而库函数__rt_entry()会完成以下工作:

1. 调用__rt_stackheap_init()设置stack和heap

2. 调用__rt_lib_init()初始化相应的库函数,

3. 调用main(),即是我们自己的应用程序了

4. 调用exit()来处理main()函数的返回值

从上面我们可以看到__main()运行时库主要是初始化一些东西,然后跳到用户的main()中去,所以我们不用__main()函数初始化运行环境的时候,要自己编写相应的代码来完成相应的内容,下面以一个例子来说明。

为了完成RO,RW段的复制,和初始化ZI域,所以我们要以下代码,

IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)

IMPORT |Image$$RW$$Base| ; Base of RAM to initialize

IMPORT |Image$$ZI$$Base| ; Base and limit of area

IMPORT |Image$$ZI$$Limit| ; to zero initialize

ldr r0,=|Image$$RO$$Limit| ; Get pointer to ROM data

ldr r1,=|Image$$RW$$Base| ; and RAM copy

ldr r3,=|Image$$ZI$$Base|

; Zero init base => top of initialized data

cmp r0,r1 ; Check that they are different

beq %F1

0

cmp r1,r3 ; Copy init data

ldrcc r2,[r0],#4

strcc r2,[r1],#4

bcc %B0

1

ldr r1,=|Image$$ZI$$Limit| ; Top of zero init segment

mov r2,#0

2

cmp r3,r1 ; Zero init

strcc r2,[r3],#4

bcc %B2

以上是没有使用scatter文件,如果使用了scatter文件来映射地址,那Image$$RO$$Limit Image$$RW$$BaseImage$$ZI$$BaseImage$$ZI$$Limit这些符合就会失效,相应的我们可以用Image$$region_name$$ZI$$Base Image$$region_name$$ZI$$Limit等等来替换,同样可以完成以上功能,

紧接着我们就可以用直接用“B ”指令跳到我们自己的c程序中,完成我们想做的事。

调试中遇到的问题

在调试中也遇到了一些问题,其中最严重的问题是,我把程序烧到NORflash后,程序不能运行(烧了几十次,只正常运行了23次,不过一按复位键就又不能运行了),而用AXD单步调试的时候程序又能够运行,于是我就不停的在运行时域,库函数,semihostingscatter文件等方面找原因,结果郁闷了快一个月也没有在这些方面发现问题,不过倒是让我对这些方面的东西熟悉了不少,最后,在对照能够跑起来的启动代码一条一条语句的改的时候,才发现是配置MPLLM,P,S几个值有问题,当让换成另一个较低的频率值的时候系统就能够正常运行了,而原来那个M,P,S配置也是正确的,但频率太高,与memory不匹配,就是不能让系统跑起来。要想让系统在较高的频率也能启动起来就需要在设置MPLL之前,把FASTBUS MODE改成ASYNCHRONOUS MODE。

这让我深深的认识到了编底层代码和编应用程序的区别:编应用程序只要逻辑是正确,程序就能跑起来;而编写和硬件相关的程序则不同,不仅仅要保证程序的逻辑正确性,还要求与相应的硬件要匹配,比如同一个2410启动代码在一个板子上能正常运行,而到另一个2410板子上就不一定能正常运行。

后记

非常感谢minix师兄给我这个机会,也很感激dandandan师兄给我学习嵌入式方面的指点,还有hn和电子产品世界论坛的truelyboy的帮助。

虽然这次做的都是一些比较简单的东西,但通过这些实践,让我对ARM体系结构,ADS编译器,启动代码都有了一定的熟悉,下一步我想学习linux的东西,我知道我在嵌入式系统这条路上才刚刚起步,非常希望和大家一起交流,学习,共同进步!




关键词: 启动     代码     移植     调试     总结     Image    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]