Android(Linux)线路规程的使用

    一般来说,车载导航主机都需要外接若干个UART的外设,如支持HFP的蓝牙模块、与原车通信的CAN解码盒模块、u-blox的GPS模块和DVD机芯等。早年使用Telechips TCC8902+WinCE6.0的方案,该芯片串口比较多,基本够用。最后实在不够时想了一招,动态复用调试串口,参见《WinCE下调试串口的动态复用》。后来改用RK3188+Android做车机,RK3188没那么多串口,于是将所有串口外设都接到了STM32上,甚至把触摸屏和收音机等IIC的设备也一并接了过去。STM32负责在RK3188和各个外设之间做数据透明传输。不得不说STM32确实很强大,当然也得亏姚同学用的出神入化了。一个软件支持几十款触屏,N版硬件,自己写的OS在上面跑得飞快。他用STM32把所有的外设都搞掂了,对主CPU就一个串口,数据流示意图如下。

    Android更新太快,RK3188没多久也过时了,后来改用MTK6735做主CPU。姚同学分分钟就把STM32程序移植到了新板子上。用老邓的话说,姚同学就是快!板子拿给我,开始移植Android驱动。原来在RK3188上是直接修改的串口驱动底层,从中断开始、缓存、打包分发等,触屏驱动也是基于原有GT9XX驱动修改的,看了半天,觉得这种方式平台依赖性太大,不便于移植。后来跟老邓和GYP讨论,准备修改软件架构,写一个虚拟设备驱动读取串口数据,并用成对的虚拟串口将数据分发到Bluetooth、CAN等设备驱动中。如此,所有设备驱动都是纯虚的,就无需修改MTK6735串口驱动了,以后再移植到其他平台也会很方便。想得很美,可是刚动手就发现有问题。虚拟设备驱动无法读取TTY设备,这跟WinCE完全不同,Linux不能在驱动里调用open,read。搜遍Linux的驱动代码,几乎就没有这样用的,仅有几处,也是做调试用,看着都别扭,网上也找不到相关的信息,而《Driving Me Nuts - Things You Never Should Do in the Kernel》里明确提到,禁止这样做,且文章还分析了为什么开发者会有此种不合理的想法,摘录如下:
  The most common question asked in this don't-do-that category is, "How do I read a file from within my kernel module?" Most new kernel developers are coming from user-space programming environments or other operating systems where reading a file is a natural and essential part of bringing configuration information into a program. From within the Linux kernel, however, reading data out of a file for configuration information is considered to be forbidden. This is due to a vast array of different problems that could result if a developer tries to do this.
    此路不通,再想别的办法。驱动里不能读取TTY设备,那么就写一个应用读取TTY设备,再将读取的数据分发到Bluetooth等设备驱动中。可仔细一琢磨,觉得这个方案很糟,数据流绕了很多弯,非常不好。还有没有别的法子?Linux下支持串口鼠标、串口蓝牙模块和串口的Modem,它们都是如何在驱动里获取TTY上的数据的呢,一定有妙法!虽然项目有点急,姚同学又太给力,但我还是打算再研究两天,不急于动手去改原生的串口驱动。我知道那是一个坑,掉进去一次就会有第二次第三次,宁可慢点也要绕过它去。
    功夫不负有心人,后来终于Google到一篇介绍TTY的好文,《The TTY demystified》。其中提到:
  Incidentally, the kernel provides several different line disciplines. Only one of them is attached to a given serial device at a time. The default discipline, which provides line editing, is called N_TTY (drivers/char/n_tty.c, if you're feeling adventurous). Other disciplines are used for other purposes, such as managing packet switched data (ppp, IrDA, serial mice), but that is outside the scope of this article. 
    这就是我想要的东东啊!虽然作者没有详述line discipline,但他明确指出Modem及串口鼠标等都使用了线路规程来处理数据,而TTY本身就是默认的线路规程。真是山穷水复疑无路,柳暗花明又一村!接下来重点研究线路规程是如何工作的,并找一个合适的驱动移植过来,最终选定kernel-3.10/drivers/tty/n_hdlc.c为驱动模版进行移植,它支持数据帧的打包和双向通信。Linux下驱动开发,尽可能找现成的移植,这样效率才会高。《Writing a Kernel Line Discipline》也是一片好文,在移植驱动时很有帮助。
    Linux下UART数据流如下图所示。

    简易图如下:

    原来在RK3188上是修改的Low level serial driver,平台相关性太大,如果原厂更新了串口驱动也需要手动同步代码。使用线路规程的方式,则避免了以上问题,且与平台无关,移植非常方便。在MT6735上移植好所有驱动后,后来项目改用MT8735,大概只花了半个小时就移植好了,只要拷贝线路规程驱动、虚拟触屏驱动、收音机驱动、蓝牙模块驱动和uartd应用,修改几个配置文件后编译即可,不用修改一行代码。其中uartd是一个用来切换线路规程的应用。后面如果采用高通的CPU,应该也可以分分钟搞定。
    使用线路规程,除了实现以上基本功能外,同时还增加了一个监测及抓取UART上所有数据流的功能,便于后期开发调试新的串口外设。不得不说,线路规程真是个好东西!Linux的驱动架构实在是牛!
时间: 2024-10-07 18:44:51

Android(Linux)线路规程的使用的相关文章

Android(Linux)实时监控串口数据

    之前在做WinCE车载方案时,曾做过一个小工具TraceMonitor,用于显示WinCE系统上应用程序的调试信息,特别是在实车调试时,用于监控和显示CAN盒与主机之间的串口数据.因为需要抢占市场先机,经常在新车上市前,就得配合CAN解码盒厂商同步调试车机端软件.这时候,TraceMonitor就可能派上大用场.遇到说不清是哪一边的问题时,抓数据一看,就清清楚楚了.有时终端客户的机器出现了原车功能异常的问题,也可以直接运行该工具,实时抓取串口数据提供给我们以分析问题原因.不过该工具需要业

android linux 静态库的生成和使用

问题描述 android linux 静态库的生成和使用 有个android手机项目,linux3.10,kernel里面有几个文件不想开源出去,想做成静态库一起发布给客户 请问一下怎么将这几个文件做成静态库,做出来后放在哪个目录,再编译整个kernel的时候.mk文件该怎么写 希望能帮忙详细的举个例子,感谢 解决方案 http://blog.chinaunix.net/uid-25885064-id-3066814.html android不太显示,因为手机的cpu型号太多,你不提供源代码,那

android/linux 怎么将调试串口切换成普通串口

问题描述 android/linux 怎么将调试串口切换成普通串口 已经试过如下方法:1.在内核编译过程中执行make menuconfig Character devices ---> Serial drivers ---> S3C2410 serial port support [ ] Console on S3C2410 serial port [注]去掉这项即可 不行.2.fp = open(""/dev/ttySAC1""O_RDONLY);

Android(Linux)控制GPIO方法二

前文<Android(Linux)控制GPIO的方法及实时性分析>主要使用Linux shell命令控制GPIO,该方法可在调试过程中快速确定GPIO硬件是否有问题,即对应的GPIO是否受控.实际项目中,一般需要对GPIO做特殊控制,如车载导航系统开机就给GPS模块上电,或在daemon程序中控制GPIO给一个脉冲以Reset蓝牙模块等,就不便用shell 命令来控制,而需要另想办法. http://elinux.org/RPi_GPIO_Code_Samples#sysfs介绍了如何在C代码

I.MX6 Android Linux UART send receive with multi-thread and multi-mode demo

/******************************************************************************************* * I.MX6 Android Linux UART send receive with multi-thread and multi-mode demo * 声明: * 1. 本软件是为了测试Android底层的Linux驱动以及硬件是否存在缺陷而编写的测试软件: * 2. 本软件可以设置为发送.接收.发送并接

I.MX6 Android Linux shell MMPF0100 i2c 设置数据

#!/system/bin/busybox ash # # I.MX6 Android Linux shell MMPF0100 i2c 设置数据 # 说明: # 本文主要记录通过shell脚本来设置MMPF0100的数据. # # 2016-4-6 深圳 南山平山村 曾剑锋 # # 检查参数个数 if [ $# -lt 3 ]; then echo "USAGE:" echo " i2cSetData.sh <curPage> <address(hex)&

I.MX6 Android Linux shell MMPF0100 i2c 获取数据

#!/system/bin/busybox ash # # I.MX6 Android Linux shell MMPF0100 i2c 获取数据 # 说明: # 本文主要记录通过shell脚本来获取MMPF0100的数据,更多的是为了更为 # 方便的获取到数据,在进行一些调试的时候能够更有效. # # 2016-4-1 深圳 南山平山村 曾剑锋 # # 检查参数个数 if [ $# -lt 3 ]; then echo "USAGE:" echo " i2cData.sh

android linux shell 日期设置

/************************************************************************ android linux shell 日期设置 * 说明: * Android下的linux shell中的date和普通的date指令不一样,这里记录一下. * * 2016-6-6 深圳 南山平山村 曾剑锋 *********************************************************************

android linux 环境-android for linux sdk怎么装?

问题描述 android for linux sdk怎么装? eclipse.adt.sdk已下载,adt已安装到eclipse插件,sdk不知到怎么安装了...求指教--- 谢谢各位的不吝赐教,小弟以解决!!!(墙外的空气真好) 解决方案 Android SDK for linux 设置代理64位linux系统无法运行Android sdk的adb和aapt,提示No such file or directory的解决办法android:xlargeScreens=""false&q