S3C6410移植日记.

FLandY:一口气看完了这几篇文章,受益匪浅啊.
原文链接:http://hi.chinaunix.net/?uid-20582279

作者:djyos
 

S3C6410移植日记之一

应深圳友坚科技之邀,这几天要把djyos移植到他们的idea6410上。

    现在发布的是si版本,是以单片机模式运行的,S3C6410这样强劲的cpu,运行si版本,就作为高速单片机用了,所有地址都是按照物理地址一一对应映射。cpu的状态也没有区分内核态和用户态。
1
、中断引擎最初的部分代码在IRQ态(还没决定是否使用FIQ)。
2
、中断引擎的大部分以及用户ISR运行在SVC态。
3
、所有其他代码运行在SYS态。

    移植碰到的第一个问题就是烧录代码到flash的问题,由于廉价的jtag烧录器不支持arm11,我们不能要求用户必须拥有昂贵的仿真烧录工具才能够在idea6410上使用djyos,这样不利于用户使用。

    我的第一个目标,就是弄清楚怎么下载程序的问题,也就是把一个最简单的闪灯程序运行起来,写了几行代码,如下:
    ldr     r0,=0x7f008820
    ldr     r1,=0x1111
    str     r1,[r0]
    ldr     r0,=0x7f008824
    ldr     r1,[r0]
    bic     r2,r1,#3
    orr     r2,r2,#0xc
    bic     r3,r1,#0xc
    orr     r3,r3,#3
nn:
    str     r2,[r0]
    ldr     r4,=5000000
delay1:
    sub     r4,r4,#1
    cmp     r4,#0
    bne     delay1
    str     r3,[r0]
    ldr     r4,=5000000
delay2:
    sub     r4,r4,#1
    cmp     r4,#0
    bne     delay2
    b       nn


    6410
的手册上说,可以从nandflashonenandSD卡启动,没有专用的烧录工具的情况下,只有SD卡启动是可以考虑的。手册上看到,SD卡启动,实际上是先执行片内IROM中的一段程序,该程序从SD卡中读取代码,写到stepping stone中,stepping stone是位于0x0c000000size8K的片内内存,代码写入stepping stone后,跳到0x0c000000处继续执行程序。那么,要实现从SD卡启动,就必须弄清楚:
1
8K的代码保存在SD卡的什么位置。
2
、代码以什么格式存储。

    为弄清楚上述问题,依例google一番,没找到有用的资料,上三星的网站,6410的资料没有公开,申请了一下,第二天得到了批准,也没有关于怎样从SD卡启动的资料。找三星代理,似乎不太爱搭理我,也是,我势单力薄一个人,他们怎看得上眼。难道就没有办法了?

    山穷水尽疑无路,柳暗花明又一村,2450不是也可以从SD卡启动吗?找找2450的资料看有没有,谢天谢地,从网上找到一篇文档:
896554S3C2450_IROM_ApplicationNote_Rev003.pdf
我如获至宝,细细读之,虽然写得不太细,比如代码校验算法等都没有讲,总是可以试一下了。

    依葫芦画瓢,把编译好的代码写入到最后芯片末尾偏移-9216字节处,插入SD卡座,把开关拨到SD0卡启动的位置,上电,哈哈,成功了,几个蓝色的LED欢快地闪烁起来。试了两个SD卡,16M的可以,2G的不行,不知何故,暂且放一边吧。

    首战告捷,该歇歇了,待续。

 

 

S3C6410移植日志之二

    上篇说道,用16MSD卡启动可以,但用2G的卡却不行,反复试过,实在不知道怎么回事,也没有IROM中的加载程序的进一步资料,问题也就无从查起了,暂且先放一边,把后续的移植工作做完再说吧。

    移植操作系统,跟开发裸奔程序是不一样的,裸奔程序可以从main开始写程序,在执行main之前,编译器产生了大量的代码用于初始化cpu、内存清零、初始化堆和栈、直到建立main的执行环境。而操作系统往往有自己的运行环境要求,C编译器完成的这些环境往往不能符合要求,需要自己写初始化文件,即initcpu.s文件。

    初始化文件主要完成以下工作:
1
、从复位地址跳转到启动地址。
2
、设置cpu为特权模式,禁止看门狗和中断,禁止cache
3
设置时钟,有些cpu的时钟设置很复杂的,尤其是高速cpu,因为涉及到内核和外设匹配的问题,设置起来比较麻烦。
4
、设置内存总线,设置内存访问速度,要跟上一步的时钟设计配合,使cpu能正确读写内存和内存映射的外设。
5
、配置cachemmu,然后使能cachemmu
6
、初始化栈,跳转到C代码。

    根据拿来主义的原则,写cpu初始化代码千万不能自己从0开始写,而是要找一个现成的来参考,因为各个系统的cpu初始化工作是大同小异的。而且,许多cpu厂商都会出example,会带一个文件名类似startup.s的文件,参考该文件来写即可。但是,三星不知从何年何月开始不公开其cpu的文档了,甚至连datasheet都要申请才给。当我千辛万苦找到三星提供的“6410_Test_Rev01”源代码包时,心都凉了,该代码包中虽然有start.s文件,但文件中只有几条指令,初始化过程都在"__rt_entry“函数中,而该函数在库中。对芯片应用资料的保密工作做得如此周密,不知三星所谋何事。

    没办法,继续找,实在不行再自己一行行写。好在天无绝人之路,终于在友坚提供的winceeboot代码中,找到了ebootstart.s文件,打开一看,果然是一个详细的启动文件,心中不禁狂喜!

    接下来的工作,就是对照datasheet,看懂这个start.s,然后改造成适合djyos的。别看说的轻巧,这里面工作量还是很大的,6410datasheet1300多页,光时钟和总线配置相关的部分就有100多页,E文的,晕死。而且第一次用arm11,其mmucache配置和arm9有多大差别,还不可知。今天先写到这里,下回分解吧。

 

S3C6410移植日志之三

接续上回,开始啃start.s,跟所有的启动文件一样,开始部分是关闭cache、禁止中断等,没什么问题。这里稍稍解释一下为什么要做这些工作,禁止中断大家应该没什么异议,关键是为什么一定要禁止cache,原来,我们不知道程序为什么要重新启动,也不知道重新启动前cpucache处于什么状态,cache可能包含错误的信息,cpu可能会从中取得错误的指令,从而不能正常启动系统ebootstart.s遗漏了一个很重要的过程,就是要重新把cpu设置成svc状态,因为就像我们不了解重启动前cache状态一样,cpu的状态也是未知的,须加上这几句确保cpu处于svc态:
    mrs     r0,cpsr                 @
CPSR
    bic     r0,r0,#MODEMASK         @
清模式位

    orr     r1,r0,#SVCMODE|NOINT    @
设置为管理态,并禁止中断
    msr     cpsr_cxsf,r1            @
切换到管理态,可防止意外返回0地址时出错.
   
实际上,这几句仍然不够保险,因为如果程序是从user态直接跳转到0地址的话,mrsmsr指令是无效的。保险的做法是用swi指令强制修改,既然是个简易的bootloader程序,暂且偷懒一下。

   
依惯例,接下来是各种时钟初始化,S3C6410的时钟结构比较复杂,共有3pll设置,而且分频控制也较为复杂,虽然start.s有得抄,但还是要自己弄清楚,因为接下来的编程用得上。6410的时钟部分之所以如此复杂,完全是为了适应其内部丰富的外设,不同的外设需要不同的时钟。设置时钟,不外乎就是定义几个常用的主频,然后分别为这些主频定义锁相环(pll)的分频系数,再把这些分频系数填充到相应的寄存器中去,细节就不再赘述了,看代码吧。 
   
初始化完时钟后,就轮到初始化内存总线了。依据用什么初始化什么的原则,这里只初始化了srom0dram两个区域,这部分代码是用C语言实现的,参见memcfg.c文件,代码比较简单,不过是按照datasheet的要求,依次设置寄存器而已。

   
接下来,你一定会想到,该初始化mmu了,初始化mmu本来是一项复杂的工作,但si版本是为单片机准备的,即使6410再强劲,也只能委屈一下,当高速单片机了。mmu在这里并没有用来做地址变换,而是把4G内存空间全部映射到其物理地址上了。这种映射效果跟禁止mmu是一样的,但是armmmucache是绑定在一起的,禁止mmu的同时也就禁止了cache,故只能打开mmu。页表的地址在0x50000000,占用16Kbytes,故应用程序的起始地址是0x50004000
   
又可以偷懒了,6410的核是arm11jzf-s的,2440的核是arm920T的,arm11jzf-smmu功能比arm920t的强很多,但都是arm公司的,做最简单映射的话,能否兼容呢?懒得读arm11的手册了,先试一下把2440版本的mmu初始化部分直接copy看行不行。事实证明是可行的,但我在这里绕了一个大大的圈子,浪费了许多时间。加入初始化mmu部分代码后,试了一下,发现灯不闪了,而把该段程序放到初始化页表的代码之前,则可以。仔细检查,发现是因为dram没有初始化,加上dram初始化后,先把闪灯程序放在dram初始化后面,发现可以了。这时候,不幸发生了,移动闪灯程序时,只copy了一半的代码,当然不闪了,可我没仔细检查代码,就怀疑是2440mmu初始化代码不能用于6410的造成的(偷懒了,心虚),于是找来arm11jzf-s的手册猛啃,几百页的英文资料啊,费了好几天功夫,最后证明了一件事:原来的mmu初始化是正确的!!
   
到这里,基本硬件的初始化就算完成了,接下来要搞norflashuartdriver了。待续……

 

S3C6410移植日至之四

    之三讲到,cpu的初始化已经完成,下一步的工作便是初始化uart,使之能够跟PC连接上。
   
初始化6410uart,有两个时钟必须区分清楚,即uartclkbaudclk,前者由系统控制寄存器CLK_SRCCLK_DIV2控制,手册并没有说明这个时钟的用途,我猜测是用于uart模块本身运行的;另一个时钟是baudclk,用来控制baud,产生串行移位时钟的,在uart模块的控制寄存器UCON设置,然后用UBRDIVUDIVSLOT0两个寄存器设置bauduart的工作方式为:
baud=115200
接收和发送fifo:开
中断:关闭,以查询方式收发。
   
接下来是norflash的驱动程序,也就是编写擦除和写入程序,根据am29lv160db的手册写就是了,没什么好说的。除了一些低级错误外,测试也几乎一次成功。
   
至此,该轮到xmodem协议收发程序了,xmodem是一个简单的串口收发文件协议,它把文件分成128字节的一个个小包传送,最后一包数据如果不满128字节,则以0x1a填充。该协议是有缺陷的,用来传送文本文件没问题,因为文本文件不会出现0x1a,但传送2进制文件的话,就不行了,因为接收方无法分辨最后的0x1a是文件本身的内容,还是填充物。不过没关系,作为代码,最后多一些垃圾并不碍事,无非就是多占几个字节而已。
    xmodem
本来是有差错控制的,通过逐帧应答和校验和(或者CRC)来确保传输正确,不过这里偷了下懒,所有这些都省略了,传错了就再传一次。
   
至此,移植S3C6410的第一步,sdbootloader就制作完成了,接下来就是移植整个操作系统了,sdbootloader的代码在这里下载:
   http://www.djyos.com/download/sdboot6410.zip

 

6410sdbootloader完成了

 sdbootloader说明:
1
、用winhex工具把boot_rom.bin写入SD卡,地址:SD卡末地址-9216
2
、把开发板的拨码开关拨到从SD卡启动,上电即可。
2
、打开超级终端,用xmodem协议下载程序,保存到dram中。
3
、把下载的代码写入到norflash
4
、把开发板的拨码开关拨到从norflash启动,复位或重新上电即可。
5
、省去了xmodem帧格式检查、校验和检查。

   
但凡开发操作系统,无论是PC服务器,还是嵌入式操作系统,第一个要解决的就是启动文件的存储问题。无论什么cpu,上电或者复位后,都会从指定的存储位置读取第一条指令予以执行,我们把这个地址成为启动向量,有些cpu可以通过跳线设置不同的启动向量地址。我们熟悉的PC,就是把bios烧录到启动向量处,再由bios逐步引导启动更高级的操作系统,比如windowslinux等。
   
在嵌入式行业,以linux为例,linux映像可以通过网口或者其他通信口下载,但你拿到裸机的时候,必须先想办法把uboot或者vivi或者其他bootloader烧录到flash中。djyos也不例外,不同的是,现在发布的si版本的djyos,是没有单独的bootloader的,而是把bootloader的角色集成在可执行影像中了,所以,需要像烧录uboot那样,烧录整个djyos影像。
   
s3c6410之前,djyos发布了arm744b0)和arm924102440)两个版本,得益于廉价的arm7arm9仿真烧录器,比如hjtagarm这两个版本是通过hjtag或者jlink或其他工具直接烧录到norflash上的。但s3c6410arm11的核,这些廉价工具不支持arm11,支持arm11的烧录工具都在数千元以上,这样势必影响大家使用djyos。要让6410执行djyos,必须解决在没有专用烧录工具的情况下,把djyos烧录到启动设备上的问题。
    6410
一共支持4种启动设备:norflashnandflashSD卡、modem,其中norflashnandflash必须使用专用烧录工具,modem则需要了解其通信协议,编写相应的PC应用程序,相比之下,SD卡最为简单,可以用普通的读卡器+winhex工具就可以完成写入。但有一个限制,就是6410启动时只从SD卡中读取8K代码到内部ram中(6410手册第二章说4K,第八章说8K,实测是8K)。读入代码后,程序就跳转到内部ram中执行,这8K程序,只能做一个简易bootloader,用这个bootloader去加载整个操作系统,这时候,就有两种选择:
1
、把程序写到SD卡的其他地方,   但这种方法不现实。SD卡是用nandflash做的, 必然要做ECC校验,那么把代码写入SD卡时,要么用文件系统,但8K代码根本做不了文件系统;要么在PC端用支持ECC的专用写卡工具,可惜没有找到。
2
、用串口下载,这是传统方法,PC端的工具很多,最通用的是超级终端了。
   
我们选择了超级终端,xmodem协议下载。
   
代码比较简单,说明见“s3c6410移植日志x”系列,下载源代码:http://www.djyos.com/download/sdboot6410.zip

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值