QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3200|回复: 3

2.4.24-uc0内核移植到44B0X问题集1

[复制链接]
发表于 2004-10-20 11:31:37 | 显示全部楼层 |阅读模式
uclinux-2.4.24-uc0支持44B0X开发板----异常处理向量表的处理

由于Flash在地址0,所以uclinux不能修改存储于Flash 0 地址的异常向量表。在Flash 0地址我们存放以下跳转指令(DRAM_BASE = 0C000000):
b      ResetHandler               ;    Reset        
ldr    pc, =(DRAM_BASE + 0x04)    ;    HandlerUndef
ldr    pc, =(DRAM_BASE + 0x0    ;    HandlerSWI
ldr    pc, =(DRAM_BASE + 0x0C)    ;    HandlerPabort
ldr    pc, =(DRAM_BASE + 0x10)    ;    HandlerDAbort
ldr    pc, =(DRAM_BASE + 0x14)    ;    HandlerReserved
ldr    pc, =(DRAM_BASE + 0x1    ;    HandlerIRQ
ldr    pc, =(DRAM_BASE + 0x1C)    ;    HandlerFIQ
Reset之后调用Bootloader的ResetHandler,而其他异常模式都跳转到内存首地址的另一份中断向量表中。在DRAM_BASE位置,我们的Bootloader将会安装另一份异常向量表:
BootloaderEVBegin   ; Bootloader s own Exception Vectors
    b .    ; Should be installed into DRAM_BASE
    ldr pc, pHandlerUndef
    ldr pc, pHandlerSWI
    ldr pc, pHandlerPabort
    ldr pc, pHandlerDabort
    b .    ; HandlerReserved
    ldr pc, pHandlerIRQ
    ldr pc, pHandlerFIQ
   
pHandlerUndef DCD HandlerUndef
pHandlerSWI DCD HandlerSWI
pHandlerPabort DCD HandlerPabort
pHandlerDabort DCD HandlerDabort
pHandlerIRQ DCD HandlerIRQ
pHandlerFIQ DCD HandlerFIQ
BootloaderEVEnd    ; Bootloader s own Exception Vector End
在Bootloader的ResetHandler函数中,我们会将自己(Bootloader)从Flash中搬移到内存高地址中运行,并将上面的Exception Vectors安装到内存首地址。

这样做我们相当于有了两级的跳转表,当有异常(IRQ)发生时,首先跳转到0x18,这里又是一条跳转指令,再到DRAM_BASE + 0x18,执行中断处理函数。而uclinux的异常向量表只要安装在这里就可以了。

为此,我们需要修改uclinux内核的include/asm-armnommu/proc-armv/system.h头文件,将vectors_base()这个宏修改为内存首地址:
#if defined(CONFIG_BOARD_SAMPLE44B0X)
#undef vectors_base()
#define vectors_base() (DRAM_BASE)
#endif

当uclinux kernel运行到start_kernel()函数(init/main.c),调用trap_init()函数(arch/armnommu/kernel/traps.c),trap_init()将调用__trap_init((void *)vectors_base());来安装它的异常向量表,这个函数在entry_armv.S源文件中,代码的注释如下:
  .equ __real_stubs_start, .LCvectors + 0x200

.LCvectors:
  swi SYS_ERROR0
  b __real_stubs_start + (vector_undefinstr - __stubs_start)
  /*
   * vector_undefinstr - __stubs_start 等于vector_undefinstr()函数相对于__stubs_start的偏移
   * 我们最终会将.LCvectors复制到0c000000,__stubs_start ~ __stubs_end之间的代码复制到0c000000 + 0x200的位置
   * __real_stubs_start是一个宏,是相对于PC的偏移量。
   */
  ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)
  b __real_stubs_start + (vector_prefetch - __stubs_start)
  b __real_stubs_start + (vector_data - __stubs_start)
  b __real_stubs_start + (vector_addrexcptn - __stubs_start)
  b __real_stubs_start + (vector_IRQ - __stubs_start)
  b __real_stubs_start + (vector_FIQ - __stubs_start)
  ......
ENTRY(__trap_init) /* 此时 r0 = vectors_base() = 0c000000 */
  stmfd sp!, {r4 - r9, lr}

  mrs r1, cpsr   @ code from 2.0.38
  bic r1, r1, #MODE_MASK  @ clear mode bits
  orr r1, r1, #I_BIT|F_BIT|MODE_SVC @ set SVC mode, disable IRQ,FIQ
  msr cpsr, r1
  /* 以上代码切换CPU status */
  ......
  adr r1, .LCvectors   @ 安装异常向量表到0c000000
  ldmia r1, {r2, r3, r4, r5, r6, r7, r8, r9}
  stmia r0, {r2, r3, r4, r5, r6, r7, r8, r9}
  ......
#ifdef CONFIG_CPU_S3C44B0X
  /*
   * Initialize the IRQ-Controller to use non-vectored mode
   * We will use the S3C44B0X_I_ISPR register to determine
   * the current interrupt to be serviced.
   */
  adr r4, .INTCON
  ldr r4, [r4]  
  /* non-vectored and enable FIQ/IRQ controlling */
  ldr r3, =0x4
  str r3, [r4]
  /* 以上代码设置44b0x的中断模式控制寄存器,参考44b0x的datasheet。*/
  
  mov r4, r0
  /* 保存 r0 = 0c000000 */
#ifdef CONFIG_BOARD_SAMPLE44B0X // John modififed
  add r0, r0, #(8*4)  @ R0 = 0x0c000080 (RAM)
  /* 设置vector-mode Interrupt vectors的首地址,原先的代码不适合我们的开发板 */
#else
  mov  r0, #(0x0080)  @ R0 = 0x0080 (RAM)
  /* 这是原先的代码,指向Flash地址 */
#endif /* CONFIG_BOARD_SAMPLE44B0X */
  add r1, r1, #(8*4)  @ R1 = start of vectors (ROM)
  add r2, r1, #(32*4)  @ R2 = end of vectors (ROM)
2:  ldr r3, [r1], #4
  str r3, [r0], #4
  cmp r1, r2
  blt 2b
  /* 以上代码复制vector-mode interrupt vectors到 0c000080,对于44b0x而言没有意义,因为是non-vector 模式 */
  mov r0, r4
  /* 恢复r0 = 0c000000 */
#endif /* CONFIG_CPU_S3C44B0X */
  add r2, r0, #0x200
  adr r0, __stubs_start  @ copy stubs to 0x200
  adr r1, __stubs_end
1:  ldr r3, [r0], #4
  str r3, [r2], #4
  cmp r0, r1
  blt 1b
  /*
   * copy __stubs_start ~ __stubs_end之间的代码,到0c000200位置,
   * 这段代码包括除了vectors_swi()之外的所有异常处理函数定义
   */
  LOADREGS(fd, sp!, {r4 - r9, pc}) /* 返回 */

以上是uclinux安装异常处理向量表的过程,也因此,在arch/armnommu/Makefile中,TEXTADDR不能定义为DRAM_BASE(0x0c000000),否则,当uclinux kernel解压到DRAM_BASE处,并且运行到__trap_init()时,会覆盖掉一部分代码。

在uclinux 2.4.24-uc0内核中,也有对MBA44这块开发板的支持,他的思路与上述有些不同,
首先,它不修改vectors_base()宏,所以vectors_base() = 0。
其次,在arch/armnommu/kernel/head-armv.S源文件中,在最开始有Exception Vectors,所以MBA44在arch/armnommu/Makefile中定义的

TEXTADDR倒是0x0c000000,它不需要__trap_init(),所以比较好的做法应该是把上面说到的安装.LCvectors,安装__stubs_*的代码都注释起

来,为什么他没有注释,因为它没有设置vectors_base(),所以对Flash的写操作都不成功就是了。这是没什么问题,不过真的没有问题么?
ENTRY(stext)
#if defined(CONFIG_CPU_S3C44B0X)
/*
* We assume that there is a bootloader that has jump instructions at all
* exception vectors that lead to their position shifted to the start of
* RAM. Further on we assume that the following code gets linked to the
* start of RAM, so that all jumps match again.
*/
  b    99f   /* 0x00 reset vector */
  b vector_undefinstr /* 0x04 undefined instruction  */
  b vector_swi  /* 0x08 software interrupt */
  b vector_prefetch  /* 0x0C prefetch abort */
  b vector_data  /* 0x10 data abort */
  b vector_addrexcptn /* 0x14 address exception */
  b vector_IRQ  /* 0x18 IRQ */
  b vector_FIQ  /* 0x1C FIQ */
99:
#endif
发表于 2004-10-21 12:16:56 | 显示全部楼层
谢谢!
回复

使用道具 举报

发表于 2004-10-26 09:59:19 | 显示全部楼层
特地来顶一下
回复

使用道具 举报

 楼主| 发表于 2004-10-27 08:57:58 | 显示全部楼层
呵呵,多谢斑竹,多谢yiwujin兄,以后多多交流。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-5 20:34 , Processed in 0.064122 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表