一、GPS 简介
GPS 全称是,全球定位系统(Global Positioning System,GPS),它是一种以人造地球卫星为基础的高精度无线电导航的定位系统,它在全球任何地方以及近地空间都能够提供准确的地理位置、车行速度及精确的时间信息。该系统包括太空中的 24 颗 GPS 卫星、地面上 1 个主控站、3 个数据注入站和 5 个监测站及作为用户端的 GPS 接收机。GPS 在小车上的应用已经随处可见,下面我们将会跟大家一起分享如何在 i.MX8QM Android 上实现 GPS 地图导航功能,实现 GPS 功能用到的软硬件平台分别是:
硬件平台:IMX8QMMEK EVM BOARD
软件环境:IMX-P9.0.0_2.1.0-AUTO-GA
首先,我们先来看看 GPS 的主要优点:
1、能覆盖全球 98% 的面积,并确保实现全球全天候连续的导航定位服务
2、室外定位精度高
3、高效率、低成本,测站间无须通视
4、操作简便,只需要一台 GPS 接收机即可准确确定用户所在位置
5、GPS 不限制终端数,在 GPS 卫星信号不被阻挡的情况下,在地球上任何地点、任何时间,任何 GPS 终端都可以得到正确的位置和时间
6、功能多,应用广泛,可应用于军事、道路、车辆、船舶等导航多种应用中
但是 GPS 需要终端内置卫星信号接收模块,定位精度受终端所处环境的影响较大。如果终端处于大型建筑物之间或者室内环境下时,能接收到的卫星信号太弱,卫星定位的精度将降低,无法进行定位计算而无法完成定位。所以 GPS 定位只适用于室外的应用场景,而且首次定位时间比较长,一般小于 40s。
GPS 使用的通讯协议是 NMEA(National Marine Electronics Association),它是一套定义接收机输出的标准信息,有几种不同的格式,每种都是独立相关的 ASCII 格式,逗点隔开数据流,数据流长度从 30-100 字符不等,通常以每秒间隔选择输出,最常用的格式为“GGA”,它包含了定位时间,纬度,经度,高度,定位所用的卫星数,DOP 值,差分状态和校正时段等,其他的有速度,跟踪,日期等。NMEA 协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有 $GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL 等。
二、UART 通信
我们使用的 GPS 模块是通过 UART 进行数据传输,首先我们需要打通 UART 链路,根据硬件连接确定 UART 口。我这里的 GPS 模块连接到的是主芯片 UART1_RX 引脚,对应的设备名称是 ttyLP1,同时对应到 GPS 驱动代码 gps.c 如下位置:
连接好硬件后,可以使用如下命令测试 GPS 模块是否正常工作:
cat dev/ttyLP1
输出结果如下,说明 GPS 模块已经在正常运行,只要供电正常, GPS 模块就会不断输出 NMEA 格式的位置信息:
至此,我们已经确定了硬件及 UART 通讯正常。
三、GPS 驱动移植
接下来就需要开始进行驱动部分的移植,上一节已经介绍了修改驱动代码里面对应到硬件的 UART 口,修改完之后就可以将 gps.c 、Android.mk、power-stub.c 这三个文件放到 SDK 里面进行编译。步骤如下,在 android_build/hardware/libhardware/modules 目录下新建 gps 文件夹,然后将以上两个文件放到该目录下,在 android_build 目录执行如下命令编译:
mmm hardware/libhardware/modules/gps/
编译完成后就会在 out/target/product/mek_8q/system/lib64/hw/ 目录下生成对应的 gps.default.so 文件
注:这里要注意,我们需要使用的是 64 bit 的文件,可以使用 file 命令查看文件属性
将生成的 so 文件放到 out/target/product/mek_8q/vendor/lib64/hw/ 目录中,重新编译 kernel,编译完成后会生成如下镜像
四、添加 GNSS 服务
如果只是将上述生成的镜像文件烧录进开发板进行测试,GPS 模块还不能正常工作,log 会提示找不到 provider:
W System.err: java.lang.IllegalArgumentException: provider doesn't exist: gps
还需要进行如下步骤操作:
① 打开文件 android_build/device/fsl/imx8q/mek_8q/mek_8q.mk,添加 gnss 服务
# GNSS HAL PUAL
PRODUCT_PACKAGES += \
android.hardware.gnss@1.0-impl \
android.hardware.gnss@1.0-service
② 打开文件 android_build/device/fsl/imx8q/mek_8q/manifest.xml,添加 gnss hidl
android.hardware.gnss
hwbinder
1.0
IGnss
default
③ 打开文件 android_build/device/fsl/imx8q/mek_8q/BoardConfig.mk,添加
#GNSS PUAL
BOARD_HAS_GPS_HARDWARE := true
④ 打开文件 android_build/device/fsl/imx8q/mek_8q/ueventd.freescale.rc,添加
/dev/ttyLP1 0660 system gps
完成上述添加之后,执行 make 命令重新编译,编译完成后再次烧录镜像文件。
五、添加 Selinux 权限
将上一节得到的镜像文件烧录后进行测试,会发现系统启动异常,启动画面一直停留在 Android 图标处,通过 logcat 命令查看 log:
mek_8q:/ # logcat | grep gnss
04-26 04:05:44.923 3358 3358 F DEBUG : pid: 3299, tid: 3299, name: android.hardwar >>> /vendor/bin/hw/android.hardware.gnss@1.0-service <<<
04-26 04:05:44.927 3358 3358 F DEBUG : #04 pc 0000000000000ae8 /vendor/bin/hw/android.hardware.gnss@1.0-service (main+40)
04-26 04:05:49.716 3511 3511 W android.hardwar: type=1400 audit(0.0:593): avc: denied { read } for name="vndbinder" dev="tmpfs" ino=9486 scontext=u:r:hal_gnss_default:s0 tcontext=u:object_r:vndbinder_device:s0 tclass=chr_file permissive=0
可以看到,log 提示 hal_gnss_default 缺少 read 权限,这时我们还需要修改 Selinux 权限:
在 device/fsl/imx8q/sepolicy/system_server.te 中添加:
allow hal_gnss_default vndbinder_device:chr_file { read };
添加完以上权限之后,make 重新编译,然后将生成的 image 烧录进开发板后就可以进行最后的测试了。
六、APP 测试
经过以上步骤,我们将烧录了 image 的开发板启动,下载百度地图 APP,连接上网线。如果配置都是正常的,通过百度地图就可以搜索到当前所在位置的定位(GPS 模块需要在窗口或者室外才可以搜索到),搜索到画面如下图所示。
以上就是如何在 i.MX8QM Android 上实现 GPS 地图导航功能的一步步带你上手的过程,下期我们将会推出 基于 i.MX8 Android 平台 GPS 启动流程分析的内容。
接下来我们也会不断更新更多关于 i.MX8 系列的开发博文,同时我们也会持续推出更多 ADAS 相关(S32V234、Hi3566V100、Hi3559AV100、Hi3518EV300、硬件、软件、算法等)的技术开发博文,如需更深入的技术交流,欢迎在博文下方评论或者关注给我留言。
【参考资料】:
3. GPS 研究二(Android 2.3__gingerbread)
4. How to enable GNSS function in Android 8.1 HAL
评论
Wan-Lai
2021年2月23日