高通平台Driver开发的参考文档.docx
《高通平台Driver开发的参考文档.docx》由会员分享,可在线阅读,更多相关《高通平台Driver开发的参考文档.docx(34页珍藏版)》请在冰豆网上搜索。
高通平台Driver开发的参考文档
高通平台Driver开发的参考文档
版权说明
本文本中所包含的一切信息,包括文字,图表,数据,图形,图象,方法和思想都是联想移动通信科技有限公司财产,未经联想移动通信科技有限公司书面授权,任何个人和组织都无权透露,拷贝,复制,拍照和传输该文本中的一切信息。
联想移动通信科技有限公司版权所有
修订记录
版本
作者
审核
批准
日期
修改说明
1.00
Chenljc
2009/11/13
Create
目录
第1章前言3
1.1文档目的及开发背景3
1.2参考文献3
1.3术语和缩写解释3
第2章综述5
2.1高通平台的硬件架构5
2.2高通平台驱动文件结构6
2.3ARM相关知识6
2.3.1ARM基本知识6
2.3.2ARM存储器格式9
第3章Driver相关模块介绍10
3.1REX简介10
3.2Boot11
3.2.1NorBoot13
3.2.2NandBoot13
3.2.3Boot流程14
3.3Gpio15
3.3.1GPIO的作用15
3.3.2GPIO的用法16
3.3.3GPIO注意事项19
3.4内存管理19
3.4.1队列(Queue)19
3.4.2DS存储池20
3.4.3Watermark–flowcontrolpoint22
3.5Sleep25
3.5.1Sleep硬件相关知识25
3.5.2Sleep软件相关知识26
3.5.3查Sleep电流方法27
3.6SIO28
3.6.1SIO模块的架构28
3.6.2SIO数据处理流程29
3.7重启问题分析30
3.7.1软件狗检测异常30
3.7.2发生dataabort导致重启31
3.7.3指针未初始化引起的系统重启31
3.7.4注意事项32
第1章前言
1.1文档目的及开发背景
本文为高通平台driver开发的学习文档,对部分概念性的东西进行了学习和总结。
由于driver的跨度太大,内容很多,加上本人水平有限。
如有不足之处及遗漏地方,麻烦大家多多包涵!
希望这份文档能对大家学习高通平台的驱动开发有所帮助!
1.2参考文献
序号
文档名称
作者
出版单位
1
80-VC881-1&QSC6055&QSC6065QSC6075ANDQSC6085SINGLECHIPDEVICESPECIFICATION
Qualcomm
--
2
80-VC881-2&QSC6055,QSC6065,QSC6075,QSC6085SOFTWAREINTERFACE
Qualcomm
3
注:
高通提供的文档比较详细,各个模块都有相关文档!
因为文档提供比较齐全(需要自己去下,对于初学者是个难题),相对来说他的技术支持不怎么样!
有得必有失!
1.3术语和缩写解释
术语和缩写
解释
DS
DATAService
SIO
SerialInput&Output
RDM
RuntimeDeviceMappe
BT
BlueTooth
PBL
PrimaryBootLoader
第2章综述
2.1高通平台的硬件架构
目前开发EVDO的手机或模块大部分采用了QSC6085平台。
高通QSC系列的平台是高度集成化,它将PMIC、RF相关模块也集成到一块芯片里(其他公司很少做到这点),对硬件来说可以省很多事。
除了上述特殊模块之外,当然也包括一般的LCD、KPD、AUDIOCODEC等很多驱动模块!
具体如下图所示:
QSC6085处理器采用ARM9核+DSP的架构,一般就不需要再加DSP去处理Audio和图片。
它集成这么多,其他硬件厂商的饭碗都被他抢了,不过这也是大势所趋!
2.2高通平台驱动文件结构
在一般高通工程(60X5系列)目录下有一个Drivers文件夹,在该文件夹下包含了60X5系列平台上所有驱动文件,分门别类!
从上图中我们可以看到,每一个驱动都有独立的文件夹,这样对于新手学习代码来说比较容易找到相关代码。
2.3ARM相关知识
因为高通处理器采用的ARM内核,遵循ARM指令,我们有必要学习一下ARM的一些基础知识。
一般驱动开发中很少涉及到ARM指令,除了BOOT以及flash开发,大部分都在C语言环境中开发。
在这部分我讲的不会太深入,如果大家想深入了解ARM架构,可以去看《ARM体系结构与编程》这本书,相当经典!
2.3.1ARM基本知识
ARM采用的是32位架构。
也就是说ARMCPU内部的总线是32位的,每条ARM汇编指令都是32位的指令。
一个CPU时钟周期最多可以处理一条32位指令或者读取一个32位的数据。
32位的指令意味着,与8位和16位的CPU相比,在一个时钟周期内,指令可以携带更多的信息。
ARM有7个基本工作模式:
User:
非特权模式,大部分任务执行在这种模式
正常程序执行的模式
FIQ:
当一个高优先级(fast)中断产生时将会进入这种模式
高速数据传输和通道处理
IRQ:
当一个低优先级(normal)中断产生时将会进入这种模式
通常的中断处理
Supervisor:
当复位或软中断指令执行时将会进入这种模式
供操作系统使用的一种保护模式
Abort:
当存取异常时将会进入这种模式
虚拟存储及存储保护
Undef:
当执行未定义指令时会进入这种模式
软件仿真硬件协处理器
System:
使用和User模式相同寄存器集的特权模式
特权级的操作系统任务
ARM有37个32-Bits长的寄存器.
1个用作PC(programcounter)
1个用作CPSR(currentprogramstatusregister)
5个用作SPSR(savedprogramstatusregisters)
30个通用寄存器
当前处理器的模式决定着哪组寄存器可操作.任何模式都可以存取:
相应的r0-r12子集
相应的r13(thestackpointer,sp)andr14(thelinkregister,lr)
相应的r15(theprogramcounter,pc)
相应的CPSR(currentprogramstatusregister,cpsr)
特权模式(除system模式)还可以存取;
相应的spsr(savedprogramstatusregister)
CPSR寄存器表示当前ARM的工作状态
条件位:
N=1-结果为负,0-结果为正或0
Z=1-结果为0,0-结果不为0
C=1-进位,0-借位
V=1-结果溢出,0结果没溢出
Q位:
仅ARM5TE/J架构支持,指示增强型DSP指令是否溢出
J位:
ARM5TE/J架构支持J=1:
处理器处于Jazelle状态
中断禁止位:
I=1:
禁止IRQ.
F=1:
禁止FIQ.
TBit
:
T=0:
处理器处于ARM状态T=1:
处理器处于Thumb状态
Mode位(处理器模式位):
0b10000User
0b10001FIQ
0b10010IRQ
0b10011Supervisor
0b10111Abort
0b11011Undefined
0b11111System
2.3.2ARM存储器格式
在ARM体系中,每个字单元包含4个字节单元或者两个半字单元;一个半字单元中包含两个字节单元。
但是在字单元中,4个字节哪一个是高位字节,哪一个是低位字节则有两种不同的格式;big_endian格式和little-endian格式。
比如一个整型数0x12345678在内存中如下图所示
-----------
| 78 |xxxx_0000
-----------
| 56 |xxxx_0001
-----------
| 34 |xxxx_0002
-----------
| 12 |xxxx_0003
-----------
LittleEndian
-----------
| 12 |xxxx_0000
-----------
| 34 |xxxx_0001
-----------
| 56 |xxxx_0002
-----------
| 78 |xxxx_0003
-----------
BigEndian
第3章Driver相关模块介绍
3.1REX简介
虽说目前QSC60x5平台上采用L4操作系统,REX只是L4上面的一个Task。
但高通为了开发的兼容性,提供的API仍然采用老的一套接口(可能内部实现不一样),很容易将老的代码移植到新的架构中。
那么我还试必要介绍一下REX。
REX是一个操作系统的名字,它是Real-timeExecutive的缩写。
它是美国的QUALCOMM开发的,REX是一个简单的、高效的、抢占式的、多任务的、嵌入式实时操作系统。
它最初是为应用于Intel的80186而设计的,如今它已经被移植到了ARM微处理器上。
下面是它比较重要的几个概念(其实和其他操作系统一样):
1、Task
REX把任务当作独立运作的实体,每一个任务都有自己独立的堆栈和优先级。
每个任务都有一个数据结构,我们称为“任务控制块”(TCB)。
REX允许在运行时,在任何时间动态的创建任意数量的任务。
但是创建的任务越多,REX的性能便稍微递降,这是因为你创建的任务越多,任务列表越长。
所以你需要确保你创建的任务数量尽量小。
另外,REX任务的负载量还跟你选择的处理器有关。
下面的图描述了REX任务的启动过程:
TCB也是一个比较重要的结构体,各个task都有一个全局变量tcb,这个tcb包含了很多重要信息如,任务优先级、堆栈指针,信号量等,这些有时对查死机问题很有帮助。
2、任务调度
REX总是选择处于就绪态的最高优先级的任务进行调度,如果任务的优先级不是唯一的,REX可能选择任何一个处于就绪态的最高优先级的任务进行调度。
被选择的任务会一直执行,直到它自愿挂起或者中断发生而激活了更高优先级的任务。
当被挂起的任务的等待条件得到满足时,该任务就变成了就绪态。
如果所有的认为都挂起的时候,那么空闲认为就被执行。
REX提供了一种机制,允许任务可以动态的提高或降低自己或其它任务的优先级。
3、信号量
信号量是任务之间进行通信和同步的桥梁。
信号量是REX提供的一种任务间通信的机制。
每个任务都有一套与之相关联的通用信号量,信号量通常作为任务的TCB的一部分,它们被用来通知任务某种事件的发生,任务的信号量可以被任何其它任务或中断设置或清除。
信号量实际上是一种约定机制,在多任务内核中普遍使用,信号量用于:
控制共享资源的使用权(满足互斥条件);
标志某事件的发生;
使2个任务的行为同步。
4、中断
REX是一个可剥夺的内核。
当从中断返回的时候,控制权就被传递给处于最高优先级的就绪任务,而没有必要返回到被ISR中断了的任务处。
一般我们只会挂载GPIO中断,后续会介绍。
5、定时器
定时器,英文是timer。
和其它内核一样,REX要求给用户提供定时时间,来实现超时控制等功能。
REX中有些信号是事件触发引起,也可以由timer引起。
一旦由于某种原因,等待的事件信号一直等不到,这时可以用timer定时来产生信号量。
关于以上几个概念,高通都提供了相关接口操作,具体参看代码!
3.2Boot
高通平台系统Memory组成可以分为:
NAND+SDRAM和NOR+PSRAM。
两者配置不能并存,这也就决定了有两种boot模式,具体决定采用哪种Boots方式是Boot_mode引脚决定。
高通60x5系列采用了Multi-Image-Boot技术,这可以从高通的代码看出,
从上述枚举变量中可以看出,flash中有多个image.其中QCSBL+OEMSBL=SBL,SBL就相当于bootloader,Bootloader主要是在Nand启动方式中起作用!
原因后续介绍!
其中每个Image又是由三个部分组成:
其中签名段和证书段是用来校验代码段的完整性与合法性的。
在启动过程中就可以看到校验的相关步骤。
代码段就不需要我说了吧。
3.2.1NorBoot
Norflash有地址线,存在NorFlash的代码可以本地执行,变量存在PSRAM,所以从NOR启动不需要Bootloader
NOR启动模式太简单,一般只要将NorFlash挂载到EBI1上,然后做些简单的操作,就可以直接运行。
在高通代码中关于这方面的注释也很少。
3.2.2NandBoot
NandFlash没有地址线,代码不能直接运行,因此需要Bootloader,那么bootloader的作用:
可以看出相对NORboot,Nandboot复杂很多。
它需要将falsh中的Image复制到SDRAM,然后才能执行。
并且要对各个image进行校验。
3.2.3Boot流程
Boot是一个很复杂的过程,尤其是NandBoot,需要你对ARM架构很深的了解,这边只是简单示意相关流程,具体大家可以参考代码!
3.3Gpio
3.3.1GPIO的作用
GPIO作为QSC60X5与外界沟通的桥梁,主要有四个作用:
1.通过GPIO向外部输出一个高/低电平,控制外部的器件或者通知外部器件某事件的发生。
例如我们可以通过GPIO输出一个高电平点亮一个LED,或者输出低电平关掉一个LED。
2.通过GPIO读入一个外界的高低电平输入,检测外部器件的当前状态。
例如键盘按键是否
按下的探测。
3.将GPIO口作为外部中断信号的一个输入口,实时检测外部事件的发生。
4.将GPIO用作其他特定用途。
例如用作I2C通信、数据线、地址线等。
3.3.2GPIO的用法
1.配置一个GPIO口。
通常一个GPIO有多种功能,我们可以将GPIO配置为符合我们当前需要的功能;同时我们也可以将GPIO配置为内部具有上拉电阻、下拉电阻或者没有任何上下拉电阻。
文件GPIO_60x5.c中定义了配置GPIO的函数接口
voidgpio_tlmm_config(GPIO_SignalTypegpio_signal)
{
…
…
}
gpio_signal指定要配置成的功能,文件GPIO_60x5.h枚举出了每个GPIO的可配置的功能选项:
typedefenum
{
…
…
GPIO_OUTPUT_3=GPIO_OUT(3,0),
GPIO_INPUT_3=GPIO_IN(3,0,GPIO_PULL_DOWN),
SDCC_DATA0=GPIO_ALT(3,0,1,GPIO_PULL_UP),
DBG_BUS_IN_7=GPIO_ALT(3,0,2,GPIO_PULL_DOWN),…
…
}
例子:
SDCC_DATA0=GPIO_ALT(3,0,1,GPIO_PULL_UP)gpio_tlmm_config(SDCC_DATA);/*将GPIO3配置为SD卡的数据线1*/gpio_tlmm_config(GPIO_INTPUT_3);/*将GPIO26配置为通用的有下拉电阻的输入端口*/
2.从GPIO输出高/低电平。
首先应该通过函数接口gpio_out来确定GPIO输出高电平或者低电平,然后通过函数接口gpio_tlmm_config把该GPIO配置为通用功能(非特定功能),在该配置函数中调用一个宏函数接口BIO_TRISTATE打开GPIO使能,将此电平输出出去。
voidgpio_out(GPIO_SignalTypegpio_signal,GPIO_ValueTypegpio_value)/*将GPIO寄存器设置输出的电平*/BIO_TRISTATE(io,mask,val)/*GPIO寄存器中的值输出出去:
输出使能*/
例子:
使GPIO31输出低电平
gpio_out(GPIO_OUTPUT_31,GPIO_LOW_VALUE);
gpio_tlmm_config(GPIO_OUTPUT_31);
3.从GPIO读入外部器件输入的高/低电平,检测外部的事件或者状态。
只能从一个输出已被disable的GPIO读入输入的高/低电平,也就是说只能从一个已被设置为输入模式的GPIO读入高/低电平。
从GPIO读入外部输入的高/低电平的宏函数接口:
GPIO_ValueTypegpio_in
(
GPIO_SignalTypegpio_signal
),
gpio_signal解释见上面的说明,而返回值
typedefenum
{
GPIO_LOW_VALUE=0,
GPIO_HIGH_VALUE=1
}GPIO_ValueType;
例:
判断GPIO3的当前状态
gpio_tlmm_config(GPIO_INTPUT_3);
if(gpio_in(GPIO_INTPUT_3)==GPIO_LOW_VALUE)
{
…..
}
4.将GPIO设置为某个中断信号的输入口。
这样外部器件一旦有中断信号(高电平或者低电平)输入到此GPIO端口,将直接触发一个中断,指定的ISR将被调用,处理中断事件。
中断的好处在于中断事件可以实时得到处理,无论系统是否处于睡眠状态。
接口函数有两个:
A)gpio_int_set_detect(gpio_int_typewhich_group_int,gpio_int_detect_typedetect)/*指定边沿触发还是电平触发*/
B)booleangpio_int_set_handler
(
gpio_int_typewhich_group_int,
gpio_int_polarity_typepolarity,
gpio_int_handler_typehandler
)/*指定ISR以及触发极性*/
typedefenum
{
/*GPIO_GROUP1*/
GPIO_INT_0=0,
GPIO_INT_1,
GPIO_INT_2,
GPIO_INT_3,
GPIO_INT_4,
…
…
}gpio_int_type;
typedefenum
{
DETECT_LEVEL=0,
DETECT_EDGE
}gpio_int_detect_type;
typedefenum
{
ACTIVE_LOW=0,
ACTIVE_HIGH
}gpio_int_polarity_type;
A)参数which_group_int指定GPIO,detect指定中断是电平触发方式还是边沿触发方式。
B)参数which_group_int指定GPIO,polarity与gpio_int_set_detect中指定的detect值相关,若detect指定电平触发方式,polarity就表示指定中断是高电平触发还是低电平触发;若detect指定边沿触发方式,polarity就表示指定中断是上升沿触发还是下降沿触发。
handler指定该中断的ISR,若handle为NULL则表示取消此GPIO的中断处理,
也就是说以后此GPIO输入任何信号都不会触发中断了。
例子:
/*将GPIO3设置为中断高电平触发*/
gpio_int_set_detect(GPIO_INT_3,DETECT_LEVEL);
gpio_int_set_handler(GPIO_INT_3,ACTIVE_HIGH,&GPIO_3_isr);
3.3.3GPIO注意事项
1.必须保证我们要用的GPIO没有已被其他地方用作其它用途,否则可能会出现一些莫名其妙的现象。
2.确保GPIO已被正确配置。
每个GPIO都有缺省的配置,如果缺省的配置不符合我们的要求,我们就需要对GPIO进行重新配置。
3.注意GPIO的上拉电阻或者下拉电阻的设置情况。
例如:
将GPIO设置为有下来电阻输入口,若外部输入的高电平电压不够高,就可能导致读入电平介于高低电平电压之间,从而无法准确辨别出高电平还是低电平。
3.4内存管理
高通平台上内存管理机制由三个部分组成:
队列(Queue)、DS存储池、Watermark。
其中真正存放数据的DS存储池,其他两个则是管理机制。
3.4.1队列(Queue)
•Single-linkedlistofdatablocks(数据块单链表)
•Eachdatablockhasalinkfieldtothenextdatablock(每个数据块有一个指针域(linkfield)指向下一个数据块)
•Alwaysusequeuefunctionstousethequeues(总是使用队列函数来操作队列)
–Declaredinqueue.h
–q_init()–initializesthequeue(初始化队列)
–q_link()–initializesthelinkfieldoftheitem(初始化队列的指针域)
–q_get()–removestheelementfromtheheadofthequeue(从队列头部取出一个元素并将其从队列中去除)
–q_check()–returnsthepointertothefirstelement;doesnotremove(返回队列的第一个元素的指针,但不删除它)
–q_put()–putstheelementatthetailofthequeue(添加一个元素到队列尾部)
–q_cnt()–countsthenumberofelementsinthequeue(计算队列中有几个元素)
ThemodelofQueue:
队列广泛使用在DS的存储池中,贯穿于整个DS的相关代码中。
3.4.2DS存储池
在高通软件平台上,它的数据存储方式比较特别。
事先划分一块区域用于数据存储,并且为不同应用再细分一个Pool(