新闻  |   论坛  |   博客  |   在线研讨会
rtems在s3c2410上的移植(二)
xiajiashan | 2012-08-28 16:40:01    阅读:1233   发布文章

作者,下家山

9.1需要改动的地方

①c/src/lib/libcpu/arm/s3c2410/include/s3c2400.h相应register的修改.

②因为要使用串口功能,所以需要在应用程序中添加端口初始化函数,来初始化各端口,主要初始化Port F,H,端口F为LED显示功能所用,端口H为串口打印功能所用.

(可以直接复制s3c2410开发板套件资料的armsys_2410/hardware_test_pro中的Port_Init函数)

③在c/src/lib/libbsp/arm/gp32/startup/Bspstart.c,bsp_start_default函数中添加bank0-bank7的相关register的设置

④在start.S(见c/src/lib/libbsp/arm/gp32/start)中添加LED显示子程序.

9.2需要确认的地方:

①在c/src/lib/libbsp/arm/gp32/console/Uart.c中对照s3c2410 datasheet确信各register地址是否正确.

②确信baudrate是否与PC机上的串口baudrate一致.

③Fclk,Pclk,Hclk的值为多少,相关函数参照c/src/lib/libcpu/arm/s3c2400/clock/Support.c c/src/lib/libbsp/arm/gp32/include/Bsp.h c/src/lib/libbsp/arm/gp32/startup/Bspstart.c 知道baudrate,Fclk,Pclk,Hclk是怎么计算的,并对照s3c2410 datasheet确信计算结果是否准确.

9.3调试方法

LED跟踪(并借助ads)

所以需要写一个LED显示程序,最好用汇编写,并在ads上验证该程序能正常调用.

10:调试hello world时碰到的问题

我用LED一直跟踪到boot_card函数都很顺利,但到执行 BSP_RTEMS_Configuration = *Configuration.RTEMS_api_configuration;这条语句时程序跳飞。显然,这条跳飞的原因大半是指针造成的,Configuration.RTEMS_api_configuration是一个指针,使用指针的大忌是不初始化就使用,因为没有初始化,所指向的地址未知,因此程序跑飞.所以,我定义了一个rtems_api_configuration_table

结构体,并把其地址赋给Configuration.RTEMS_api_configuration,果然BSP_RTEMS_Configuration = *Configuration.RTEMS_api_configuration;执行过去了.我开始接着往下调,但一个OS往往是牵一发而动全身,改动了Configuration.RTEMS_api_configuration,接下来很多地方都要改动,所以要找到根源.

BSP_RTEMS_Configuration是Configuration的一个复制体,而Configuration是在confdefs.h中定义的,是一个已初始化的全局变量,所以我怀疑是不是全局变量初始化不成功?初始化的全局变量是放在.data区域的,而这一区域是定位在sdram中的.那么怎样才能看到这一区域的内容呢?最后想到了ads,我通过ftp把编译好的bin文件下载到板子后,再通过AXD调试软件查看sdram中的内容.这里,可以定义些一眼就能看出来的特征值,比如定义两个全局变量int a=0xaaaaaaaa;int b=0xbbbbbbbb;.但是,64M的sdram怎么查呢!用过ads的人应该知道,编译后的执行文件(.o)对每个函数,全局变量都已分配好了地址,这些地址在编译完成时在Section Cross References中会列出来.那么,在gcc中编译后怎么查看其中的函数,变量的地址呢?找相关资料,发现readelf就是干这个事的,所以readelf -a helloworld.exe >map得到map文件,用UltraEdit -32打开查看,记下全局变量a,b的地址(map中你还可以看到各函数的具体位置及占用空间的大小。要知道自己添加的文件是否编译进去,这是个很好的方法,我在编译network时,就如此).然后,在axd中定位到刚才记下的地址,发现AXD中a,b的地址与刚记下的地址(map)相差0x100偏移量.后面,我还做了大量的实验,比如定义结构体.都证明gcc编译后的全局变量的地址与AXD中查到的地址相差0x100,AXD查到的地址应该是sdram中的实际反映.因此我马上想到了linkcmds文件的.base段,其定义的就是sdram起始的0x100个字节,果然,当我把.base段去掉后原来跑飞的地方通过了.但去掉.base也不是办法,之后把它移到.bss段。但后来想来想去还是不妥,既然系统把它定义到前面一定不会错,我把它改动了,还不知有什么后患呢?那还有什么办法呢?后来突然想到,我通过uboot下载bin文件到sdram时,load地址是0x30000000,我把load地址改为0x30000100后,也一样解决了问题.

在调试hello world例程时碰到的主要是这个问题.其他地方只要调试时细心应该不会有什么问题.

11:调试网络时碰到的问题

在testsuites/samples中找到loopback例程,发现要用到clock驱动. 而专门测试clock的例程是testsuites/samples下的ticker.clock是通过中断来实现的,所以接下来要添加中断.

首先,弄清楚RTEMS内核,中断的实现机制.rtems-4.6.99.3关于中断的函数调用流程如下:

 
绘图302.jpg

rtems_exception_init_mngt安装六类异常向量地址到rtems_vector_table(在linkcmds中定义,实际地址为0x30000020)开始的地方,rtems_irq_mngt_init以实际的irq句柄初始化异常向量表,并以default_int_handler地址初始化32个rtems bsp

irq中断向量地址.当发生irq中断时,系统跳到0x00000018地址执行,0x00000018地址处装载的就是rtems_irq_mngt_init安装的实际的irq句柄,通过这个句柄就可以找到相应的32个rtems bsp irq中断向量的哪个发生了中断,从而跳到对应isr服务程序执行.

系统是怎么找到clock中断isr服务地址的,rtems-4.6.99.3关于clock中断的函数调用流程如下

 

 
 
绘图301.jpg

到现在虽然中断句柄已经安装好了,但还没有做映射,系统怎么访问0x00000018地址呢?

11.1 MMU

记得,在start.S中我屏蔽了

ldr r0, =mem_map/*装载映射表*/

bl mmu_init /*初始化mmu*/

现在要打开

程序的调试工作有回到了汇编阶段,所以,我又用LED跟踪.

一直跟踪到函数mmu_init中的 mmu_set_ctrl函数

前都没事,但调用这个函数时程序跑飞了.

我开始怀疑是C内嵌汇编出了问题,所以我把mmu_set_ctrl换成了纯汇编程序放到了start.S中,同样跟踪到了我转换后的汇编函数中。但,就在执行使能mmu这条语句时飞掉了.把这条语句屏蔽了就没事.说明不是内嵌汇编的问题.那么在执行这条语句时,cpu到底做了些什么呢?要擦看汇编及pc指针最好的办法莫过于用ads了,用AXD调试程序运行到使能mmu这条语句时也跑飞了.做了改动的地方只有

mem_map,gp32中的映射表为

 

绘图11.jpg

我改动后为

 

绘图12.jpg

我开始以为映射属性的问题,但怎么换都不行,后来,发现问题出在映射size上,64M的sdram只映射了9M,暂且不说,因为我程序加各堆栈再怎么样也不会超过9M,没有映射完64M也不会出什么问题.但是,Internals Regs如果没有映射完就有问题了,我对照s3c2410.h,发现,从48000000-4a000000,50000000-5a0000000而我只映射了16M也就是只映射了48000000-49000000,50000000-510000000,这么多register没有映射,当要访问没有映射的register时肯定会因找不到地址而跑飞.所以,映射所有的bank0-bank7

mmu_sect_map_t mem_map[] = {

/* */

{0x30000000, 0x00000000, 1, MMU_CACHE_NONE}, /* SDRAM for vectors */

{0x30000000, 0x30000000, 32, MMU_CACHE_WTHROUGH}, /* SDRAM W cache */

{0x32000000, 0x32000000, 32, MMU_CACHE_NONE}, /* SDRAM W/O cache */

{0x48000000, 0x48000000, 256, MMU_CACHE_NONE}, /* Internals Regs - */

{0x50000000, 0x50000000, 256, MMU_CACHE_NONE}, /* Internal Regs - */

{0x00000000, 0x00000000, 0, 0} /* The end */

};

这样,运行ticker例程时,看到了正确结果.

11.2 照葫芦画瓢

由于rtems-4.6.99.3源码自带的gp32-bsp中并没有网络驱动,所幸的是edp7312中有cs8900的驱动,因此可以copy edp7312目录下的整个network目录到c/src/lib/libbsp/arm/gp32下,并修改相关makefike文件,这里我把要注意的地方列出来:

①在configure rtems-4.6.99.3时去掉disable-networking disable-posix;

②对bank3 bus设置:

/*==========Bank 3 parameter==========*/

#define B3_Tacs 0x0 /*0clk*/

#define B3_Tcos 0x3 /*0clk*/

#define B3_Tacc 0x7 /*14clk*/

#define B3_Tcoh 0x1 /*0clk*/

#define B3_Tah 0x0 /*0clk*/

#define B3_Tacp 0x3

#define B3_PMC 0x0 /*normal*/

rBANKCON3= ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC));

不然,连cs8900 ID号都读不出来.

要成功编译需要花点时间。但这不是难点!只要细心,应该没有问题。

转载:请注明,作者,下家山 请尊重原创!

 

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
02年接触ARM和ucos,开发过有线和无线图像报警器,IPCamera,人脸识别系统,OCR识别系统,指纹识别系统,05年开始从事Linux及Rtems下WiFi,camera,Ethernet等驱动开发工作,专做嵌入式linux培训,致力于把我十年来的研发经验传授给每一个学员,招人的可以找我,ximenpiaoxue4016@sina.com
推荐文章
最近访客