基于uboot的2410调试平台的实现

调试及优化

3人已加入

描述

 

  关于这个东东,开始的时候,笔者是因为木有钱买仿真机,而且被一遍一遍的烧写nand flash折腾的很烦躁,因为nand flash的烧写速度并不像下载到SRAM或者SDRAM里边那么快。而且相当nand的寿命有限,烧写有风险,每次都是heart hard-beating下完成的,生怕nand挂了或者CPU挂了,sigh......生亦何哀,死亦何苦。有痛如斯,夫复何求?!无奈当时对于ARM的MMU还不是很熟悉,而且当时是一边上班一边业余折腾,遇到问题了就有点躁。痛定思痛,长痛不如短痛!咬着牙花了一晚上把MMU看了两遍,结果发现有好几种配置方式,让人抓狂哇!哈哈,想想当时真的很傻很天真,就因为有多种配置方式,段式,页式,页式还分个粗细,就不知道到底该用哪个更合适,后来想到linux下用哪个方式咱就用哪个方式,然后抱着这个想法去看linux内核代码,结果不了了之--没看明白,HOHO~~~~~~~~不过后来是在一个关于ARM MMU的例程中找到了定心丸,就用段式映射,这个最简单!当时还不知道看SAMSUNG的代码,很多代码都是网上杂七杂八搜罗过来的。原理弄明白,方案定下来之后,事情就好办多了,一步一步实施就是了,无非是代码出问题了再调试。

  原理其实是这样的,首先移植一个可以用的uboot,至少要包含tftp和go命令,然后将其烧到nand flash里边,每次系统上电的时候能顺利运行uboot;然后我们将编译链接好的目标代码通过uboot下载到SDRAM里边,再从uboot里边go到我们自己的程序去运行。

  实施过程中遇到的几个问题如下:

  1、代码的存储位置和运行位置的问题

  2、中断向量表的位置问题

  3、中断入口配置

  第一个问题中关于两个位置的问题,这应该是连接器要处理的,这个问题不是这里的阐述重点,有兴趣的可以参考《arm学习报告》系列文档,里边基本讲的非常详细,而且不像GNU Ld那么长篇大论。虽然这个问题不是咱的重点,但是多少对咱是有影响的,不然.............讲讲到底怎么影响咱的是正事,废话就不扯了,嘿嘿,因为,废话已经扯了很多了,GAGA~~~~~~~~~。因为从原理上来看,我们自己编写的程序用这种方式来调试的话,就不可能再放到0地址开始,让系统自动加载了,因此存储地址和运行地址都不能直接用默认的0了,这个地址需要我们在链接脚本里边亲自指定一下。为了节省大家时间,笔者在尼度给俩例子吧,一个是源代码里边的链接脚本文件,一个是链接脚本的书写规则。

  SECTIONS {

  .text

  0x30004000

  :

  {

  head.o

  clock.o

  init.o

  led.o

  serial.o

  timer0.o

  mmu.o

  interrupt.o

  main.o

  }

  }

  这个是链接脚本,其中的 0x30004000地址前面的text是指如下内容全是文本段。关于文本段如果您不想看别的资料,就简单的理解成是代码段吧。实际也是代码的运行地址,更确切的说是运行地址的开始,就是我们目标代码的入口地址。链接以后,程序在执行时的一些相对跳转中,这个地址就是个基地址了。如果在把程序从别的介质加载到运行内存(SDRAM)时,地址发生了错误,有些程序就无法正常执行,这就是位置相关和位置无关代码的区别。

  下面是我注释的一个lds文件的书写规则,估计大多数看官都能很快看明白,当然,能把lds的书写规则系统的研究研究,绝对是大有裨益。

  

SDRAM

 

  可能以上内容讲的不够详细,但是木有办法,如果这些东西对于您理解这些东西来说还不够的话,那么强烈建议您认真阅读下《arm学习报告》系列文档,共有3篇,《arm学习报告001》、《arm学习报告002》、《arm学习报告003》,因为那个里边对这个分析的是比较到位的,而且篇幅并不大,绝对值得品味的,笔者也就不再好意思再搁这废话了。

  之所以讲以上关于链接的问题,就是因为我们的程序最后不可能放到0地址,然系统一上电就自动去运行,而是要放到SDRAM里边去,然后从uboot里边go过去。

  如果是一个非常简单的程序,不涉及中断的,那么只讲讲上面的内容,加上笔者推荐的几篇文档,差不多足够了。但是这样玩起来就太没意思了,只够点个流水灯而已!如果加上中断,那差不多就把ARM的体系全弄明白了吧。接下来就切入ARM的中断。

  ARM的中断体系实际上也不复杂,向量中断一共就那么8个,reset一个,几乎是个CPU都会有这玩意,就像男人的撒尿工具。然后就是什么未定义的一个,软中断,预取终止,数据终止,中间还有个未使用的,后面就生外部中断和快中断了。这8个里边我们用到最多的也就是reset、外部中断这两个,连快中断都比较少用。

  reset就是一个入口,CPU在上电的时候先找她!如果您有什么工作希望CPU在上电之后就做的话,您也找她!

  外部中断的入口用处是非常强大的,因为一切外部中断源都要经过他。2410上的外部中断实际上是这样安排的,首先在系统的向量中断中安排了外部中断这一级,然后在外部中断中又安排了下一级的中断表,这一级就不再是向量式的了,但是这一级的中断入口都是隔4个字节放置一个,即每个入口的地址用4个字节来描述。这就是2410的二级中断表。第二级的中断表其实每个地址也是固定对应一个中断源的。算了,还是废话少说,上代码。

  _start:

  @ 0x00: 中断向量表并非从0地址开始放置,因为我们使用的直接SDRAM调试时,中断入口是需要通过MMU来映射的

  @Reset:

  b

  Reset

  @直接在SDRAM中调试的话,实际是不使用Reset的,因此一Reset,硬件系统将从nand flash中读取uboot来执行,所以此处实际是个空语句处理

  @ 0x04: Undefined instruction exception

  HandleUndef:

  b

  HandleUndef

  @ 0x08: Software interrupt exception

  HandleSWI:

  b

  HandleSWI

  @ 0x0c: Prefetch Abort (Instruction Fetch Memory Abort)

  HandlePrefetchAbort:

  b

  HandlePrefetchAbort

  @ 0x10: Data Access Memory Abort

  HandleDataAbort:

  b

  HandleDataAbort

  @ 0x14: Not used

  HandleNotUsed:

  b

  HandleNotUsed

  @ 0x18: IRQ(Interrupt Request) exception

  ldr

  pc,HandleIRQAddr

  @

  ldr

  pc,=HandleIRQ

  @ 0x1c: FIQ(Fast Interrupt Request) exception

  HandleFIQ:

  b

  HandleFIQ

  这几行是最基本的,不用讲也该明白。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分