这里主要是涉及硬件驱动编程的问题,许多是drew在论坛和E-MAIL上和网友探讨过的一些问题,有些是个人编程经验.不一定全面.一些相关程序代码会陆续补到程序示例
这里是一些程序示例和源码解释.一些相关程序代码会陆续补上.系统初始化
系统初始化对不同的CPU,基本步骤是类似的.
系统初始化的主要步骤如下
启动
关闭中断
放boot type到堆栈
清空缓存
VxWorks 系统的 PowerPC BSP,系统开机后执行的第一个函数 romInit(),在ROM的起点,这里是使用的PowerPC汇编语言
/* 定义内部函数 internals */
.globl romInit /* start of system code */
.globl _romInit /* start of system code */
/* 定义外部函数 externals */
.extern romStart /* system initialization routine */
.text
.align 2
/*******************************************************************************
*
* romInit ( int startType /@ only used by 2nd entry point @/ )
*/
romInit:
_romInit:
bl cold /* 冷启动 */
bl warm /* 热启动 */
cold:
li p5, BOOT_COLD
bl start /* skip over next instruction */
warm:
or p5, p0, p0 /* startType to p5 */
start: /* 此处是系统启动开始 */
/* 屏蔽MSR中CE,EE位,关闭所有的外部中断
/*
* Disable external interrupts
*/
mfmsr p0 /* p0 = msr */
INT_MASK (p0, p1) /* mask EE and CE bit */
ori p1,p1,_PPC_MSR_ME /* enable machine checks */
mtmsr p1 /* msr = p1 */
isync
/* 下面两步是按照硬件定义初始化一些SPR,DCR寄存器,置0或置1
/* SPR是特殊功能寄存器,DCR为设备控制寄存器,还有MSR机器状态寄存器,这些是PowerPC内核中很重要的寄存器
/* 初始化SPR,DCR寄存器置0
* Initalize registers that need to be set to zero.
*/
addi r4,r0,0x0000
mtspr SGR,r4 /* 解锁所有存储区域 SPR 中 SGR 位置0 */
mtspr ESR, r4 /* SPR中的错误状态位 ESR 清0 */
mtspr TCR, r4 /* 关闭所有的 timers */
mtspr PIT, r4 /* 清0 PIT timer */
mtdcr UICER, r4 /* 关闭中断控制器(UIC)中的所有中断 */
mtspr XER, r4 /* 清0 integer exception 寄存器 */
/* 初始化另一些SPR,DCR寄存器置1
* Initalize registers that need to be cleared with 0xFFFFFFFF.
*/
addis r4,r0,0xffff
ori r4,r4,0xffff
mtspr TSR, r4 /* timer */
mtspr DBSR, r4 /* 调试状态位置1 */
mtdcr UICSR, r4 /* 清除中断控制器(UIC)中的所有 pending 中断 */
mtdcr dmasr, r4 /* DMA状态寄存器置1 */
/* PowerPC405用两个缓存,一个是16K指令缓存(ICU),一个是6K数据缓存(DCU),下面是清空着两个缓存,并根据硬件设置缓存 */
/* 清空指令缓存 */
/*BESR type regs ZZZZZZZZZZZZ
* Invalidate the entire instruction cache. This can be done
* with a single iccci instruction in the processor core.
*/
iccci r0, r0
/*清空数据缓存
* Invalidate the entire data cache.
* The 405 processor core in the 405GP has 128 congruence classes.
* Each cache line in the 405 processor is 32 bytes.
*/
/*
* Turn the instruction cache on for faster boot-up.
* Also, the icache is needed to help initialize Bank 0
* of the EBC to speed up accesses to flash.
* address space 0x00000000-0x07ffffff is cached
* address space 0xf8000000-0xffffffff is cached
*/
lis p0, HIADJ(_PPC403_ICCR_DEFAULT_VAL)
addi p0, p0, LO(_PPC403_ICCR_DEFAULT_VAL)
mtspr _PPC403_ICCR, p0
isync
/* 初始化外部总线控制器(EBC),跳转指令BL,执行extBusCntlrInit
* /
bl extBusCntlrInit
/*
* Now that the EBC Bank 0 has been set up, turn the I-cache off if
* i-cache was not specified in config.h. It is also invalidated
* again.
*/
#ifndef USER_I_CACHE_ENABLE
li p0, 0 /* clear p0 */
mtspr _PPC403_ICCR, p0 /* turn off i-cache */
isync
iccci r0, r0 /* invalidate the I-cache again */
#endif
/* 初始化和SDRAM相关的IIC(inter-integrated circut)寄存器IIC0,
* Initialize IIC0 for use in automatic SDRAM configuration
*/
#ifdef LOCAL_MEM_AUTOSIZE
bl iic0Init
#endif
/* 初始化SDRAM,BL跳转执行sdramInit
* Configure the SDRAM controller only if this is a cold boot.
* If the SDRAM controller is reinitialized on a warm boot, the
* boot line will get wiped out because of the ECC SDRAM memory
* initialization.
*/
li p0, BOOT_COLD
and. p0, p0, p5 /* p5 is saved at the entry of romInit */
beq skip
bl sdramInit
skip:
/*
* Clear the CPU reservation bit
*/
li r0, 0
lwarx p0, r0, r0
stwcx. p0, r0, r0
#ifdef PPC405GP_REVA
/* 设置中断向量表到0x0000 */
li p0, 0x2100/4
mtctr p0
lis p0, WALNUT_EVPR_VAL
li p1, 0x0000
zeroOut:
stw p1,0x0(p0)
addi p0, p0, 4
bdnz zeroOut
#endif
/* 初始化堆栈
/* Initialize the stack pointer (r1) */
lis sp, HIADJ(STACK_ADRS)
addi sp, sp, LO(STACK_ADRS)
#if FALSE /* SDA not supported */
/* initialize r2 and r13 according to EABI standard */
lis r2, HIADJ(_SDA2_BASE_)
addi r2, r2, LO(_SDA2_BASE_)
lis r13, HIADJ(_SDA_BASE_)
addi r13, r13, LO(_SDA_BASE_)
#endif
/* 得到C程序romStart()在ROM中的地址,保证romInit执行结束后,系统跳转执行romStart()
/* calculate C entry point: routine - entry point + ROM base */
lis p1, HIADJ(romStart) /* p1 = romstart */
addi p1, p1, LO(romStart)
lis p2, HIADJ(romInit) /* p2 = romInit */
addi p2, p2, LO(romInit)
/* ROM_TEXT_ADRS为ROM的入口地址,在文件makefile定义,为0xfff80100
lis p3, HIADJ(ROM_TEXT_ADRS) /* p3 = ROM_TEXT_ADRS */
addi p3, p3, LO(ROM_TEXT_ADRS)
subf p1, p2, p1 /* p1 = p1 - p2 */
add p1, p1, p3 /* p1 = p1 + p3 */
/* p1中是romStart()的地址,这里把这个地址放到连接寄存器LR中. mtlr p1 /* link register = C entry point */
or p0, p5, p5 /* p0 = startType */
addi sp, sp, -FRAMEBASESZ /* get frame stack */
/* 跳转到LR中romStart()的地址,执行romStart()
blr /* branch to link register */
硬件中断
中断的产生和VxWorks系统的中断操作:
一般中断的产生是由硬件定义的,如串口中断的定义:
1.接收中断:当接收中断使能,接收数据存储器 RxData 存在有效数据,则产生中断.
2.发送中断:当发送中断使能,发送数据存储器 TxData 为空,则产生中断.
硬件发送中断产生逻辑示意 |
硬件接收中断产生逻辑示意 所以要产生一个串口中断,主要有两步: 1.使能这两个串口中断,RX Enable,TX Enable,函数intEnable().
程序示例 在VxWorks系统上登记,使能串口中断 intConnect((VOIDFUNCPTR *)5,ComISR,0); //登记中断服务程序ComISR()到外部中断号5, intEnable((VOIDFUNCPTR *)5); //使能外部中断5
//divider register,baut rate 19200 设置波特率
注意:中断程序不能单步执行,或跟踪调试,中断服务程序中与函数库或系统有关的函数不可用如print()等,因为中断调用时,所有其它的任务都被挂起停止运行.
返回页首
VxWorks系统的网络驱动(END) VxWorks网络配置参见VxWorks网络驱动配置及分析 VxWorks系统网络驱动在BSP中完成,写驱动时应参考BSP develop kit,在VxWorks中叫做END( Enhanced Network Driver),编写程序使用由VxWorks定义的MUX接口 MUX是数据链路层和网络协议层之间的接口 主要调用过程和步骤如下: VxWorks系统执行的第一个任务target\config\all\usrConfig.c文件中 usrRoot()=======>> target\src\config\usrNetwork.c文件(该文件初始化TCP/IP)中 usrNetInit(BOOT_LINE_ADRS)(该函数作用是添加MUX END)========>> pcooki = pCookie = muxDevLoad(pDevTbl->unit,.....)其中pDevTbl在BSP网络配置文件configNet.h中定义.END_TBL_ENTRY endDevTbl[]={...},该表定义了网络设备的具体参数,在这里调用了网络驱动 END_TBL_ENTRY endDevTbl [] = ========>>muxDevStart(pcooki)==========>>ibmEmacEndLoad()
ibmEmacEndLoad()初始化系统为网络驱动运行做准备 MUX调用ibmEmacStart() ibmEmacStart() 登记中断服务程序ibmEmacInit(),启动设备运行在中断模式下. LOCAL STATUS ibmEmacStart ( EMAC_DRV_CTRL * pDrvCtrl ) SYS_INT_CONNECT (pDrvCtrl, ibmEmacInt, pDrvCtrl, &rc); /* Allow MAL EOB and Des criptor error interrupts */ malChannelIntMaskSet(MAL_TX_TYPE, pDrvCtrl->txChn0MalChannel, malChannelIntMaskSet(MAL_RX_TYPE, pDrvCtrl->rxChn0MalChannel, return (OK); 中断服务程序ibmEmacInit() 处理EMAC控制器的中断,主要是 TX,RX状态错误 LOCAL void ibmEmacInt ( EMAC_DRV_CTRL * pDrvCtrl ) /* Read the EMAC interrupt status register */ SYS_IN_LONG(pDrvCtrl, EMAC_ISR, isrReg); /* if (isrReg & EMAC_ISR_TX_INTS) /* if (isrReg & EMAC_ISR_RX_INTS) return; (未完)
Cillus网卡CS8900A Linux驱动 下面是我为一个网友解释的CS8900A网卡驱动文件中的部分函数,操作系统为ucLinux,CPU是国内常用的Motorola龙珠系列MC68EZ328(16M),相比PowerPC和ARM来说,它的结构简单,不带MMU,较易理解 CS8900A是一个16位网卡,支持ISA总线,10-BastT. static inline void outw(unsigned short value,unsigned int addr) //这里为什么要交换一下? ////++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ _dest[0]=_src[1]; static int cs89x0_probe1(struct device *dev, int ioaddr) irq2dev_map[0] = dev; /* set up the chip select */ //下面这一段该怎么理解?看不懂阿 //连通PORT F I/O功能管脚1,SEL1(-IRQ5/PF1), //连通PORT F 中断功能管脚1,SEL1(-IRQ5/PF1) //*(volatile unsigned short *)0xfffff302 |= 0x0080; ..................... void /* wait 30 ms */ /* Wait until the chip is reset */ static int write_irq(dev, lp->chip_type, 0); irq2dev_map[/* FIXME */ 0] = dev; //这里和上面那个一样,怎么看懂? //中断信号,正电平触发(POL5) //调整PORT G的输入输出状态,及设置管脚相应的电平信号 ////++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ......................... static void //下面两行怎么右边是一样的? ...................... static int return 0;
返回页首
LCD 与触摸屏 返回页首
Modem拨号 Modem拨号程序步骤如下
最好按上述步骤一步一步调,并要等待正确的返回值后再进行下一步. 具体程序例子如下,拨号: // 清空接收FIFO
|