您的位置:首页 > 其它

基于S3C4510B的一个简单BSP的开发报告

2008-01-22 12:53 387 查看
2007-12-24 13:29:14







基于S3C4510B的一个简单BSP的开发报告

系统环境
(一) 硬件环境
CPU:S3C4510B
SDRAM:W981216DH 16M
FLASH:MX29LV160AB 2M
(二) 软件环境
tornado2.01 for arm(AKA的FTP上有tornado2.2需要的可以自己去下载:))
(三) 调试环境
TRACE32`

TRACE32

(一)利用TRACE32调试vxWorks
S3C4510B在系统上电时,CPU寄存器的基地址为0X3FF0000,利用TRACE32直接对CPU进行初始化,分配内存布局,初始化SDRAM,然后再加载vxWorks.st进行系统调试。
脚本如下:
; t32initial script for s3c4510b
; initial s4510b sdram and flash
d.s 0x03ff0000 %l 0x87ffffa0
d.s 0x03ff3010 %l 0x00003001
d.s 0x03ff3014 %l 0x12040060
d.s 0x03ff3018 %l 0x60
d.s 0x03ff301c %l 0x60
d.s 0x03ff3020 %l 0x60
d.s 0x03ff3024 %l 0x60
d.s 0x03ff3028 %l 0x60
d.s 0x03ff302c %l 0x10000398
d.s 0x03ff3030 %l 0x00
d.s 0x03ff3034 %l 0x00
d.s 0x03ff3038 %l 0x00
d.s 0x03ff303c %l 0xce2983fd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; s3c4510b board - load coff file TRACE32 script file
B::
sYmbol.RESet

; load coff file
d.load.coff e:/s4510b_bsp/vxWorks.st /spath /lpath
r.s pc 0x1000

; load symbol path
y.spath + e:/s3c4510b_bsp/
y.spath + d:/tor_arm/target/src/netwrs
y.spath + d:/tor_arm/target/src/netinet

ENDDO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1:初始化CPU
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/syscfg.jpg" align=baseline border=0>
d.s 0x03ff0000 %l 0x87ffffa0 二进制为1000,0111,1111,1111,1111,1111,1010,0000
[05:04] = 10b 为8-Kbyte SRAM 0-Kbyte Cache
[15:06] = 1111111110b = 0x3FE SRAM的起始地址为0x3FE0000
[25:16] = 1111111111b = 0x3FF CPU寄存器基地址为0x3FF0000
[31] = 1b SDRAM
2:初始化内存布局

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/extdbwth.jpg" align=baseline border=0>
d.s 0x03ff3010 %l 0x00003001二进制为 0000,0000,0000,0000,0011,0000,0000,0001
[01:00] = 01b FLASH bank0数据总线为BYTE(8-BIT)
[13:12] = 11b SDRAM bank0 数据总线为 DWORD(32-BIT)
其他全部disable

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/flashcfg.jpg" align=baseline border=0>
d.s 0x03ff3014 %l 0x12040060二进制为 0001,0010,0000,0100,0000,0000,0110,0000
[01:00] = 00b NormalROM
[03:02] = 00b 5 cycles (Page address access time (tPA))
[06:04] = 110b 7 cycle (Programmable access cycle (tACC))
[19:10] = 0100000000b = 0x100 FLASH bank0基地址为0x1000000
[29:20] = 0100100000b = 0x120 FLASH bank0 结束地址为 0x1200000-1

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/DRAM.jpg" align=baseline border=0>
d.s 0x03ff302c %l 0x10000398 二进制为 0001,0000,0000,0000,0000,0011,1001,1000
[00:00] = 00b Normal SDRAM
[02:01] = 00b 1 cycle ( CAS strobe time (tCS) )
[03:03] = 01b 2 cycles(CAS pre-charge time (tCP))
[07:07] = 01b 2 cycles (RAS to CAS delay (tRC or tRCD))
[09:08] = 11b 4 cycles (RAS pre-charge time (tRP))
[19:10] = 0000000000b = 0x00 SDRAM bank0 基地址为 0x000000
[29:20] = 0100000000b = 0x100 SDRAM bank0 结束地址为 0x1000000-1
[31:30] = 00b 8bits (Number of column address bits in DRAM bank0)

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/externalcfg.jpg" align=baseline border=0>
d.s 0x03ff303c %l 0xce2983fd 二进制为 1100,1110,0010,1001,1000,0011,1111,1101
[09:00] = 1111111101b = 0x3FD External I/O bank0 的基地址为 0x3FD0000
其他各位意义请对照datasheet
内存初始化完毕后系统内存布局为:
00-16M 为 SDRAM
16-18M 为 FLASH
0x3FD0000开始64K为External I/O
0x3FE0000 开始8K为SRAM
0x3FF0000 开始64K 为CPU寄存器
3:加载vxWorks.st
d.load.coff e:/s4510b_bsp/vxWorks.st /spath /lpath 将vxWorks.st 加载到SDRAM中去
r.s pc 0x1000 设置pc指针到RAM_LOW_ADRS(0x1000)
这时就可以使用TRACE32设置断点进行调试了。
(二)利用TRACE32烧写bootrom
1:FLASH的擦除
; s3c4510b - flash erase TRACE32 script file
; flash type : AM29F100
; Erase flash by TRACE32
flash.reset
flash.create 0x1000000--0x10fffff AM29F100 WORD
flash.erase 0x1000000--0x1001fff
flash.erase 0x1002000--0x1003fff
flash.erase 0x1004000--0x1005fff
flash.erase 0x1006000--0x1007fff
flash.erase 0x1008000--0x1009fff
flash.erase 0x100a000--0x100bfff
flash.erase 0x100c000--0x100dfff
flash.erase 0x100e000--0x100ffff
…………………………………….
ENDDO
2:bootrom的烧写
;s3c4510b flash write TRACE32 script file
; flash type : AM29F100
; Write flash by TRACE32
B::
flash.reset
flash.create 0x1000000--0x10fffff AM29F100 word
flash.program all
; download *.bin file
d.load.binary E:/s4510b_bsp/bootrom.bin 0x1000000
flash.program off

ENDDO

BSP的开发流程
(一) vxWorks的执行流程
在系统开发期,我们通常利用调试工具将编译好的带调试符号的vxWorks下载到SDRAM中进行调试,所有功能调试结束后才编译生成bootrom.bin将其烧写的FLASH中。所以vxWorks有从ROM中启动和SDRAM中启动之分。

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/MEMORYLAYOUT.jpg" align=baseline border=0>
1:从SDRAM中启动vxWorks
利用TRACE32将vxWorks.st下载到SDRAM中,这时根据TRACE32脚本设置,pc指针指向0x1000,这是sysInit ()的入口点。VxWorks在正常重启下调用该函数,在sysALib.s中定义,它禁止缓存器,初始化系统中断表、系统故障表,清除所有等待的中断,调用usrInit(bootType)。
UsrInit()是vxWorks下首先运行的C程序,它需要完成创建初始任务usrRoot()所需要的工作。它首先调用bzero (edata, end - edata);清除系统bss段,保存启动类型,调用intVecBaseSet ((FUNCPTR *) VEC_BASE_ADRS); 设置中断向量表,调用excVecInit ();设置异常向量,调用sysHwInit ();初始化系统硬件,调用usrKernelInit ();配置Wind内核,最后调用kernelInit ()开始系统根任务usrRoot;
UsrRoot是运行在多任务环境下的第一个任务,它完成最后的初始化,并且启动其他任务。UsrRoot()按照configAll.h和config.h中的配置来初始化I/O系统,安装驱动程序,创建设备,设置网络等等。
在开发过程中,我们可以利用TRACE32对每一步执行进行跟踪,观察程序的执行行为,检查相关寄存器的内容;也可以写一些测试函数,对完成的相关的功能进行简单的测试,例如当我们完成了串口在轮询模式下工作的驱动程序后,我们可以写一个echo程序对串口的输入输出进行简单的检查。
2:从ROM中启动vxWorks
当我们利用TRACE32调试好一个BSP以后,这时就需要修改rominit.s这个文件了,这个文件中的romInit()是冷启动时的入口点,它将启动类型入栈,禁止中断,初始化CPU,配置SDRAM、FLASH,并转移到bootinti.c中的romStart(),它将(文本段和)数据段复制到SDRAM中的RAM_HIGH_ADRS处,并最终调用usrInit(bootType)。
在开发过程中,我们需要利用烧录工具或者调试工具将编译生成的bootrom.bin下载到FLASH之中,当系统上电时,CPU将FLASH镜像到地址0x00000000处,并开始执行,当romInit()执行完必要的操作后,它将跳转到FLASH的真实地址0x01000000处,并执行SDRAM、FLASH的初始化,这时再将SDRAM映射到0x00000000至0x00ffffff处(0-16M),将FLASH映射到0x01000000至0x011fffff(16-18M)处完成其他的执行。
(二) CPU的体系结构
S3C4510B是使用ARM7TDMI核的CPU,因此需要对ARM7TDMI有一定的了解,需要注意的是32位精简指令集的CPU对数据的操作是按一个字长(4-BYTE)进行的,所以我们在gcc的编译开关中需要用—pack-struct来消除结构体间的空白,在强制类型转换时也需要特别的注意,因为一旦一个奇数地址被解释成一个short(16-bit)或int(32-bit)类型地址时将产生异常。
(三) 利用调试工具辅助开发
在开发BSP时,有得心应手的调试工具将事半功倍。在这个项目中,我使用了TRACE32,它界面简洁,十分容易上手。
在开发初期,我们需要编写脚本文件来对CPU、SDRAM、FLASH进行初始化,为了检验初始化结果是否正确,我们可以通过对SDRAM中的地址进行读写,看看结果与我们期望的是否一致。经过了这一步,再将vxWorks.st下载到SDRAM中,通过单步运行检查代码执行是否正常,定位出错误的代码位置,反复修改直到系统正常运行为止。

硬件初始化
(一) VxWorks的行为
vxWorks在usrInit()中调用sysHwInit(),它设置所有设备进入安静状态,屏蔽所有可屏蔽的中断。sysHwInit调用sysSerialHwInit();来初始化串口设备,并且在uartDevInit()中配置串口相关寄存器,设置波特率,置串口工作模式为轮询模式。
在usrRoot()中调用sysClkConnect(),sysClkConnect立即调用sysHwInit2()来完成sysHwInit()中不能完成的工作,(因为在调用sysHwInit()时还没有初始化系统内存池,所以不能调用malloc相关的函数,例如intConnect())它调用intLibInit()初始化中断库,调用irqDevIcnit()初始化中断控制器,然后用intConnect()挂接时钟中断,调用sysSerialHwInit2()将串口设置成中断工作模式。
(二) SC34510B的中断描述
SC34510B拥有21个中断源,如下表所示:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/interruputsource.jpg" align=baseline border=0>
在这个例子中我用到了[4]、[5]、[10]这三个中断源,分别为串口0发送中断、串口0接收中断、定时器0中断。在初始化中断控制器时我们需要设置INTMOD寄存器,将中断源配置在我们需要的工作模式下,这里我将他们配置成普通中断模式(IRQ),即将[20:00]位清零。INTMOD寄存器如下图所示:

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/intmod.jpg" align=baseline border=0>
INTPND中断未决寄存器,它包含每个中断源的未决中断,需要在中断服务程序中通过对相应的位置一来清除该未决的中断。寄存器如下图所示:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/intpending.jpg" align=baseline border=0>
INTMSK中断掩码寄存器,它包含每个中断源的中断掩码,当相应的位被置一时,该中断将被屏蔽。寄存器如下图所示:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/intmsk.jpg" align=baseline border=0>
在这个例子中,我没有改变系统中各个中断源的优先级顺序,即从0开始到第21,0的优先级最高,依次递减。
(三) 中断驱动程序
在irqDevIcnit()中初始化中断控制器,它初始化中断驱动程序结构,初始化中断控制器寄存器。
在irqcLvlVecChk()中检查并返回当前优先级最高的未决中断。在这期间它设置当前中断优先级为这个未决中断的优先级,来确保在中断服务期间只允许优先级比它高的中断产生。
在irqcLvlVecAck()中重新设置当前中断为前一个中断级别。
在irqcLvlChg()中设置新的当前中断级别,所用优先级比当前中断低的(包括当前中断)将被屏蔽掉,所有比当前中断优先级高的且被允许中断的将被打开。
在irqcLvlEnable()允许指定中断产生。
在irqcLvlDisable()屏蔽一个指定中断。
(四) 串口中断
在uartDevInit()中初始化串口控制器,设置波特率,初始化串口驱动程序。在期间需要配置的寄存器如下:
ULCON0寄存器,其值设为0x03,8-bit数据位,无停止位,无奇偶位。
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/ULCON0.jpg" align=baseline border=0>
UCON0寄存器,其值设为0x00,设置接收和发送中断无效。
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/UCON0.jpg" align=baseline border=0>
UBRDIV0寄存器,设置波特率除数因子,这里我设置的波特率为38400根据公式可以计算出该寄存器的值应该为0x270。公式为(fMCLK_MHz/(32*(_rate)) - 1)这里CPU的频率为50MHZ,_rate为38400,所以CNT0的值为0x27,采用除一的方式,所以CNT1为0000b,所以该寄存器的结果为0x270。
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/UBRDIV0.jpg" align=baseline border=0>
uartPollInput()串口在轮询模式下输入处理程序。
UartPollOutput()串口在轮询模式下输出处理程序。
UartTxStartup()串口启动一个中断输出。
UartIntRX()输人中断服务程序,注意要清除输入中断相应的中断未决位。
UartIntTX()输出中断服务程序,注意要清除输出中断相应的中断未决位。
在以上几个函数中需要用到一下几个寄存器USTAT0、URXBUF0、UTXBUF0,大家自己查资料吧:)。
(五) 时钟中断
sysClkInt()为时钟中断的服务程序,在中断驱动程序初始化之后调用intConnect()注册的。
SysClkEnable()启动一个定时器,它计算每次时钟中断发生的时间间隔,并根据公式((fMCLK_MHz)/(sysClkTicksPerSecond)-1)算出TDATA0的值。设置TMOD为0x03,开启timer0,打开时钟中断。
SysClkDisable()停止一个定时器。它设置TMOD为0x00,关闭时钟中断。相关寄存器如下:

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" alt="" hspace=0 src="file:///E:/李淼的文档/TMOD.jpg" align=baseline border=0>
sysClkRateSet()设置每秒钟tick数,并通过连续调用SysClkDisable(),SysClkEnable()来更新设置。
SysClkRateGet()获取每秒钟tick数。

RomInit.s文件分析
当我们利用TRACE32开发调试完一个在RAM中运行的vxWorks后,需要修改romInit.s和bootInti.c,编译连接生成bootrom.bin,然后利用工具烧录到FLASH之中。以下是我针对S3C4510B这款CPU修改的romInit.s文件,代码及注释如下:

/* romInit.s - ARM PID ROM initialization module */
/* Copyright 1996-1999 Wind River Systems, Inc. */
.data
.globl _copyright_wind_river
.long _copyright_wind_river

/*
modification history
--------------------
;*****************************************************************************/

#define _ASMLANGUAGE
#include "vxWorks.h"
#include "arch/arm/arm.h"
#include "regs.h"
#include "sysLib.h"
#include "config.h"
#include "s4510b.h"

/* internals */

.globl _romInit /* start of system code */
.globl _sdata /* start of data */

/* externals */

.extern _romStart /* system initialization routine */

_sdata:
.asciz "start of data"
.balign 4

.text
.balign 4

/*******************************************************************************
*
* romInit - entry point for VxWorks in ROM
*
* romInit
* (
* int startType /@ only used by 2nd entry point @/
* )
* INTERNAL
* sysToMonitor examines the ROM for the first instruction and the string
* "Copy" in the third word so if this changes, sysToMonitor must be updated.
*/
_romInit:
romInit:
cold:
mov r0, #BOOT_COLD /* fall through to warm boot entry */
warm:
b start
/* copyright notice appears at beginning of ROM (in TEXT segment) */
.ascii "Copyright 2000-2001 STM / Cap Gemini."
.balign 4

start:
nop
nop
nop
nop
/*Part 1*/
/****************************************************************/
/*disable interrupts in CPU and switch to SVC32 mode*/
mrs r0, cpsr
bic r0, r0, #MASK_MODE
orr r0, r0, #MODE_SVC32
orr r0, r0, #I_BIT
orr r0, r0, #F_BIT
msr cpsr, r0

ldr r2, =ARM7_INTMASK /*R2-
mvn r1, #0 /*&FFFFFFFF*/
str r1, [r2] /*disable all interrupt soucres*/
ldr r2, =ARM7_INTPEND /*R2-
mvn r1, #0 /*&FFFFFFFF*/
str r1, [r2] /*clear all interrupt flags.*/

/*Part 2*/
/*****************************************************************/
ldr r0, =ARM7_SYSCFG
ldr r1, =0x87ffffA0 /*config SYSCFG*/
str r1, [r0] /*Cache & WB disabled*/

/*part 3*/
/****************************************************************/
/*jump to flash addr exec @16M*/

ldr lr, L$_HiPosn /* load lr with the ROM address where */
/* to jump after remap (this is an */
/* address after 0x20000000) */
mov pc, lr /* jump to address stored in lr */

/*Part 4*/
/****************************************************************/
/*Initalize the memory as followa:*/
/* FLASH @ 16 ~ 18 M*/
/* SDRAM @ 0 ~ 16M*/
HiPosn:

ldr r1, =rEXTDBWTH /*EXTDBWTH */
ldr r2, =rROMCON0 /*ROMCON0 @ 16M ~ 18M */
ldr r3, =rROMCON1 /*ROMCON1 @ DISABLED */
ldr r4, =rROMCON2 /*ROMCON1 @ DISABLED */
ldr r5, =rROMCON3 /*ROMCON1 @ DISABLED */
ldr r6, =rROMCON4 /*ROMCON1 @ DISABLED */
ldr r7, =rROMCON5 /*ROMCON1 @ DISABLED */
ldr r8, =rSDRAMCON0 /*SDRAMCON0 @ 0M ~ 16M */
ldr r9, =rSDRAMCON1 /*SDRAMCON1 @ DISABLED*/
ldr r10,=rSDRAMCON2 /*SDRAMCON2 @ DISABLED*/
ldr r11,=rSDRAMCON3 /*SDRAMCON3 @ DISABLED*/
ldr r12,=rSREFEXTCON

ldr r0, =ARM7_EXTDBWTH
stmia r0, {r1-r12}

/*---------------------------------------------------------------*/
/*
* Initialize the stack pointer to just before where the
* uncompress code, copied from ROM to RAM, will run.
*/
/*---------------------------------------------------------------*/

ldr sp, L$_STACK_ADDR
mov fp, #0 /* zero frame pointer */

/*----------------------------------------------------------------*/
/* jump to C entry point in ROM: routine - entry point + ROM base */
/*----------------------------------------------------------------*/

ldr pc, L$_rStrtInRom /* use ARM mode (no Thumb) */

/******************************************************************************/

/*
* PC-relative-addressable pointers - LDR Rn,=sym is broken
* note "_" after "$" to stop preprocessor preforming substitution
*/

.balign 4

L$_HiPosn:
.long ROM_TEXT_ADRS + HiPosn - _romInit

L$_rStrtInRom:
.long ROM_TEXT_ADRS + _romStart - _romInit

L$_STACK_ADDR:
.long STACK_ADRS

注意:上电以后FLASH将被镜像到0x00000000处,并开始执行。
这里ROM_TEXT_ADRS的值为0x01000000,当对CPU进行完必要的初始化以后它将跳转到FLASH的真实地址处进行执行,它继续完成对SDRAM的初始化,内存布局的分配等等,详细信息请参看TRACE32那一节.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐