基于ZYNQ 的多轴运动控制平台关键技术研发-Linux+xenomai开源实时系统设计(二)
机制时,进程(或线程)会获取一个非负整数的信号量,表示共享资源的访问状态。的正确解析,双核系统需要对数据帧进行统一设置。齐方式,方便双核系统进行数据帧的保存和解析。的一种系统调用,其功能是将一个文件或者其他对象映射到进程的地址空间。任务将通信数据打包处理后发送给邮箱,邮箱接收到数据邮件后,根据邮箱状态将邮。本文设计了二进制的核间信号量,并根据双核间任务通信时序,对核间信号量的。固定长度邮箱通信中,
·
4. SoC
双核系统与核间多任务通信设计
本章详细介绍
AMP
架构下
SoC
核系统的设计和核间任务通信的实现方法。首
先,进行双核系统的搭建并完成设备驱动的移植;然后,进行基于共享内存的通信模
块设计;最后,针对系统不同通信任务的要求,提出多任务通信的实现方案。
4.1
双核系统设计与实现
4.1.1 Linux
实时系统搭建
(
1
)
Xenomai
实时补丁安装
机器人控制系统需要具有强实时性能力,在运行时必须保证运动控制相关的任
务调度和数据通信的实时处理和响应。
Linux
系统因支持内核抢占、中断屏蔽和优先
级抢占调度等机制,无法提供严格的强实时性能。
Linux
系统的实时性优化有两种方
法,分别为
Linux
内核源码改进和
Linux
双内核扩展。其中,内核改进法方便用户进
行指定方向的性能优化,但存在工作量大,改造难度高等问题。
因此,本文通过
Xenomai
对
Linux
系统进行拓展,实现双内核实时系统,即满足
系统使用要求,同时提高了开发效率。
Xenomai
采用
Adeos(Adaptive Domain
Environment for Operating System)
技术保证硬实时的拓展,双内核架构如图
4.1
所示。
在采用
Adeos
的双核架构中,
Adeos
主要完成域的调度、中断和域的管理等工
作。在
Adeos
架构中设置了域的优先级,
Xenomai
域要高于普通的
Linux
域。因此,
当系统接收到中断信号时,
Adeos
将中断分配给
Xenomai
进行处理;只有当
Xenomai
域的任务执行完成后,
Linux
域中的任务才会继续执行。通过上述调度方法,
Adeos
保证了
Xenomai
域的优先级,从而保证了任务的实时处理。如图
4.2
所示,本文使用
Linux 4.9.0
版本内核和
Xenoma 3.0.7
实现实时系统的搭建。
为了保证
Xenomai
正确使用,表
4.1
中列出内核配置中重要的
Xenomai
部分功
能项。其中,内核需要开启
Xenomai
相关的服务项,同时关掉与实时性功能相冲突
的内核选型,保证系统的正常运行。
在
Linux+Xenomai
系统搭建完成后,验证
Xenoma
是否安装成功。在
Linux
启动
完成后,通过
dmesg |grep I-pipe
和
dmesg |grep Xenomai
命令查看安装状态。如图
4.3
所示,系统完成
Xenomai
实时补丁的安装。
(2)
Linux
设备驱动移植
基于
SoC
关键通信接口设计,在
Linux
系统下完成对外设驱动的移植,保证系
统设备的正确使用,实现平台对外通信。如图
4.4
所示,
Linux 4.9.0
内核使用总线架
构的设备模型。
在总线架构的设备模型中,系统的设备和驱动是分离的,使用总线机制对二者进
行匹配。总线设备模型为系统的驱动移植提供了一致性接口,简化了移植流程,提高
了开发效率。
进行
SoC
平台通信接口设备的驱动移植,具体分为两种方法:
(
1
)当内核提供该设备驱动时,直接使用内核中的驱动。
(2)对于内核中不提供驱动的设备,为其设计驱动程序并进行移植。
首先,通过查看内核
config
配置文件,
Linux-4.9.0
内核提供千兆以太网、
USB
HUB
和
UART
的设备驱动支持。因此采用方法(
1
)进行驱动移植,具体如下:使
用
make menuconfig
命令开启内核配置;将设备驱动配置为静态加载,实现系统启
动时驱动自加载功能;使用
arm-linux-gcc
完成
zImage
的编译生成。如图
4.5
所
示,在使用
zImage
完成系统启动后,通过
dmesg
命令查看内核日志,千兆以太
网、
USB HUB
和
UART
的驱动程序已完成注册,设备可以正常使用。
Linux-4.9.0
内核中不提供
AX88772B
网卡芯片的驱动程序,
USB
扩展的百兆以
太网接口无法直接使用,因此采用方法(
2
)进行
AX88772B
网卡驱动程序的移植。
出于减小开发难度和节约开发时间的目的,本文使用
AX88772B
官方驱动源码,
并在其基础上根据平台功能需求进行相应设计。通过分析,
AX88772B
在使用中,通
过外部存储器保存用户写入的
PHY
芯片
MAC
(
Media Access Control Address
)地址,
进而完成驱动程序注册。为了满足系统快捷化和多样化的配置需求,本文提出一种基
于
AX88772B
芯片的
MAC
地址动态设置方法。具体方法为:将用户自定义
MAC
地
址预先存储在
Flash
设备中;驱动程序在注册中,如果未检测到外部存储器,则从
Flash
中读取用户
MAC
地址,完成注册。如图
4.6
所示,完成
AX88772B
驱动程序
的修改,并在
Linux
环境下生成内核驱动模块,方便用户根据使用情况进行动态加
载。
如图
4.7
所示,系统加载
asix.ko
内核模块,驱动在注册过程中通过
flash
为两个
AX88772B
网卡分配
MAC
地址,网卡驱动移植成功。
4.1.2
伺服裸机系统构建
在
CPU1
上搭载伺服裸机系统需要完成以下三部分工作:
Linux
系统在运行时将
CPU
使用数量设置为
1
;
CPU0
完成
CPU1
伺服应用程序的加载;
CPU0
完成
CPU1
的唤醒。
Linux
系统在启动阶段,默认使用
SMP
对称处理模式,同时对两个
CPU
进行管
理,协调
CPU
之间的相关工作。因此,在使用
AMP
架构时,需要限制
Linux
系统
只占用
CPU0
,
CPU1
预留用于伺服裸机系统。
Linux
启动过程中,内核文件根据环
境变量
bootargs
对系统进行相应配置,用户可以通过修改变量
bootargs
实现
CPU
使
用数量的指定。变量
bootargs
的生成分为直接指定法和
Bootloader
生成法两种方式。
其中,直接指定法是在内核配置过程中设置
bootargs
,这种方法保证
bootargs
在重新
配置前的唯一性和有效性;
Bootloader
生成法是在
Bootloader
文件中设置
bootargs
,
并在
Bootloader
执行完毕后将其传递给内核。这种方法提供了用户修改
bootargs
的
可能性和快捷性,有利于软件的开发和维护。本文采用
Bootloader
生成法。在
Bootloader
启动过程中对
bootargs
进行动态配置和保存,将
Linux
系统使用的
CPU
数量设置为
1
,从而保证
CPU1
的空闲状态。环境变量
bootargs
值配置如表
4.2
所示。
在保证
CPU1
处于空闲状态后,
CPU0
需要完成伺服应用程序
CPU1_APP
的加
载。
CPU1_APP
的加载工作是将应用程序写入用户指定的内存空间中。
Xilinx
为
SoC
加载裸机程序提供了两种实现方法:第一种是使用
Jtag
烧写器将
CPU1_APP 写入内
存。此方法需要使用到外部烧写器,而且只能实现程序的单次加载,因此适用于系统
开发和调试阶段。第二种方法是使用
Xilinx SDK
工具将
CPU1_APP
集成到
Bootloader
中形成
BOOT.bin
文件;系统启动时执行
BOOT.bin
文件,自动寻找
CPU1_APP
并将
其加载到指定内存中。第二种方法不需要烧写器,加载操作方便;但是,多文件集成
的加载方式破坏了伺服应用程序的独立性,不利于后续软件的单独更新。
本文提出一种基于
Bootcmd
环境变量的应用程序加载方法。
Bootcmd
是
Bootloader
的一种环境变量,保存了
Bootloader
在启动后执行的指令操作。通过在
Bootloader
启动阶段,对
Bootcmd
进行动态设置,添加加载
CPU1_APP
程序的指令
操作并保存。如图
4.8
所示,平台在复位操作后,
Bootloader
会执行
Bootcmd
中的命
令,将
CPU1_APP
加载到指定内存中。本方法同样适用于
FPGA
烧写文件的动态加
载,有效保证了用户文件的独立性。
Zynq 7020 SoC
在
AMP
架构下,
CPU1
在
SoC
上电后首先执行芯片固件程序进
入休眠状态。此时,必须通过
CPU0
才能将
CPU1
唤醒。基于
Xilinx
提供的
CPU1
唤
醒方法, 在进行
CPU1
伺服软件的重运行操作时,需要将双系统进行复位,不满足
运动控制系统的使用要求。
因此,本文提出一种针对
SoC AMP
架构下的
CPU1
可单独重运行的方法。方法
的实现流程如下:(
1
)系统启动阶段,
CPU0
完成
CPU1_APP
的加载;
(2)系统启动 完成后,CPU0
将一段可实现
CPU1
程序跳转的指令写入地址
0x0
的内存中;
(3) CPU0 中执行
CPU1
的复位操作;
(4)
CPU1
重启后,执行地址
0x0 处的跳转指令,
跳转到
CPU1_APP
加载地址
(5)
CPU1
执行
CPU1_APP
,伺服系统重运行完成。
基于图
4.9
所示方法,完成
CPU1
程序的加载和运行,实现伺服系统的搭建。
4.2
核间通信模块设计
基于双核间多任务通信需求,本文采用共享内存
OCM
作为通信媒介,并进行如
下通信模块设计:共享内存的管理方法、核间信号量设计和消息邮箱设计。
4.2.1
共享内存的管理方法
共享内存是双核间任务通信的物理介质,用于保存通信数据。本文采用
SoC
芯
片内部的
256K
片上内存作为共享内存,其在
4G
寻址空间的地址范围为
0xFFFC0000~0xFFFFFFFF
。片上共享内存
OCM
在
SoC
芯片启动过程中,会被用于
系统启动文件的加载和运行;系统启动完成后,
OCM
内部数据并不为空。因此,在
使用
OCM
进行任务通信时,为了保证
OCM
中数据的安全性和一致性,需要进行如
下操作:
(
1
)机器人控制程序开始运行时,
Linux
系统完成
OCM
访问申请并对
OCM
进
行初始化;
(
2
)每次完成伺服系统重运行后,
Linux
系统需要对
OCM
进行初始化;
(
3
)机器人控制程序运行结束时,
Linux
系统关闭内存映射,释放共享内存。
针对以上操作,设计并实现了用于
Linux
系统访问
OCM
的三个接口函数,分别
为:
System_Ocm_Req()
、
System_Ocm_Init()
和
System_Ocm_Free()
,函数功能依次为
OCM
申请、
OCM
初始化和
OCM
释放。
在
Linux
系统中,用户进程无法同裸机程序一样直接对物理内存进行访问。为了
保证用户进程对共享内存的快速访问,
System_Ocm_Req()
函数通过内存映射方法
(
Memory Map
,简称
MMAP
),完成共享内存的申请操作。
MMAP
是
Linux
系统下
的一种系统调用,其功能是将一个文件或者其他对象映射到进程的地址空间。如图
4.10
所示,
System_Ocm_Req()
中使用
MMAP
完成
256KB
大小的
OCM
物理内存空
间的访问申请。申请成功后,
System_Ocm_Req()
函数返回一个基地址指针,用户进
程通过指针方式对
OCM
进行读写操作。
System_Ocm_Init()
函数主要完成对
OCM
的状态检查,读写校验和擦除。状态检
查中,
Linux
访问
OCM
状态寄存器并判断
OCM
是否存在通信错误,如果存在错误
则对其进行复位操作;如果状态正常,则进行读写校验。读写校验中,通过向
OCM
写入用户测试数据,写入完成后将
OCM
中数据读出,比较写读前后数据的一致性。
如果读写校验成功,对
OCM
进行擦除操作,保证双核系统通信的安全性;否则,表
明
OCM
校验失败,
Linux
系统进行相应的出错处理。
在机器人控制软件运行结束时,为了保证系统的安全性,需要关闭
OCM
在进程
空间中的映射,此时通过
System_Ocm_ Free ()
函数实现。
System_Ocm_ Free ()
中通过
使用
munmap()
系统调用,实现映射关系的解除,完成
OCM
的释放。如图
4.11
所示,
Linux
在任务执行阶段,对
OCM
的进行有序访问。
4.2.2
核间信号量设计
为了保证双核对
OCM
数据访问的互斥性和一致性,引入信号量设计思想,并根
据双核间任务通信的使用要求完成核间信号量的设计。信号量是一种用于多进程(或
线程)情况下,避免共享资源被不同对象同时访问的保护机制
[44]
。采用信号量同步
机制时,进程(或线程)会获取一个非负整数的信号量,表示共享资源的访问状态。
信号量非零时,表示有空闲共享资源,允许进程(或线程)访问;信号量为零时,表
示共享资源为空,此时进程(或线程)将处于等待状态。如果共享资源数量大于
1
,
称为计数信号量(
Counting semaphore
);如果共享资源数量为
1
,信号量只有
0
或
1
两种状态,称为二进制信号量(
binary semaphore
)。
本文设计了二进制的核间信号量,并根据双核间任务通信时序,对核间信号量的
访问进行约束。核间信号量表示
OCM
数据区的访问状态,具体定义如表
4.3
所示。
其中,核间信号量为
1
时,表示
OCM
数据区处于空闲,可以发起任务通信;核间信
号量为
0
时,表示
OCM
数据处于忙状态,任务通信正在进行。如果信号量出现为其
他状态,表明双核系统在任务通信过程中发生通信错误。
在双核间任务通信开始前,
Linux
系统对信号量进行初始化,将其设置为
1
。在
双核间任务通信阶段,对信号量进行以下操作:
(
1
)双核系统对信号量均有可读
/
可写权限,若读写操作同时发生时,读操作优
先权高于写操作优先权。
(2)双核系统任务通信阶段,进行“
CPU0
读
-CPU0
修改
-CPU1
读
-CPU1
修改”
顺序的信号量访问。
其中,(
1
)保证了在任务通信过程中,双核系统可以根据通信状态对信号量进行
设置;在访问优先级设置上,读操作高于写操作,当双核系统同时对信号量进行读写
操作时,保证信号量先被读取,避免通信状态的丢失。(
2
)设置了通信过程中双核系
统对信号量的访问顺序。在双核间任务通信时,通信由
Linux
系统先发起,此时系统
读取信号量并判断其状态,当信号量为
1
时开始访问
OCM
;当信号量为
0
时,表示
任务通信已处于进行状态。图
4.12
表示双核系统任务通信阶段的信号量状态切换。
在
linux
系统完成
OCM
访问后,将信号量设置为
0
。伺服系统持续读取信号量,当
信号量为
1
时,表示未发生通信;当信号量为
0
时,表示通信正在进行,伺服系统开
始访问
OCM
。当伺服系统完成
OCM
访问后,将信号量重新设置为
1
,表示
OCM
处
于空闲状态。
4.2.3
数据消息邮箱设计
双核系统任务通信阶段,需要支持多种类型数据通信,因此采用消息邮箱实现数
据传输。消息邮箱是一种任务间的数据通信方法,设计简单且系统开销少
[45]
。系统
任务将通信数据打包处理后发送给邮箱,邮箱接收到数据邮件后,根据邮箱状态将邮
件转发至其他任务。针对多轴运动控制的使用要求和邮箱通信的特点,本文设计两种
邮箱通信方式,分别为固定长度邮箱通信和可变长度邮箱通信。
固定长度邮箱通信中,邮件数据长度固定,系统可根据通信数据的使用要求设置
为
8/16/32/64
位。采用固定长度邮箱进行任务通信时,在双核系统初始化阶段,需要
对邮箱地址进行设置,保证双核系统对同一邮箱的访问。
可变长度邮箱通信时,邮件内容为通信数据帧,数据帧长度不定。为了保证邮件
的正确解析,双核系统需要对数据帧进行统一设置。因此,设计一种支持读写命令和
可变数据长度的数据帧格式,帧结构如表
4.4
所示。邮件数据帧的数据采用
32
位对
齐方式,方便双核系统进行数据帧的保存和解析。同时,在双核系统初始化阶段,需
要对邮箱地址进行设置,保证双核系统对同一邮箱的访问。
为固定长度和可变长度两种邮箱通信方式设计不同的接口函数,分别为
DRV_Control()
和
DRV_ASYControl()
,函数的具体功能定义如表
4.5
和表
4.6
所示。
信迈提供ZYNQ+LINUX+Xenomai+运动控制系统实时系统移植方案。
更多推荐
已为社区贡献4条内容
所有评论(0)