基于S3C4510B的一个简单BSP的开发报告
系統(tǒng)環(huán)境
(一)? 硬件環(huán)境
CPU:S3C4510B
SDRAM:W981216DH 16M
FLASH:MX29LV160AB 2M
(二)? 軟件環(huán)境
tornado2.01 for arm(AKA的FTP上有tornado2.2需要的可以自己去下載:))
(三)? 調(diào)試環(huán)境
TRACE32`??? ??
?
TRACE32
(一)利用TRACE32調(diào)試vxWorks
S3C4510B在系統(tǒng)上電時(shí),CPU寄存器的基地址為0X3FF0000,利用TRACE32直接對CPU進(jìn)行初始化,分配內(nèi)存布局,初始化SDRAM,然后再加載vxWorks.st進(jìn)行系統(tǒng)調(diào)試。
腳本如下:
; 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
???
d.s 0x03ff0000 %l 0x87ffffa0 二進(jìn)制為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:初始化內(nèi)存布局
?
d.s 0x03ff3010 %l 0x00003001二進(jìn)制為??? 0000,0000,0000,0000,0011,0000,0000,0001
[01:00] = 01b FLASH bank0數(shù)據(jù)總線為BYTE(8-BIT)
[13:12] = 11b SDRAM bank0 數(shù)據(jù)總線為 DWORD(32-BIT)
其他全部disable
?
d.s 0x03ff3014 %l 0x12040060二進(jìn)制為 0001,0010,0000,0100,0000,0000,0110,0000
[01:00] = 00b NormalROM
[03:02] = 00b 5 cycles ( Page address access time (t PA ) )
[06:04] = 110b 7 cycle ( Programmable access cycle (t ACC ) )
[19:10] = 0100000000b = 0x100 FLASH bank0基地址為0x1000000
[29:20] = 0100100000b = 0x120 FLASH bank0 結(jié)束地址為 0x1200000-1
?
d.s 0x03ff302c %l 0x10000398 二進(jìn)制為 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 結(jié)束地址為 0x1000000-1
[31:30] = 00b 8bits ( Number of column address bits in DRAM bank0 )
?
d.s 0x03ff303c %l 0xce2983fd 二進(jìn)制為 1100,1110,0010,1001,1000,0011,1111,1101
[09:00] = 1111111101b = 0x3FD External I/O bank0 的基地址為 0x3FD0000
其他各位意義請對照datasheet
內(nèi)存初始化完畢后系統(tǒng)內(nèi)存布局為:
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 設(shè)置pc指針到RAM_LOW_ADRS(0x1000)
這時(shí)就可以使用TRACE32設(shè)置斷點(diǎn)進(jìn)行調(diào)試了。
(二)利用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的開發(fā)流程
(一)? vxWorks的執(zhí)行流程
在系統(tǒng)開發(fā)期,我們通常利用調(diào)試工具將編譯好的帶調(diào)試符號(hào)的vxWorks下載到SDRAM中進(jìn)行調(diào)試,所有功能調(diào)試結(jié)束后才編譯生成bootrom.bin將其燒寫的FLASH中。所以vxWorks有從ROM中啟動(dòng)和SDRAM中啟動(dòng)之分。
?
1:從SDRAM中啟動(dòng)vxWorks
?????? 利 用TRACE32將vxWorks.st下載到SDRAM中,這時(shí)根據(jù)TRACE32腳本設(shè)置,pc指針指向0x1000,這是sysInit ()的入口點(diǎn)。VxWorks在正常重啟下調(diào)用該函數(shù),在sysALib.s中定義,它禁止緩存器,初始化系統(tǒng)中斷表、系統(tǒng)故障表,清除所有等待的中斷, 調(diào)用usrInit(bootType)。
??????? UsrInit() 是vxWorks下首先運(yùn)行的C程序,它需要完成創(chuàng)建初始任務(wù)usrRoot()所需要的工作。它首先調(diào)用bzero (edata, end - edata);清除系統(tǒng)bss段,保存啟動(dòng)類型,調(diào)用intVecBaseSet ((FUNCPTR *) VEC_BASE_ADRS); 設(shè)置中斷向量表,調(diào)用excVecInit ();設(shè)置異常向量,調(diào)用sysHwInit ();初始化系統(tǒng)硬件,調(diào)用usrKernelInit ();配置Wind內(nèi)核,最后調(diào)用kernelInit ()開始系統(tǒng)根任務(wù)usrRoot;
??????? UsrRoot是運(yùn)行在多任務(wù)環(huán)境下的第一個(gè)任務(wù),它完成最后的初始化,并且啟動(dòng)其他任務(wù)。UsrRoot()按照configAll.h和config.h中的配置來初始化I/O系統(tǒng),安裝驅(qū)動(dòng)程序,創(chuàng)建設(shè)備,設(shè)置網(wǎng)絡(luò)等等。
??? ??? 在 開發(fā)過程中,我們可以利用TRACE32對每一步執(zhí)行進(jìn)行跟蹤,觀察程序的執(zhí)行行為,檢查相關(guān)寄存器的內(nèi)容;也可以寫一些測試函數(shù),對完成的相關(guān)的功能進(jìn) 行簡單的測試,例如當(dāng)我們完成了串口在輪詢模式下工作的驅(qū)動(dòng)程序后,我們可以寫一個(gè)echo程序?qū)Υ诘妮斎胼敵鲞M(jìn)行簡單的檢查。 ???
2:從ROM中啟動(dòng)vxWorks
當(dāng)我們利用TRACE32 調(diào)試好一個(gè)BSP以后,這時(shí)就需要修改rominit.s這個(gè)文件了,這個(gè)文件中的romInit()是冷啟動(dòng)時(shí)的入口點(diǎn),它將啟動(dòng)類型入棧,禁止中斷, 初始化CPU,配置SDRAM、FLASH,并轉(zhuǎn)移到bootinti.c中的romStart(),它將(文本段和)數(shù)據(jù)段復(fù)制到SDRAM中的 RAM_HIGH_ADRS處,并最終調(diào)用usrInit(bootType)。
在開發(fā)過程中,我們需要利用燒錄工具或者調(diào)試工具將編譯生成的bootrom.bin 下載到FLASH之中,當(dāng)系統(tǒng)上電時(shí),CPU將FLASH鏡像到地址0x00000000處,并開始執(zhí)行,當(dāng)romInit()執(zhí)行完必要的操作后,它將 跳轉(zhuǎn)到FLASH的真實(shí)地址0x01000000處,并執(zhí)行SDRAM、FLASH的初始化,這時(shí)再將SDRAM映射到0x00000000至 0x00ffffff處(0-16M),將FLASH映射到0x01000000至0x011fffff(16-18M)處完成其他的執(zhí)行。
(二)? CPU的體系結(jié)構(gòu)
S3C4510B 是使用ARM7TDMI核的CPU,因此需要對ARM7TDMI有一定的了解,需要注意的是32位精簡指令集的CPU對數(shù)據(jù)的操作是按一個(gè)字長(4- BYTE)進(jìn)行的,所以我們在gcc的編譯開關(guān)中需要用—pack-struct來消除結(jié)構(gòu)體間的空白,在強(qiáng)制類型轉(zhuǎn)換時(shí)也需要特別的注意,因?yàn)橐坏┮粋€(gè) 奇數(shù)地址被解釋成一個(gè)short(16-bit)或int(32-bit)類型地址時(shí)將產(chǎn)生異常。
(三)? 利用調(diào)試工具輔助開發(fā)
在開發(fā)BSP時(shí),有得心應(yīng)手的調(diào)試工具將事半功倍。在這個(gè)項(xiàng)目中,我使用了TRACE32,它界面簡潔,十分容易上手。
在開發(fā)初期,我們需要編寫腳本文件來對CPU、 SDRAM、FLASH進(jìn)行初始化,為了檢驗(yàn)初始化結(jié)果是否正確,我們可以通過對SDRAM中的地址進(jìn)行讀寫,看看結(jié)果與我們期望的是否一致。經(jīng)過了這一 步,再將vxWorks.st下載到SDRAM中,通過單步運(yùn)行檢查代碼執(zhí)行是否正常,定位出錯(cuò)誤的代碼位置,反復(fù)修改直到系統(tǒng)正常運(yùn)行為止。
?
硬件初始化
(一)?? VxWorks的行為
vxWorks 在usrInit()中調(diào)用sysHwInit(),它設(shè)置所有設(shè)備進(jìn)入安靜狀態(tài),屏蔽所有可屏蔽的中斷。sysHwInit調(diào)用 sysSerialHwInit();來初始化串口設(shè)備,并且在uartDevInit()中配置串口相關(guān)寄存器,設(shè)置波特率,置串口工作模式為輪詢模 式。
在usrRoot() 中調(diào)用sysClkConnect(),sysClkConnect立即調(diào)用sysHwInit2()來完成sysHwInit()中不能完成的工作, (因?yàn)樵谡{(diào)用sysHwInit()時(shí)還沒有初始化系統(tǒng)內(nèi)存池,所以不能調(diào)用malloc相關(guān)的函數(shù),例如intConnect())它調(diào)用 intLibInit()初始化中斷庫,調(diào)用irqDevIcnit()初始化中斷控制器,然后用intConnect()掛接時(shí)鐘中斷,調(diào)用 sysSerialHwInit2()將串口設(shè)置成中斷工作模式。
(二)? SC34510B的中斷描述
?????? SC34510B擁有21個(gè)中斷源,如下表所示:
??
在這個(gè)例子中我用到了[4]、[5]、[10] 這三個(gè)中斷源,分別為串口0發(fā)送中斷、串口0接收中斷、定時(shí)器0中斷。在初始化中斷控制器時(shí)我們需要設(shè)置INTMOD寄存器,將中斷源配置在我們需要的工 作模式下,這里我將他們配置成普通中斷模式(IRQ),即將[20:00]位清零。INTMOD寄存器如下圖所示:
?
INTPND中斷未決寄存器,它包含每個(gè)中斷源的未決中斷,需要在中斷服務(wù)程序中通過對相應(yīng)的位置一來清除該未決的中斷。寄存器如下圖所示:
INTMSK中斷掩碼寄存器,它包含每個(gè)中斷源的中斷掩碼,當(dāng)相應(yīng)的位被置一時(shí),該中斷將被屏蔽。寄存器如下圖所示:
在這個(gè)例子中,我沒有改變系統(tǒng)中各個(gè)中斷源的優(yōu)先級(jí)順序,即從0開始到第21,0的優(yōu)先級(jí)最高,依次遞減。
(三)? 中斷驅(qū)動(dòng)程序
??? 在irqDevIcnit()中初始化中斷控制器,它初始化中斷驅(qū)動(dòng)程序結(jié)構(gòu),初始化中斷控制器寄存器。
在irqcLvlVecChk()中檢查并返回當(dāng)前優(yōu)先級(jí)最高的未決中斷。在這期間它設(shè)置當(dāng)前中斷優(yōu)先級(jí)為這個(gè)未決中斷的優(yōu)先級(jí),來確保在中斷服務(wù)期間只允許優(yōu)先級(jí)比它高的中斷產(chǎn)生。
在irqcLvlVecAck()中重新設(shè)置當(dāng)前中斷為前一個(gè)中斷級(jí)別。
在irqcLvlChg()中設(shè)置新的當(dāng)前中斷級(jí)別,所用優(yōu)先級(jí)比當(dāng)前中斷低的(包括當(dāng)前中斷)將被屏蔽掉,所有比當(dāng)前中斷優(yōu)先級(jí)高的且被允許中斷的將被打開。
在irqcLvlEnable()允許指定中斷產(chǎn)生。
在irqcLvlDisable()屏蔽一個(gè)指定中斷。
(四)? 串口中斷
在uartDevInit()中初始化串口控制器,設(shè)置波特率,初始化串口驅(qū)動(dòng)程序。在期間需要配置的寄存器如下:
ULCON0寄存器,其值設(shè)為0x03,8-bit數(shù)據(jù)位,無停止位,無奇偶位。
??????? UCON0寄存器,其值設(shè)為0x00,設(shè)置接收和發(fā)送中斷無效。
??????? UBRDIV0 寄存器,設(shè)置波特率除數(shù)因子,這里我設(shè)置的波特率為38400根據(jù)公式可以計(jì)算出該寄存器的值應(yīng)該為0x270。公式為(fMCLK_MHz/(32* (_rate)) - 1)這里CPU的頻率為50MHZ,_rate為38400,所以CNT0的值為0x27,采用除一的方式,所以CNT1為0000b,所以該寄存器的結(jié) 果為0x270。
??????? uartPollInput()串口在輪詢模式下輸入處理程序。
UartPollOutput()串口在輪詢模式下輸出處理程序。
UartTxStartup()串口啟動(dòng)一個(gè)中斷輸出。
UartIntRX()輸人中斷服務(wù)程序,注意要清除輸入中斷相應(yīng)的中斷未決位。
UartIntTX()輸出中斷服務(wù)程序,注意要清除輸出中斷相應(yīng)的中斷未決位。
在以上幾個(gè)函數(shù)中需要用到一下幾個(gè)寄存器USTAT0、URXBUF0、UTXBUF0,大家自己查資料吧:)。
(五)? 時(shí)鐘中斷
??????? sysClkInt()為時(shí)鐘中斷的服務(wù)程序,在中斷驅(qū)動(dòng)程序初始化之后調(diào)用intConnect()注冊的。
??? ??? SysClkEnable()啟動(dòng)一個(gè)定時(shí)器,它計(jì)算每次時(shí)鐘中斷發(fā)生的時(shí)間間隔,并根據(jù)公式((fMCLK_MHz)/(sysClkTicksPerSecond)-1)算出TDATA0的值。設(shè)置TMOD為0x03,開啟timer0,打開時(shí)鐘中斷。
??????? SysClkDisable()停止一個(gè)定時(shí)器。它設(shè)置TMOD為0x00,關(guān)閉時(shí)鐘中斷。相關(guān)寄存器如下:
sysClkRateSet()設(shè)置每秒鐘tick數(shù),并通過連續(xù)調(diào)用SysClkDisable(),SysClkEnable()來更新設(shè)置。
SysClkRateGet()獲取每秒鐘tick數(shù)。
?
RomInit.s文件分析
當(dāng)我們利用TRACE32 開發(fā)調(diào)試完一個(gè)在RAM中運(yùn)行的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->interrupt controller*/
??? mvn r1, #0????????????????? ??? /*&FFFFFFFF*/
??? str r1, [r2]??????????????? ??????? /*disable all interrupt soucres*/
??? ldr r2, =ARM7_INTPEND?????????? /*R2->interrupt pend register.*/
??? 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處,并開始執(zhí)行。
這里ROM_TEXT_ADRS的值為0x01000000,當(dāng)對CPU進(jìn)行完必要的初始化以后它將跳轉(zhuǎn)到FLASH的真實(shí)地址處進(jìn)行執(zhí)行,它繼續(xù)完成對SDRAM的初始化,內(nèi)存布局的分配等等,詳細(xì)信息請參看TRACE32那一節(jié)。
?
總結(jié)
以上是生活随笔為你收集整理的基于S3C4510B的一个简单BSP的开发报告的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 子夜秋歌的作者是谁啊?
- 下一篇: Ubuntu10.04安装Flash插件