地图导航应用 系统架构_c语言本文首先概述HD-GR导航软件的基本功能、开源传承、运行开发环境、并发任务目标、等等,然后比较全面地介绍HD-GR导航软件的任务结构和处理逻辑。

4.1 概述

地图导航应用 系统架构_c语言HD-GR导航软件(AGRS_GP_1)是面向NIOS II软核和μC/OS-II RTOS设计开发的开源软件包,实现了实时接收机导航定位所需的基本软件功能,支持应用GPS和BDS完成单系统或双系统定位任务。

地图导航应用 系统架构_c语言AGRS_GP_1项目以Namuru开源GPS代码为基础。Namuru是新南威尔士州大学(UNSW)开发的开源GPS接收机研究平台的名称。2006年,Namuru成功地将运行在开源eCos RTOS中的早期开源GPS软件GPL-GPS,移植到了它的Namuru GPS接收机中,并将移植后的开源软件称为Namuru GPL。开源Namuru GPL可以从网络下载,模块代码由UNSW的Peter Mumford移植和应用于Namuru V2 电路板,最终修改年份为 2007年。

地图导航应用 系统架构_c语言AGRS_GP_1项目继承了Namuru GPL的基本设计和大部分代码,成功地将Namuru GPL代码移植到了Nios-II支持的μC/OS-II RTOS之中,并进一步扩展为支持BDS定位和GPS/BDS双系统混合定位。概括而言,AGRS_GP_1项目能够并发完成以下任务:

  • 读取HD-GR基带模块中的通道累积器
  • 控制HD-GR基带模块中的通道跟踪环
  • 监控通道环路锁定状态
  • 计算接收机位置
  • 分析从卫星接收到的GNSS导航电文
  • 采集观测数据
  • 产生RS232输出数据流

地图导航应用 系统架构_c语言项目AGRS_GP_1使用软件生成工具(Nios II IDE)创建。Nios II IDE创建AGRS_GP_1项目的同时,使用SOPC信息文件AGRS_GP_1_SYS.sopcinfo和所选择的μC/OS-II RTOS操作系统,创建了BSP项目AGRS_GP_1_bsp。这个BSP项目是C源文件、头文件和初始化文件的集合,用于为系统中的硬件构建自定义库。此自定义库与编译后的应用程序相链接,为NIOS II CPU系统创建可执行的二进制文件,称为HD-GR导航软件(映像)。编译、链接后的映像可下载到HD-GR接收机运行或调试。这些任务可以在统一的Nios II IDE开发环境中完成。有关Nios II IDE的操作使用和开发流程参见有关参考。

地图导航应用 系统架构_c语言项目AGRS_GP_1中的源代码和可执行映像的基本情况如下:

  • 304 Kbytes ‘C’ 源码
  • 52 Kbytes ‘H’ 头文件
  • 740 KBytes可执行映像(包括系统和硬件自定义库)
  • 编译工具:Nios II 11.0 Software Build Tool for Eclipse

地图导航应用 系统架构_c语言在HD-GR导航软件运行过程中,除只执行一次的初始化代码外,其它功能块的执行都源自一个硬件中断的驱动和唤醒,基此实现从基带数据累积开始,到最终获得定位计算结果的目标。本文随后一节的软件任务结构以及本章接着几节(除最后一节外)的软件处理功能,正是循着在实现这一目标的过程中,信号和数据的流向来组织的。它们以基本的脉络揭示了这个软件这样设计和实现的粗略理由。

4.2 软件任务结构

地图导航应用 系统架构_c语言本节介绍HD-GR导航软件的任务结构。第一小节介绍AGRS_GP_1项目的基本设计。随后一小节给出项目的源文件列表,以及各文件包含的主要任务。接下来的几小节对主程序功能、任务执行逻辑、以及多任务同步机制进行描述,它们可参照图4-2中的软件并发任务结构来阅读。本章第4.7.1小节专门讨论多任务共享数据保护机制。

4.2.1 基本设计

地图导航应用 系统架构_c语言AGRS_GP_1项目继承了Namuru GPL的基本设计,成功地将实现在eCos RTOS中的Namuru GPL开源代码移植到了Nios-II支持的μC/OS-II RTOS之中。下面加以简单介绍。

地图导航应用 系统架构_c语言HD-GR导航软件包括两个重要部分,主程序和中断服务例程。图4-1说明了它的基本对象结构。三个基本对象是导航软件、基带通道、以及卫星。卫星通过射频信号作用于基带通道。每个通道与一颗卫星一对一通信。GPS星座和BDS星座有多达64颗卫星,HD-GR基带模块只有20个通道,分别与10颗GPS卫星和10颗BDS卫星相对应。基带模块以固定间隔(缺省约0.8 ms)发出累积中断(GNSS_BDMOD_IRQ);在导航软件中,由累积中断服务例程(accum_int_handler)响应每次中断,并通过它与其它部分进行交互。

地图导航应用 系统架构_地图导航应用 系统架构_11


图4-1 HD-GR导航软件的基本对象结构

地图导航应用 系统架构_c语言下面进一步描述导航软件的并发任务结构,参见图4-2;

  • 导航软件的主程序作为代码执行入口,首先顺序完成以下任务:
  • 初始化包括基带模块在内的所有外围设备;
  • 创建信号和数据处理所需的任务(线程);
  • 注册累积中断处理例程(accum_int_handler);
  • 将程序执行控制权交给μC/OS-II内核。
  • 导航软件的信号和数据处理被分解为实时性、时间片、优先级不同的6个功能模块,分别在以下6个优先级依次递减的任务(线程)中执行。其中,相关数据累积任务(accum_task)是所有处理功能的入口,其它任务的唤醒都源自它的执行。
  • 相关数据累积任务(accum_task)
  • 观测量读取任务(meas_task)
  • 电文处理任务(message_task)
  • 星历处理任务(ephemeris_task)
  • 通道分配任务(allocate_task)
  • 定位计算任务(position_task)
  • 每当基带模块发出(导航软件中唯一的)累积中断(GNSS_BDMOD_IRQ),μC/OS-II内核都会立即调用累积中断服务例程(accum_int_handler);
  • 在每次中断服务例程(accum_int_handler)响应期间,只执行最简单和最关键的代码,之后立即唤醒相关数据累积任务(accum_task)来执行;
  • 多个任务(包括accum_int_handler)之间的同步执行用以下同步机制来保证:
  • 信号量(semaphore)
  • 事件标志集(flags)
  • 多个任务(包括accum_int_handler)之间的数据共享用以下同步机制来保证安全:
  • 信号量(semaphore)
  • 事件标志集(flags)
  • 互斥量(mutex)

地图导航应用 系统架构_地图导航应用 系统架构_13


图4-2 HD-GR导航软件的并发任务结构

4.2.2 源文件列表

地图导航应用 系统架构_c语言本小节给出AGRS_GP_1项目的源文件列表及其包含的主要任务:

constants.h							// 基本常数和宏定义
agrs_gp_1_ucos.c					// 主程序main(…)、累积中断处理例程accum_int_handler(…)
|-- spi_max2769.c					// 射频前端设置函数
|-- spi_max2769.h					// 及其定义
|-- rtc.c							// 实时数据备份和实时时钟函数
|-- rtc.h							// 及其定义
|
|-- main_accum_task.c				// 相关数据累积任务accum_task(…)
|-- main_accum_task.h				// 及其定义
  |-- gnsstime.c					// 接收机本地时间函数
  |-- gnsstime.h					// 及其定义
  |-- display.c						// 数据输出函数
  |-- display.h						// 及其定义
  |
  |-- gps_accum_task.c				// GPS L1信号捕获和跟踪gps_track_channels(…)
  |-- gps_accum_task.h				// 及其定义
  |-- b1i_accum_task.c				// BDS B1I信号捕获和跟踪b1i_track_channels(…)
  |-- b1i_accum_task.h				// 及其定义
  |
  |-- main_allocate.c				// 通道分配任务allocate_task(…)
  |-- main_allocate.h				// 及其定义
  |
  |-- main_message.c				// 电文处理任务message_task(…)
  |-- main_message.h				// 及其定义
    |-- gps_message.c				// GPS L1电文处理入口gps_process_message (…)
    |-- gps_message.h				// 及其定义
    |-- b1i_message.c				// BDS B1I电文处理入口b1i _process_message (…)
    |-- b1i_message.h				// 及其定义
    |-- main_ephemeris.c			// 星历处理任务ephemeris_task(…)
    |-- main_ephemeris.h			// 及其定义
      |-- gps_ephemeris.c			// GPS L1星历处理入口gps_ephemeris_task (…)
      |-- gps_ephemeris.h			// 及其定义
      |-- gps_almanac.c				// GPS L1历书处理
      |-- gps_almanac.h				// 及其定义
      |-- b1i_ephemeris.c			// BDS B1I星历处理入口b1i _ephemeris_task(…)
      |-- b1i_ephemeris.h			// 及其定义
      |-- b1i_almanac.c				// BDS B1I历书处理
      |-- b1i_almanac.h				// 及其定义
  |
  |-- main_measure.c				// 观测量读取任务meas_task(…)
  |-- main_measure.h				// 及其定义
    |-- main_pseudorange.c			// 伪距计算函数calculate_pseudorange(…)
    |-- main_pseudorange.h			// 及其定义
      |-- main_position.c			// 定位计算任务position_task(…)
      |-- main_position.h			// 及其定义
        |-- gps_position.c			// GPS L1定位计算函数
        |-- gps_position.h			// 及其定义
        |-- b1i_position.c			// BDS B1I定位计算函数
        |-- b1i_position.h			// 及其定义
        |-- calculate_position_4.c	// 单系统定位解算函数
        |-- calculate_position_4.h	// 及其定义
        |-- calculate_position_5.c	// 双系统定位解算函数
        |-- calculate_position_5.h	// 及其定义

4.2.3 主程序

地图导航应用 系统架构_c语言HD-GR导航软件的主程序(参见agrs_gp_1_ucos.c)简单明了:

  • 首先初始化包括GNSS基带模块在内的外围设备;
  • 然后初始化导航软件内部参数和结构;
  • 接着创建导航软件工作所需的μC/OS-II任务;
  • 之后注册累积中断处理例程(accum_int_handler);
  • 最后调用内核函数OSStart()启动所有μC/OS-II任务。

这时,所有任务处于挂起状态(信号量等待状态)。之后的任务唤醒(可归结为)由累积中断(GNSS_BDMOD_IRQ)触发。

4.2.4 累积中断处理例程

地图导航应用 系统架构_c语言每当GNSS基带模块发出一个GNSS_BDMOD_IRQ中断,累积中断处理例程accum_int_handler首先读取基带模块当前状态并保存到m_status,随即发出一个唤醒相关数据累积任务(accum_task)的信号(m_SemISR)。GNSS_BDMOD_IRQ中断间隔为0.5 ms到1 ms之间,缺省为0.8 ms。

4.2.5 相关数据累积任务

地图导航应用 系统架构_c语言相关数据累积任务的入口函数为accum_task(…),位于文件main_accum_task.c中。在从唤醒到挂起的一个循环中,任务accum_task相继执行以下处理:

  • 从基带模块读取NEW_DATA寄存器,它指示了哪些通道具有有效的新相关数据;
  • 如果m_status包含TIC标志,更新接收机时钟,以位(bit)为单位保存各通道时间;
  • 读取和累积通道的新相关数据,参见gps_accum_task.c中的函数gps_accum_newdata(…)和b1i_accum_task.c中的函数b1i_accum_newdata(…);
  • 捕获和跟踪通道信号(基带环路控制),参见gps_accum_task.c中的入口函数gps_track_channels(…)和b1i_accum_task.c中的入口函数b1i_track_channels(…);
  • 如果有任何关闭的通道,向通道分配任务(allocate_task)发出信号(m_AllocateFlag),唤醒它分配新通道;
  • 如果有任何通道存在等待处理的数据位,向电文处理任务(message_task)发出信号(m_MessageFlag),唤醒它解码导航电文;
  • 如果m_status包含TIC标志,向观测量读取任务(meas_task)发出信号(m_SemMeas),唤醒它读取通道观测量。

4.2.6 通道分配任务

地图导航应用 系统架构_c语言通道分配任务的入口函数为allocate_task(…),位于文件main_allocate.c中。任务allocate_task从唤醒到挂起的一个循环相继执行以下处理:

  • 获得当前时间(now);
  • 检查每个通道:
  • 如果通道状态为锁定且接收机时钟已进行了秒设置,更新锁定时间(now);
  • 如果通道状态为关闭,以冷启动方式分配通道。如果成功分配了卫星,初始化通道参数,通道设置为信号捕获状态状态;
  • 保持其它通道为当前状态。

4.2.7 电文处理任务

地图导航应用 系统架构_c语言电文处理任务的入口函数为message_task,位于文件main_message.c中。任务message_task在从唤醒到挂起的一个循环中,对GPS L1和BDS B1I信号通道分别调用位于gps_message.c中的函数gps_process_message(…)和位于b1i_message.c中的函数b1i_ process_message(…)进行处理。如果任何通道保存了一个完整子帧的数据,就向星历处理任务(ephemeris_task)发出信号(m_EphemerisChannelFlag),唤醒它将子帧数据转换为星历。

4.2.8 星历处理任务

地图导航应用 系统架构_c语言星历处理任务的入口函数为ephemeris_task,位于文件main_ephemeris.c中。任务ephemeris_task在从唤醒到挂起的一个循环中,对GPS L1和BDS B1I信号通道分别调用位于gps_ephemeris.c中的函数gps_ephemeris_task(…)和位于b1i_ephemeris.c中的函数b1i_ephemeris_task(…)进行处理,将任一通道有待处理的子帧数据转换为星历。如果对于一个通道,转换完了它的所有子帧,则进一步将结果保存到它的星历表中。

4.2.9 观测量读取任务

地图导航应用 系统架构_c语言观测量读取任务的入口函数为meas_task,位于文件main_measure.c中,它在相关数据累积任务(accum_task)检测到一个TIC信号时被唤醒。任务meas_task在从唤醒到挂起的一个循环中,只在正确设置了接收机时钟的周数(week number)之后,才相继执行以下处理:

  • 获取当前GPS/BDS时间,以标识观测量时间;
  • 读取当前TIC计数值;
  • 如果需要抓取当前TIC时刻的观测数据,当一个通道满足以下条件时,读取和合成它们:
  • 处于信号锁定状态;
  • 信号质量良好(大于锁定阈值);
  • 历元计数器(epoch counter)已经设置。
  • 如果抓取了任何通道观测数据,计算它们的伪距;
  • 如果计算了任何通道的伪距,发出信号(m_SemPosi)唤醒定位计算任务(position_task)。注意,任务position_task需要花费较长时间进行处理。由于希望在position_task运行期间继续生成伪距,所以产生了一个伪距副本(g_ppr_cur)供它使用。
  • 调用函数set_pps_org(…)进行1PPS时标处理。

4.2.10 定位计算任务

地图导航应用 系统架构_c语言定位计算任务的入口函数为position_task,位于文件main_position.c中。任务position_task从唤醒到挂起的一个循环相继执行以下处理:

  • 计算所有可用于定位解算的卫星的ECEF坐标;
  • 计算卫星信号的对流层校正值并进行伪距校正;
  • 如果可用卫星为4颗或更多,计算接收机PVT值:
  • 当可用卫星对应双系统情况,应用双系统定位算法;
  • 当可用卫星对应单系统情况,应用单系统定位算法;
  • 如果定位解算成功:
  • 将接收机ECEF坐标转换为LLH坐标;
  • 根据接收机LLH坐标,计算接收机NEU坐标;
  • 计算定位解算的DOP值;
  • 保存本地时钟偏差值和校正接收机时钟;
  • 显示定位解算结果;
  • 将定位解算状态和本地时钟偏差值传递给观测量读取任务。