转载《S3C44B0X BSP移植》
内容导读:
转载自:http://bbs.eepw.com.cn/dispbbs.asp?BoardID=3&ID=27451&replyID=&skin=1
原作者:eking
打造你的44BSP-小试牛刀
====================
对BSP的启动流程和系统配置有了一些了解后,就应该实际动动代码啦!
最基本的BSP要能运行至少需要启动代码、中断处理、定时器驱动、串口驱动,当这些驱动写好以后,基本的BSP就可以起来了。之后你可以通过TSFS加载vxWorks,运行自己的程序,小试一把!!
1. 启动代码
---------
1)romInit.s
这是从ROM启动时执行的第一个文件,所以要在这里放置一些跳转指令转到我们自定义的处理入口
_ARM_FUNCTION(romInit)
_romInit:
B cold
B Undef
B Swi
B Pabort
B Dabort
B .
B Irq
B .
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 1984-2001 Wind River Systems, Inc."
.balign 4
start:
/* 进行44b0的CPU初始化工作 */
设置CPSR的I_BIT和F_BIT - 禁止中断,进入SVC32模式;
如果BOOT_WARM跳过CPU初始化;
设置WTCON - 禁止WDT;
设置INTMSK - 屏蔽中断;
设置时钟控制寄存器;
根据DRAM_TYPE初始化内存控制寄存器(SDRAM、EDO);
设置SP - 初始化堆栈地址;
跳转到romInit();
Undef:
SUB sp, sp, #4
STMFD sp!, {r1}
LDR r1, vecUndef
STR r1, [sp, #4]
LDMFD sp!, {r1, pc}
Swi:
SUB sp, sp, #4
STMFD sp!, {r1}
LDR r1, vecSwi
STR r1, [sp, #4]
LDMFD sp!, {r1, pc}
Pabort:
SUB sp, sp, #4
STMFD sp!, {r1}
LDR r1, vecPabort
STR r1, [sp, #4]
LDMFD sp!, {r1, pc}
Dabort:
SUB sp, sp, #4
STMFD sp!, {r1}
LDR r1, vecDabort
STR r1, [sp, #4]
LDMFD sp!, {r1, pc}
Irq:
SUB sp, sp, #4
STMFD sp!, {r1}
LDR r1, vecIrq /* load IRQVec addr to r1 */
STR r1, [sp, #4] /* store content(ISR addr) to stack */
LDMFD sp!, {r1, pc} /* pop work regs and pc (jump to ISR) */
vecUndef:
.long VEC_BASE_ADRS + 4
vecSwi:
.long VEC_BASE_ADRS + 8
vecPabort:
.long VEC_BASE_ADRS + 12
vecDabort:
.long VEC_BASE_ADRS + 16
vecIrq:
.long VEC_BASE_ADRS + 24
关键在此,VEC_BASE_ADRS是在config.h重定义的宏:
#define VEC_BASE_ADRS 0x0C000000
这样中断产生后先保护现场,然后跳转到RAM中的向量表,但在RAM的VEC_BASE_ADRS处并没有代码,所以我们要在VEC_BASE_ADRS处构造一个向量表。
2)sysLib.c
我通过对内核的跟踪,发现中断后会跳到excEnterTable查找异常向量入口,然后跳转到内核的异常处理函数excEnterXXX(),如果可以改变异常向量表的向量入口地址则问题即可解决,但该死的疯河却不提供修改向量入口地址的API(可能是想要我们再购买源码吧^o^)。
既然这样不行,那就只好自己构造异常向量表了。
/* 声明内核异常处理函数,(呵呵,这可是辛辛苦苦跟踪来的!!) */
extern void excEnterUndef(void);
extern void excEnterSwi(void);
extern void excEnterPrefetchAbort(void);
extern void excEnterDataAbort(void);
extern void intEnt(void);
typedef struct {
UINT32 vector;
VOIDFUNCPTR func;
} exc_tbl_t;
#define SYS_EXC_NUM 5
LOCAL exc_tbl_t sysExcTbl[SYS_EXC_NUM] = {
{VEC_BASE_ADRS+0x04, excEnterUndef},
{VEC_BASE_ADRS+0x08, excEnterSwi},
{VEC_BASE_ADRS+0x0c, excEnterPrefetchAbort},
{VEC_BASE_ADRS+0x10, excEnterDataAbort},
{VEC_BASE_ADRS+0x18, intEnt}
};
void sysExcTblSet(void)
{
int i;
for (i = 0; i < SYS_EXC_NUM; ++i) {
*(UINT32 *)(sysExcTbl[i].vector) = (UINT32)0xe59ff0f4;
/* ldr pc, pc + 0xfc */
*(UINT32 *)(sysExcTbl[i].vector + 0xfc) = (UINT32)(sysExcTbl[i].func);
}
}
首先声明内核异常处理函数,定义异常处理向量表结构,用各个异常处理函数填充这个表,最后根据这个表在VEC_BASE_ADRS处放置跳转指令,LDR PC, PC+0xFC,跳转到异常处理函数。
这样中断发生时,CPU从0x00000018 -> VEC_BASE_ADRS + 0x18 -> excEnterXXX()。
我这样做是参考vxWorks的异常向量处理方式,使得设置用户的异常向量处理函数更容易。有网友直接把异常处理函数地址放在异常入口处,结果是一样的。
最后把sysExcTblSet()加到sysHwInit()即可完成向量表的设置。
2. 中断控制
----------
NOTE: vxWorks只支持IRQ中断,中断只能采用非向量模式。
1) 中断初始化
初始化中断控制器,在此必须设置INTCON关闭所有IRQ FIQ中断,否则即使屏蔽了所有中断仍会有中断产生,而使系统死机。
INTCON = 0x07 - 关闭所有IRQ和FIQ中断
INTMOD = 0x0 - 设置中断为IRQ模式
INTMSK = 1<<26 - 屏蔽所有中断
2) 中断使能
使能特定的中断,由于此时中断可能已经打开,所以对寄存器的操作要上锁。要先使能IRQ中断,再清除相应的中断屏蔽位。
3) 中断禁止
关闭特定的中断,操作寄存器时也要上锁。关闭中断就是设置相应的中断屏蔽位为1。
4) 中断查询
检查是否有中断发生,若中断发生清除此中断位(防止中断再次发生)并则返回中断号。
3. 定时器驱动
------------
1) 初始化
TCFG0 设置TIMER预分频
TCFG1 设置TIMER分频值
TCON 禁止TIMER
2) 启动定时器
TCNTBx 设置计数初值
设置TCON更新初值(TIMER_UPDATE)
设置TCON启动定时器(TIMER_START TIMER_AUTOLOAD)
3) 使能定时器
设置TCON启动定时器(TIMER_START TIMER_AUTOLOAD)
4) 关闭定时器
设置TCON禁止定时器(清除TIMER_START位)
最后,修改系统定时器接口sysTimer.c,调用相应的底层驱动函数,完成定时器驱动。
4. 串口驱动
----------
硬件底层驱动实现了S3C44B0的UART口的初始化、参数配置、*询方式的发送和接收、中断方式的发送和接收等函数。
1) 数据结构
修改串口数据结构devParas[],设置UART的接收发送的中断号、向量号、寄存器基地址等;
2) 初始化
串口初始化时用devParas[]数据填充底层驱动的SNG44B_CHAN结构,每个UART都有各自的SNG44B_CHAN结构,然后调用底层初始化函数sng44bDevInit进行实际的UART初始化。
对UART的初始化分为2个阶段,第1阶段设置回调函数、初始化硬件、设置波特率、设置UART为*询模式;第2阶段设置UART为中断模式,但不使能UART中断。
3) 发送(中断和*询)
中断方式下,由sng44bTxStartup启动发送,往UTXH写入数据,并使能UART中断;发送完成后由回调函数sng44bIntTx检查是否还有数据要发送,是则发送,否则关闭中断。
*询方式下,不断检查UTRSTAT,若发送就绪往UTXH写入数据返回OK,否则返回EAGAIN。
4) 接收(中断和*询)
中断方式下,当接收到数据时,由函数sng44bIntRx调用回调函数pChan->putRcvChar接收数据。
*询方式下,不断检查UTRSTAT,若接收就绪返回接收到的数据
2.修改配置文件
------------
2.1 CPU寄存器定义
参考S3C44B0 datasheet修改CPU寄存器定义,这部分就不用我多说了吧
2.2 板级配置定义
在此定义板级的配置,如时钟频率、总线宽度、存储器配置参数等板级相关的配置。
1) CPU FREQ CONF
根据开发板晶振频率定义SNG44B_OSC_CLK、CPU内频SNG44B_CPU_SPEED
由此得出分频系数定义M_DIV P_DIV S_DIV SNG44B_PLLCON
这些定义将在TIMER驱动里设置TIMER的时基和串口波特率的计算。
2) CPU MODE DEFINE
根据CPU的DATASHEET定义CPSR位定义,如下:
#define FBit 0x40
#define IBit 0x80
#define LOCKOUT 0xC0 /* Interrupt lockout value */
#define LOCK_MSK 0xC0 /* Interrupt lockout mask value */
#define MODE_MASK 0x1F /* Processor Mode Mask */
#define UDF_MODE 0x1B /* Undefine Mode(UDF) */
#define ABT_MODE 0x17 /* Abort Mode(ABT) */
#define SUP_MODE 0x13 /* Supervisor Mode (SVC) */
#define IRQ_MODE 0x12 /* Interrupt Mode (IRQ) */
#define FIQ_MODE 0x11 /* Fast Interrupt Mode (FIQ) */
#define USR_MODE 0x10 /* User Mode(USR) */
3) ONBOARD MEM CONF
SABARM7_BUSWIDTH FLASH数据宽度
SABARM7_FLASH_BASE FLASH的基地址
SABARM7_FLASH_SIZE FLASH大小
LOCAL_MEM_LOCAL_ADRS SDRAM基地址
LOCAL_MEM_BUS_ADRS 同上
DRAM_TYPE 存储器类型 SDRAM or EDO
SNG44B_BxCON MEMORY BANK控制寄存器(x=0~7),需根据实际配置定义
SNG44B_REFRESH
4) UART CONF
SNG44B_UART_CHANNELS UART通道数
UART_REG_ADDR_INTERVAL UART寄存器地址间隔,在UART驱动使用
5) INT VEC DEFINE
INT_LVL_XXXX CPU中断号定义
INT_VEC_XXXX IVEC_TO_INUM(INT_LVL_XXXX) 中断向量定义
6) CACHE CONF
CACHE_SIZE 8K 定义CACHE大小
NONCACHE_BEG 0x02000000 NONCACHE起始地址
NONCACHE_END 0x0C000000 NONCACHE结束地址
NONCACHE 0xC0002000 NONCACHE寄存器值定义(根据NONCACHE_BEG NONCACHE_END得出)
WRITE_BUFF 0x08 使能WRITE BUFFER
TAGRAM_BEG 0x10002000 CACHE TAG RAM起始地址
TAGRAM_END 0x10004800 CACHE TAG RAM结束地址
7)TIMER CONF
N_TIMERS 定时器个数 6
SYS_CLK_RATE_MIN 系统tick最小值 10
SYS_CLK_RATE_MAX 系统tick最大值 10000
AUX_CLK_RATE_MIN 辅助tick最小值 2
AUX_CLK_RATE_MAX 辅助tick最大值 10000
SYS_TIMER_CLK 系统时钟频率
AUX_TIMER_CLK 辅助时钟频率
SYS_TIMER_INT_LVL 系统时钟中断号
AUX_TIMER_INT_LVL 辅助时钟中断号
2.3 系统配置
-----------
VxWorks缺省配置由../all/目录下的configAll.h确定一般来说缺省配置的设置和自行开发的硬件系统的配
置是不同的,用户需要通过改写Config.h来改变缺省配置。这些内容包括设置存储区的大小;增加新的程序模
块,如包含专用接口的驱动和操作;删除不需要的模块。
在config.h中定义了vxWorks系统的配置,用户可通过修改config.h来裁剪系统。
1) BSP VERSION
BSP版本定义
2) BOOT LINE CONFIGURATION
强制从DEFAULT_BOOT_LINE获取下载参数
#define FORCE_DEFAULT_BOOT_LINE
通过END方式下载的DEFAULT_ BOOT_LINE
# define DEFAULT_BOOT_LINE "ene(0,0) eking:vxWorks " \
"h=192.168.1.31 " \
"e=192.168.1.11:ffffff00 " \
"u=target " \
"pw=ok " \
"tn=44b0"
通过TSFS方式下载的DEFAULT_BOOT_LINE
# define DEFAULT_BOOT_LINE "tsfs(0,0) eking:vxWorks " \
"h=192.168.1.31 " \
"e=192.168.1.11 " \
"u=target " \
"tn=44b0"
DEFAULT_BOOT_LINE只能定义一次,需用编译开关控制,格式参考其他帖子
3) MEMORY CONF
#define USER_RESERVED_MEM 0x0 用户保留内存块大小
#define ROM_BASE_ADRS 0x00020000 image烧入FLASH的地址
#define ROM_TEXT_ADRS ROM_BASE_ADRS
#define ROM_SIZE 0x00080000 image大小限制512KB
#define ROM_COPY_SIZE ROM_SIZE
#define ROM_SIZE_TOTAL 0x00200000 FLASH ROM大小
#define RAM_LOW_ADRS 0x0C100000 下载vxWorks执行地址
#define RAM_HIGH_ADRS 0x0C500000 bootrom执行地址
4) VECTOR BASE
/*
* VEC_BASE_ADRS
*
* The base address of CPU interrupt and exception vector
* VxWorks vecter table must resident in RAM, BUT s3c44b0 doesn't support
* memory remap and its vector table can only place in ROM(0x00000000).
* The solution is that we construct a vector at RAM (ISR_RAM_ADRS) by romInit()
* If an interrupt being raised, CPU jump to the real vector in ROM,
* and then goto vector in RAM which we h**e constructed. In this way,
* the kernel know how to deal with it well.
*
* Eking 2004-02-26
*/
#define ISR_RAM_ADRS 0x0c000000 自定义的VECTOR TABLE地址
#undef VEC_BASE_ADRS
#define VEC_BASE_ADRS ISR_RAM_ADRS
5) CACHE CONF
#define INCLUDE_CACHE_SUPPORT
#ifdef INCLUDE_CACHE_SUPPORT
# define USER_I_CACHE_ENABLE
# undef USER_I_CACHE_MODE
# define USER_I_CACHE_MODE CACHE_WRITETHROUGH
# define USER_D_CACHE_ENABLE
# undef USER_D_CACHE_MODE
# define USER_D_CACHE_MODE CACHE_DISABLED
#endif /* INCLUDE_CACHE_SUPPORT */
因为44b0不支持D_CACHE,故而关之
关于cache
5) CACHE CONF
#define INCLUDE_CACHE_SUPPORT
#ifdef INCLUDE_CACHE_SUPPORT
# define USER_I_CACHE_ENABLE
# undef USER_I_CACHE_MODE
# define USER_I_CACHE_MODE CACHE_WRITETHROUGH
# define USER_D_CACHE_ENABLE
# undef USER_D_CACHE_MODE
# define USER_D_CACHE_MODE CACHE_DISABLED
#endif /* INCLUDE_CACHE_SUPPORT */
因为44b0不支持D_CACHE,故而关之
440的cache是unified, 就是data/instruction合在一起的cache, 所以我觉得
USER_D_CACHE_MODE 也可以定义为CACHE_WRITETHROUGH
CACHE_SIZE 8K 定义CACHE大小
NONCACHE_BEG 0x02000000 NONCACHE起始地址
NONCACHE_END 0x0C000000 NONCACHE结束地址
NONCACHE 0xC0002000 NONCACHE寄存器值定义(根据NONCACHE_BEG NONCACHE_END得出
非cacheable的区域是否应该包括flash的空间, 从0x02000000到0x0c000000就是外设的io空间, 我只把sdram的空间设为cacheable, 其余都是non cacheable的
这样的配置结果是0xc0000000,
#define ROM_BASE_ADRS 0x00020000 image烧入FLASH的地址
没有放置到地址0上?
6) BSP_VTS
BSP_VTS用于bsp的测试,完成后应关掉
#undef BSP_VTS
#ifdef BSP_VTS
# undef INCLUDE_PING
# undef INCLUDE_RLOGIN
# undef INCLUDE_SHOW_ROUTINES
# undef INCLUDE_NET_SYM_TABLE
# define INCLUDE_SHELL
# define INCLUDE_PING
# define INCLUDE_RLOGIN
# define INCLUDE_SHOW_ROUTINES
# define INCLUDE_NET_SYM_TABLE
#endif /*BSP_VTS*/
7) SERIAL CONF
控制台串口配置
#define INCLUDE_SERIAL
#ifdef INCLUDE_SERIAL
# undef NUM_TTY
# define NUM_TTY N_UART_CHANNELS
# undef CONSOLE_TTY
# define CONSOLE_TTY 0
# undef CONSOLE_BAUD_RATE
# define CONSOLE_BAUD_RATE 115200
#endif
8) WDB CONF
若选择WDB_COMM_SERIAL,只能从TSFS下载vxWorks
/* WDB communicate configuration */
#if WDB_COMM_TYPE == WDB_COMM_SERIAL
/* WDB self test include */
# undef INCLUDE_WDB_TTY_TEST
# define INCLUDE_WDB_TTY_TEST
/* default TYCODRV_5_2 device name */
# undef WDB_TTY_DEV_NAME
# define WDB_TTY_DEV_NAME "/tyCo/0"
/* WDB COM PORT #2 */
# undef WDB_TTY_CHANNEL
# define WDB_TTY_CHANNEL 1
/* WDB in Serial mode */
# undef WDB_COMM_TYPE
# define WDB_COMM_TYPE WDB_COMM_SERIAL
/* Baud rate for WDB Connection */
# undef WDB_TTY_BAUD
# define WDB_TTY_BAUD 115200
/* BOOT from TSFS */
# define INCLUDE_TSFS_BOOT
# undef INCLUDE_WDB_TSFS
# define INCLUDE_WDB_TSFS
# ifdef INCLUDE_TSFS_BOOT
# undef DEFAULT_BOOT_LINE
# define DEFAULT_BOOT_LINE "tsfs(0,0) eking:vxWorks " \
"h=192.168.1.31 " \
"e=192.168.1.11 " \
"u=target " \
"tn=44b0"
# endif
#elif WDB_COMM_TYPE == WDB_COMM_END
#endif /* WDB_COMM_TYPE */
9) NETWORK CONF
包含END驱动及相关应用程序
/* De-select unused (default) network drivers selected in configAll.h */
#undef INCLUDE_ENP /* include CMC Ethernet inte**ce*/
#undef INCLUDE_EX /* include Excelan Ethernet inte**ce */
#undef INCLUDE_SM_NET /* include backplane net inte**ce */
#undef INCLUDE_SM_SEQ_ADDR /* shared memory network auto address setup */
/* Enhanced Network Driver (END) Support */
#define INCLUDE_NETWORK
#ifdef INCLUDE_NETWORK
# define INCLUDE_UDP
# define INCLUDE_TCP
# define INCLUDE_ICMP
# undef INCLUDE_IGMP
# undef INCLUDE_PPP
#endif
#define INCLUDE_END
#undef END_OVERRIDE /* define if you are using old boot ROMs. */
#ifdef INCLUDE_END
# define INCLUDE_SNG44B_END /* Include Ethernet driver */
#endif /* INCLUDE_END */
10) INT MODE
#define INT_MODE INT_NON_PREEMPT_MODEL 非强占中断模式
11) TFFS CONF
包含TFFS驱动,TFFS和BOOTROM在同一片FLASH中,所以只使用其中一部分做文件系统,需包含必须的几个模
块。
#define INCLUDE_TFFS /* to include TrueFFS driver */
#ifdef INCLUDE_TFFS
# define TFFS_FLASH_ADRS (SNG44B_FLASH_BASE + 0x180000)
# define TFFS_FLASH_SIZE (0x50000)
# undef INCLUDE_SHOW_ROUTINES
# define INCLUDE_DOSFS
# define INCLUDE_DOSFS_CHKDSK
# define INCLUDE_DOSFS_DIR_FIXED
# define INCLUDE_DOSFS_DIR_VFAT
# define INCLUDE_DOSFS_FAT
# define INCLUDE_DOSFS_FMT
# define INCLUDE_DOSFS_MAIN
# define INCLUDE_DISK_UTIL /* shell disk utils: ld, cd... */
# define INCLUDE_CBIO
#endif /* INCLUDE_TFFS */
12) MISC CONF
44b0不支持MMU,禁用它
#undef INCLUDE_MMU_BASIC
#undef INCLUDE_MMU_FULL
#undef INCLUDE_MMU_MPU
标签:
来源: 作者: 时间:2006/9/25 16:50:53