访问手机版页面
你的位置:老古开发网 > 其他 > 正文  
转载《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
相关阅读
推荐阅读
阅读排行
最近更新
商品推荐