移植 RTEMS 4.11 到 SBC2440 上

centos 6.5 i386,用virtualbox 4.3
rtems 4.11 / svn head 20140107

(一)从仓库获取最新版
git clone git://git.rtems.org/rtems.git

(二)删除不要的cpu和bsp,加快速度
1,
\rtems\cpukit\score\cpu
只留下arm,其他删掉,修改 Makefile.am 不要其他cpu
\rtems\cpukit
修改 configure.ac ,354行附近,不要其他cpu的makefile,否则会提示错误

2,
\rtems\c\src\lib\libcpu
只留下 arm 和 share

3,
\rtems\c\src\lib\libbsp
只留下 arm 和 shared

4,
\rtems\c\src\lib\libbsp\arm
备份所有bsp到其他地方,删掉所有bsp,创建 sbc2440文件夹,修改 acinclude.m4
# RTEMS_CHECK_BSPDIR(RTEMS_BSP_FAMILY)
AC_DEFUN([RTEMS_CHECK_BSPDIR],
[
case "$1" in
sbc2440 )
AC_CONFIG_SUBDIRS([sbc2440]);;
*)
AC_MSG_ERROR([Invalid BSP]);;
esac
])

(三)开始移植
1,
将 c/src/lib/libbsp/arm/smdk2410 复制一份为 sbc2440
sbc2440/make/custom/目录下的文件修改为 sbc2440.cfg

2, 查看 sbc2440/Makefile.am文件,看到一些引用了 gp32 目录的文件的,
凡是有 gp32 的都修改过来,主要就是修改路径,例如 ../gp32/include/bsp.h 改为 include/bsp.h
一共有这些
include_HEADERS = ../gp32/include/bsp.h
include_HEADERS += ../gp32/smc/smc.h
libbspstart_a_SOURCES = ../gp32/start/start.S
../gp32/startup/bspstart.c
../gp32/startup/bspidle.c
libbsp_a_SOURCES += ../gp32/console/uart.c
libbsp_a_SOURCES += ../gp32/smc/smc.c ../gp32/smc/smc.h

复制 gp32/include/bsp.h 并覆盖
复制 gp32/smc 目录所有文件
复制 gp32/start 目录所有文件
复制 gp32/startup 目录的 bspidle.c 和 bspstart.c 文件过来
复制 gp32/console 目录所有文件

$(PROJECT_INCLUDE)/bsp.h: ../gp32/include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h

$(PROJECT_INCLUDE)/smc.h: ../gp32/smc/smc.h $(PROJECT_INCLUDE)

3,
建立network 文件夹,下面建立 network.c 和 network.h 文件
因为增加文件需要重新config,比较麻烦,所以这里先搞好目录结构和文件,到时候修改再make比较省事。
修改 sbc2440/Makefile.am 添加网络驱动
在编译原文件下面,例如 smc 下面,53行附近,添加网络部分的代码,并将这个库加入到连接
# smc
libbsp_a_SOURCES += smc/smc.c smc/smc.h
(这里是添加的)
if HAS_NETWORKING
noinst_PROGRAMS =
network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
noinst_PROGRAMS += network.rel
network_rel_SOURCES = network/network.c
network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS)
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif

libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/shared/arm920.rel \
../../../libcpu/@RTEMS_CPU@/s3c24xx/clock.rel \
../../../libcpu/@RTEMS_CPU@/s3c24xx/timer.rel \
../../../libcpu/@RTEMS_CPU@/s3c24xx/irq.rel
(这里是添加的)
if HAS_NETWORKING
libbsp_a_LIBADD += network.rel
endif

到这里为止,目录结构已经完毕了,编译,保证正确编译,我需要网络和posix,其他不需要,也不打算学 :-)
如果不成功,则保留 smdk2410 和 gp32 目录。编译 smdk2410 ,一步一步的学吧。

# cd rtems
# ./bootstrap -c
# ./bootstrap -p
# ./bootstrap

如果发生错误。那么就没办法,只能按照上面的一步一步搞,实在不行就推到重来,如果没有经验,
则是不建议这样删除目录什么的,按照原来的所有源码来搞就行了,只是速度比较慢。
了解一下 autoconf 和 automake需要哪些文件,可以查看RTEMS的文档 bsp_howto.pdf
如果更改了目录结构,则需要 # ./bootstrap -p 来重新生产 preinstall.am
我的经验是:
如果每次都在根目录执行bootstrap的话,是很慢的,也没有必要,因为其他目录都没有修改。
其实我们可以
转到 rtems/c/src/lib/libbsp/arm 目录,执行这些命令
/rtems/rtems/bootstrap -c
/rtems/rtems/bootstrap -p
/rtems/rtems/bootstrap

只会执行本目录,已经所有子目录中执行,这样速度就很快了。
总之,如果增加文件,或者目录结构,则都需要重新 bootstarp 和config 的,是比较麻烦,所以
尽量先决定好目录和所有的文件,然后慢慢修改代码。


(四)开始修改源代码
做这类工作的时候,最好是使用对比工具,看看之前和现在的文件哪里修改了,修改起来心中有数。我使用的是 beyond compare

1,
sbc2440\make\custom
修改 sbc2440.cfg 将调试等级修改为 0,因为我需要下载到板上面调试的,体积大点没所谓,最关键是调试好用。
CFLAGS_OPTIMIZE_V = -O0 -g

2,
sbc2440/start/start.s 增加初始化bss段的内容,注意,这个工作为什么不做?其实这是提供给bootloader 来做的
bootloader从 _start + 4 的地址开始,就可以读取到各个段的开始结束为止,所以,该做什么就做什么了。这个是
启动系统必须做好的,必须注意这点。

我估计好多人就忽略了指点,直接跑直接就fatal错误了。
当然,最简单的是在启动文件里面添加自己初始化就行了。另外,我没有用bootloader,我是使用jlink直接调试的
所以更加需要添加自己初始化bss段的。
一些段的名字变了,例如 _axf_bss_start 变为 bsp_section_bss_begin
不过影响不大,对应过来就行了。
/*
* clear .bss ,etual add
*/
clear_bss:
ldr r0, =bsp_section_bss_begin
ldr r1, =bsp_section_bss_end
mov r2, #0x00000000
b clbss_2
clbss_l:
str r2, [r0]
add r0, r0, #4
clbss_2:
cmp r0, r1
bne clbss_l

3,
为了debug,设置时钟,SDRAM控制器 等都不需要做,全部在 GDB脚本中做,但实际跑的话是需要修改这里的,自己注意。
如果这里设置有问题则可以再启动文件 start.s 中设置,也可以通过bootloader设置,反正方法是多样的。

有点小变动就是 bsp_idle_task 改为一个独立的文件去做,这里就不关心了。

在 \sbc2440\startup 的 bspstart.c 中
#if 0
/* setup clocks */
rCLKDIVN = M_CLKDIVN;
rMPLLCON = ((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV);
/* setup rREFRESH
* period = 15.6 us, HCLK=66Mhz, (2048+1-15.6*66)
*/
REFCNT = 2048+1-(15.6*get_HCLK()/1000000);
rREFRESH = ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT);
#endif

4,
查看 startup/linkcmds,连接脚本的写法变了,前面变为了MMU的表了,这里不需要修改,只需要了解
MEMORY {
SDRAM_MMU : ORIGIN = 0x30000000, LENGTH = 16k
SDRAM : ORIGIN = 0x30004000, LENGTH = 64M - 16k
}

_ttbl_base = ORIGIN (SDRAM_MMU);

5,
修改 sbc2440/startup/memmap.c 添加各个bank地址的映射,映射还没有变,所以自己也添加
各个bank的映射,否则访问网卡等外设的时候各种莫名其妙的异常,我开始就被搞了好久。

mmu_sect_map_t mem_map[] = {
/* <phys addr> <virt addr> <size> <flags> */
{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 - */
{0x08000000, 0x08000000, 128, MMU_CACHE_NONE}, /* bank1 */
{0x10000000, 0x10000000, 128, MMU_CACHE_NONE}, /* bank2 */
{0x18000000, 0x18000000, 128, MMU_CACHE_NONE}, /* bank3 */
{0x20000000, 0x20000000, 128, MMU_CACHE_NONE}, /* bank4 */
{0x28000000, 0x28000000, 128, MMU_CACHE_NONE}, /* bank5 */
{0x00000000, 0x00000000, 0, 0} /* The end */
};


6
修改 sbc2440\console\uart.c
串口的一些数据结构改变了,但暂时不需要关心,由于和 2410设置不同,而串口暂时是用来做debug用的
所以不需要关心效率,直接poll输出就行了。
/* Set up the UART. */

static void uart_init(int minor)

{

int i;

unsigned int reg = 0;



rGPHCON = (rGPHCON & 0xFFFFFF0F) | 0xa0; //GPH2 GPH3

rGPHUP = (rGPHUP & 0xFFFFFFF3) | 0x0c;


/* enable UART0 */

rCLKCON |= (1<<10);



/* value is calculated so : (int)(PCLK/16./baudrate) -1 */

reg = get_PCLK() / (16 * 115200) - 1;



/* FIFO enable, Tx/Rx FIFO clear */

rUFCON0 = 0x0;

rUMCON0 = 0x0;

/* Normal,No parity,1 stop,8 bit */

rULCON0 = 0x3;

/*

* tx=level,rx=edge,disable timeout int.,enable rx error int.,

* normal,interrupt or polling

*/

rUCON0 = 0x5;

rUBRDIV0 = reg;



for (i = 0; i < 100; i++);



}
7,
libcpu\arm\s3c24xx\clock\support.c
修改get_FCLK
由于2440 的PLL计算公式不同,在原来的基础上乘以2 就行了。修改为
return((BSP_OSC_FREQ * m * 2) / (p << s));

8,
修改链接脚本 sbc2440/startup/linkcmd
在 rtems-4.10.2 中的连接脚本不是这样写的,但是 4.11 来了个大换血,开始也折腾了2天,
最后意识到可能是mmu的问题,于是找到了 rickleaf 大侠的文章,豁然开朗
原来是将MMU表放在 0x30000000 开始的 64K,内存映射之后这里是地址0,也就是所有的
向量的位置,这肯定是不行的,rtems-4.10.2 是将这个映射表放在 bss 段中的,不知道
为什么要这样改,我们将他指定一个位置就行了,当然也可以修改linkcmd.base将它重新放
到bss段,随便你怎么改了。
MEMORY {
SDRAM :     ORIGIN = 0x30000000, LENGTH = 64M - 16k
SDRAM_MMU : ORIGIN = 0x33ffc000, LENGTH = 16k
}
具体看 rickleaf大侠的文章

http://blog.csdn.net/rickleaf/article/details/7073031


最后
我的调试办法windows下面使用 eclipse 和 jlink gdb server 调试的,RTEMS 的时钟
看门狗,SDRAM 控制器等都没有设置,都在调试脚本中设置。(其实相当于一个 bootloader吧)
由于我的板子是友善 sbc2440,比 mini2440 还要早,使用的 SDRAM 和 mini2440 是不同的,
所以个脚本在 mini2440 上不可以使用,需要重新设置 REFRESH 的值,请注意。

我的脚本是:

target remote localhost:2331
monitor reset
monitor halt
monitor speed 8000
monitor endian little
monitor reg cpsr = 0xd3

#WDT
monitor memU32 0x53000000 = 0x00000000 #WTCON
#PLL
monitor memU32 0x4C000000 = 0xFFFFFFFF #LOCKTIME
monitor memU32 0x4C000004 = 0x0005C011 #MPLLCON 400MHZ:100:50
monitor memU32 0x4C000008 = 0x00038021 #UPLLCON
monitor memU32 0x4C00000C = 0x001FFFF0 #CLKCON
monitor memU32 0x4C000010 = 0x00000004 #CLKSLOW
monitor memU32 0x4C000014 = 0x00000003 #CLKDIVN 200:100:50
monitor memU32 0x4C000018 = 0x00000000 #CAMDIVN
#MEMCTRL
monitor memU32 0x48000000 = 0x2201D110 #BWSCON
monitor memU32 0x48000004 = 0x00000700 #BANK0-5
monitor memU32 0x48000008 = 0x00000700
monitor memU32 0x4800000c = 0x00000700
monitor memU32 0x48000010 = 0x00001F44 #bank3 cs8900
monitor memU32 0x48000014 = 0x00000700
monitor memU32 0x48000018 = 0x00000700
monitor memU32 0x4800001C = 0x00018005 #BANK6-7
monitor memU32 0x48000020 = 0x00018005
monitor memU32 0x48000024 = 0x008C04F5 #REFRESH 2^11 + 1 - HCLK* 7.8 = 1269 = 4F5
monitor memU32 0x48000028 = 0x000000B1 #BANKSIZE
monitor memU32 0x4800002C = 0x00000030 #MRSRB6-7
monitor memU32 0x48000030 = 0x00000030

break boot_card
load
continue


+++++++++++++++++
编译 hello 程序,正常运行了,接着再搞网络。

Etual
20140108
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值