44922004.doc
3.6 SIO
3.6.1 SIO模块的架构
在高通平台,SIO模块的整体架构如下图所示:
sevice layerDIAGDATANMEA Control layerRDMDS3GSIOLIB Device layerSIO interfaceSIO Device driverHW Service layer主要实现相关服务,DATA等等,Control layer主要负责设备与服务的管理,如DIAG、
并且加上相应管理机制。Device layer可以分为两层,SIO Interface向上层提供统一的接口,隐藏了硬件的相关操作。SIO Device driver实现相关硬件驱动。
开机时,在tmc_init函数中,会依次调用rdm_get_prev_port及rdm_issue_open函数,rdm_get_prev_ports()的作用在于读取保存在efs中的设备映射表。在设备映射表中保存了上次断电前的设备映射表。读出设备映射表内容将其放入到rdm_current_device_map[ RDM_DEV_MAX ]之
联想移动产品开发部软件处 - 28 -
44922004.doc
接着调用rdm_issue_opens(),中。根据读出的rdm_current_device_map[ RDM_DEV_MAX ]的内容,打开相应的port。
RDM的作用在于动态的修改设备映射关系,那么在应用中可以动态修改设备映射关系。只要调用相关接口rdm_assign_port就可以。
3.6.2 SIO数据处理流程
在上一节介绍了高通平台中SIO模块的整体架构,但我们经常涉及到其中一部分(device layer),通常也是修改这一部分。在这一节我们将详细介绍SIO的数据处理流程。
SIO数据接收:
RX FIFO中如果有数据,则会从DSM Pool中申请得到一个DSM item,然后将RX FIFO中的数据装载到这个DSM item中,然后将这个DSM item入队到对应的watermark中,watermark在有新的DSM item加入时会进行监测,看数据是否达到要求以调用不同的call back,发出信号通知application来处理这些数据。 当然也可以直接通过回调函数rx_fun直接处理DSM item。
联想移动产品开发部软件处 - 29 -
44922004.doc
SIO数据发送:
数据发送前会先申请一个DSM item,然后将要发送的数据填充到dsm item中,如果TX FIFO为空,则直接将这个dsm item中的数据传送到TX FIFO中,如果TX FIFO不为空(发送器正忙),则将
watermark会在适当的时候将这些数据发送到TX FIFO这个dsm item入队到相应的water mark中,
中。
3.7 重启问题分析
重起及异常无非就是软件和硬件的原因; 万事皆有根源。我们在分析的过程中通常需要排除,定位。2. 程序跑飞,硬件上的异常现象通常表现在: 1 电压过低(或限流过低)没有规律(这通常是flash的原因,时序太紧了);等等这些原因用调试器,软件的方法是没法查找的,是一些经验问题,在驱动调试阶段一般可以解决。 还有就是软件上的问题, 这些问题我们一般都可以寻根溯源, 在异常向量表的地方打断点,逐步尝试, 一般可以定位到:指令没定义,指令预取异常, data abort, 或者就是reset。 这些原因我们都可以根据r14 的值来回溯, 查找; 这些方法技巧做嵌入式的软件工程师都应该有所了解,加以掌握。
3.7.1 软件狗检测异常
通常重起时,我们跟踪会在0地址打断点, 然后根据r14(或者r14-4,r14-8)的值进行回溯,
一般可以找发生重起的地方, 然后再分析原因。 通常有两种情况:
1. 就是dog task 跑起来之前重起, 通常是在初始化过程中没有及时踢狗, 这时要审查代
码在适当的地方(处理费时的地方)加入硬件踢狗, 多试几处, 通常可以解决问题; 2. 就是dog task 跑进之后重起,就是下面所描述的。
在QSC60x5系列的平台里面有一个优先级最高的任务Dog task,它用来监测其它task是否在正常运行,如果某一任务陷入了死循环,或者长时间占有系统资源不释放,导致其它任务不能及时的得到调度,这时候dog task会认为当前的任务调度出现了问题,当dog task认为在规定的时间之内某一个task 还没有给自己做dog_report()的动作时,它就认为该任务已经死了,所以dog task接下去会去调用:err_fatal_put_log ( 0,(char*)&(dog_task_info[loop_index].task)) 发生这种情况时,我们需要先确认是否真的是由于dog task检测的原因导致重启的,通过调试器在spider上可以跟踪。步骤如下:
联想移动产品开发部软件处 - 30 -
44922004.doc
如上图,将断点设置到dog.c文件的 err_fatal_put_log ( 0,(char*)&(dog_task_info[loop_index].task))处,如果设置了你需要的debug操作后,程序进入到这里,那么很可能就是某一个task没有给dog task做dog_report()导致的原因。具体还可以定位到是哪一个task没有做dog reprot导致超时的。这可以再深入研究里面的代码。
3.7.2 发生data abort导致重启
ARM中有一种异常称之为data abort。当PC指针指向一段未定义区域并访问(读或者写)的时候,系统会发生data abort异常。这时候PC指针会自动跳转到0x10的地方执行data abort的处理程序.目前QSC60x5平台同样在这个时候设置了一个死循环,导致硬件狗超时并重启。Data abort的情况在实际开发过程中也经常发生,数组越界,指针乱指,都有可能导致data abort异常发生。 发生了data abort的时候可以将断点直接设置到0x10 data abort的程序入口处,通过回溯R14寄存器来找到发生data abort的地方:R14 – 8的地方就是发生data abort的地方。
3.7.3 指针未初始化引起的系统重启
下面这个代码说明了一个极为常见的错误: int *a;
联想移动产品开发部软件处 - 31 -
44922004.doc
*a = 12;
这个声明创建了一个名叫a的指针变量,后面那 条赋值语句把12存储在a所指向的内存位置。但是a指向那里呢?我们声明了这个变量,但从未对它进行初始化,所以我们没有办法预测12这个值将存储于什么地方。从这一点看,指针变量和其他变量并无区别。如果变量是静态的,它会被初始化为0;但如果变量是自动的,它根本不会被初始化。无论是那种情况,声明一个指向整型的指针都不会“创建”用于存储整型值的内存空间。由于指针没有被初始化所以这个指针包含一个“随机的合法的‖地址。接下来的事情很简单:位于该“随机的合法的”地址位置的值被修改,虽然操作者并无意去修改它。这种类型的错误非常难以捕捉,因为引发的错误可能与原先用于操作那个值的代码完全布相干。所以,在呢对指针进行间或访问之前,必须非常小心,确保它们已被初始化。
3.7.4 注意事项
1、将使用到的比较大的栈变量使用static修饰,或者改为MALLOC,使用堆空间。 2、避免使用递归。
3、函数调用的参数使用结构指针,不要使用结构体做为参数。 4、使用指针变量之前必须初始化 5、在写数组或者MEMSET中,检测边界 6、在大段程序执行注意踢狗 总之最重要的是仔细!
联想移动产品开发部软件处 - 32 -