广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
3. 移植要点
3.1 异常处理
在VxWorks中对异常向量表的初始化是通过intVecBaseSet和excVecInit这两个函数来完成的。在ARM体系机构中,VxWorks提供的异常向量初始化大致如程序清单3.1所示:
程序清单3.1 VxWorks提供的excVecInit
static struct excEnterEntry excEnterEntrys[5]={
{(unsigned char *)(0x00000004),(unsigned char *)excEnterUndef}, {(unsigned char *)(0x00000008),(unsigned char *)excEnterSwi}, {(unsigned char *)(0x0000000c),(unsigned char *)excEnterPrefetchAbort}, {(unsigned char *)(0x00000010),(unsigned char *)excEnterDataAbort}, {(unsigned char *)(0x00000018),(unsigned char *)intEnt} };
STATUS excVecInit (void){ int i;
armInitExceptionModes(); for(i = 0;i<5;i++){
*(unsigned int*)(excEnterEntrys.vectorBase) = 0xe59ff0f4;
*(unsigned int *)(excEnterEntrys.vectorBase+0xfc) = (int)(excEnterEntrys.vectorReal); }
if(cacheLib.textUpdateRtn !=NULL){ cacheLib.textUpdateRtn(0,0x1c); }
_func_armIrqHandler = (FUNCPTR)intEnt; return OK; }
从中可以看出,VxWorks不支持对ARM的FIQ的处理,异常向量表中的5个异常处理函数,是由VxWorks提供的异常处理函数,不需要用户来直接操作。
使用机器码0xe59ff0f4等同于“ldr pc,pc+0xfc”。
这段程序的意思是在异常向量表的安装基地址0地址开始处填写异常向量表跳转语句,在0x100处写异常处理的跳转地址。
VxWorks本来提供了intVecBaseSet函数来设置异常向量表的安装基地址,但是在ARM体系结构中intVecBaseSet是空的,根本不能通过调用该函数来改变异常向量表的安装基地址。
对于一些ARM体系结构的处理器来说,根本没有提供地址重映射功能,如s3c44B0x,或者是能映射的地址空间有限,如LPC2xxx,能重映射到0地址的RAM空间只有64字节。 通常这些处理器的启动Flash是0地址,因此VxWorks提供的excVecInit在这些处理器上无法完成异常向量表的安装。对于s3c2440a来说,在未使能MMU或者使能MMU但是进行平坦地址映射的情况下,Flash仍处于地址0。对于这些情况的处理方法有多种,下面以s3c2440a为例,进行介绍。
我们可以编写自己的excVecInit(),来替换VxWorks提供的excVecInit。如程序清单 3.2移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
6
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
所示:
程序清单 3.2 自定义的excVecInit
static struct excEnterEntry excEnterEntrys[5]={
{(unsigned char *)( VEC_BASE_ADRS+0x00000004),(unsigned char *)excEnterUndef}, {(unsigned char *)( VEC_BASE_ADRS+0x00000008),(unsigned char *)excEnterSwi}, {(unsigned char *)( VEC_BASE_ADRS+0x0000000c),(unsigned char *)excEnterPrefetchAbort}, {(unsigned char *)( VEC_BASE_ADRS+0x00000010),(unsigned char *)excEnterDataAbort}, {(unsigned char *)( VEC_BASE_ADRS+0x00000018),(unsigned char *)intEnt} };
STATUS excVecInit (void){ int i;
armInitExceptionModes(); for(i = 0;i<5;i++){
*(unsigned int*)(excEnterEntrys.vectorBase) = 0xe59ff0f4;
*(unsigned int *)(excEnterEntrys.vectorBase+0xfc) = (int)(excEnterEntrys.vectorReal); }
if(cacheLib.textUpdateRtn !=NULL){
cacheLib.textUpdateRtn(VEC_BASE_ADRS,0x1c); }
_func_armIrqHandler = (FUNCPTR)intEnt; return OK; }
VEC_BASE_ADRS是异常向量表的安装基地址,在“configall.h”中定义,我们可以在“config.h”对其重新定义。如程序清单3.3所示:
程序清单3.3 VEC_BASE_ADRS
#undef VEC_BASE_ADRS
#define VEC_BASE_ADRS 0x30000000
这样VxWorks提供的异常处理向量表就能被安装到由VEC_BASE_ADRS所确定的RAM空间中。
启动Flash为0地址时还需要作以下处理:在Flash的0地址处编码异常向量处理入口, 异常发生时,经Flash存储器的异常入口,跳转到由自定义的excVecInit 函数所安装的RAM中的异常向量处理入口,再调用vxWorks提供的异常处理函数。如程序清单 3.4所示:
程序清单 3.4 Flash的异常入口程序
cold:
mov r0, #BOOT_COLD /* BOOT_COLD boot entry */ warm: b start b Swi b Pabort
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
7
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
b Dabort b cold b Irq b Fiq Swi: … Pabort: … Dabort: … Irq:
sub sp,sp,#4 stmfd sp!,{r1} ldr r1,vecIrq str r1,[sp,#4] ldmfd sp!,{r1,pc} vecIrq:
.long 0x30000018 /* VEC_BASE_ADRS+0X18 */
异常处理流程如图 3.1:
Flash空间0x00000000cold...b Irq...Irq函数RAM空间0x30000000...0xe5ff0f40xe5ff0f4...intEnt
图 3.1 异常处理流程图
对于s3c2440a,还可以使能MMU,将VEC_BASE_ADRS映射到0地址,以提高异常响应的速度。这里只映射了1页的地址空间。
如程序清单 3.5所示:
程序清单 3.5 VEC_BASE_ADRS映射
#ifdef INCLUDE_MMU
PHYS_MEM_DESC sysPhysMemDesc[] = {
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
8
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
#ifdef EXCEPTE_VECT_MMU_MAP /* remap system except tbl */ {
(void *)ROM_BASE_ADRS, (void *)VEC_BASE_ADRS, PAGE_SIZE,
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE|VM_STATE_MASK_CACHEABLE, VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT }, …
3.2 中断处理
ARM的中断是抢占式的,因此在“config.h”中定义中断模式如程序清单3.6:
程序清单3.6 定义中断模式
#define INT_MODE INT_PREEMPT_MODEL
intLibInit是中断库初始化函数,需要在中断初始化前调用。它根据传入的参数(最大中断向量数,中断模式),来进行处理,根据最大中断向量数分配内存,其结构大致如程序清单3.7 中断向量表所示:
程序清单3.7 中断向量表
struct {
VOIDFUNCPTR routine; int parameter; }intVecTable[INT_NUM_LEVELS]
调用intConnect函数安装中断向量程序入口及参数到intVecTable。如程序清单 3.8所示:
程序清单 3.8 intConnect
STATUS intConnect (
VOIDFUNCPTR * vector, /* interrupt vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ )
intLibInit根据参数INT_MODE设置_func_armIrqHandler这个钩子函数 ,这个钩子函数可被设置为intIntRtnPreemt或intIntRtnNoPreemt。在ARM体系结构中,_func_armIrqHandler被设置为intIntRtnPreemt。
VxWorks的中断处理流程大致如图3.2所示:
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
9
广州致远电子有限公司 VxWorks BSP移植技术笔记 VxWorks技术笔记
intEnt:(IRQ->SVC)intIntRtnPreempt:{(*sysIntLvlVecChkRtn)(&oldLvl,&vecIndex)intUnlock(*intVecTable[vecIndex].routine)(intVecTable[vecIndex].arg)intLock(*sysIntLvlVecAckRtn)(oldLvl,vecIndex);intExit: resumeIntExitresumeIntExit: intExit_RTI(SVC->IRQ)图3.2 VxWorks的中断处理流程
中断初始化函数的实现如下,我们需要安装VxWorks的中断处理回调函数,如程序清单3.9所示:
程序清单3.9 中断初始化
int s3c2440aIntInit (void) { /*
* 所有中断都为 IRQ 模式,屏蔽所有中断,清除所有子中断。 */ … /*
* Install the driver routines in the architecture hooks */
sysIntLvlVecChkRtn = s3c2440aIntLvlVecChk; sysIntLvlVecAckRtn = s3c2440aIntLvlVecAck; sysIntLvlChgRtn = s3c2440aIntLvlChg; sysIntLvlEnableRtn = s3c2440aIntLvlEnable; sysIntLvlDisableRtn = s3c2440aIntLvlDisable; … return OK; }
各个回调函数的主要功能如下:
sysIntVecChkRtn:查找中断源,并根据中断源确定中断向量(屏蔽当前中断,清中断)。 sysIntLvlVecAckRtn:中断处理结束后的一些工作(使能当前中断)。 sysIntLvlEnableRtn:使能某个中断向量。 sysIntLvlDisableRtn:禁止某个中断向量。
其具体实现根据中断控制器的不同而不同,s3c2440a的具体实现可参考s3c2440a_wrsbsp包中的“sysInt.c”文件。
移植技术笔记 ?2009 Guangzhou ZHIYUAN Electronics CO., LTD.
10
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库vxWorks_BSP移植笔记(3)在线全文阅读。
相关推荐: