前言
1553总线是一种指令/响应式串行总线标准,除了作为美军标在国外广泛应用于军用飞机坦克、船舶、卫星、导弹等领域,在国内已得到了广泛的应用。抗干扰能力强实时性好,且拥有着双冗余备份设计,数据传输极为可靠。就我个人认知来看,常见的实现形式一种是通过专用的接口协议芯片,相对比较简单集成度高;另一种是IP核,非常考验逻辑和软件设计的功底。此次工程选用了前者,LHB15530接口芯片,在不改变原有传输方式的前提下,突破了原有的1Mb/s的传输速率,可达4Mb/s,也能满足绝大部分应用场景。
一.工作原理
LHB155304 是国内某研究所研发的国产接口芯片,采用了和DDC 公司的 BU‐61580 全兼容的软件界面。相对于 BU‐61580而言,LHB155304 提供了更加灵活高效的主机接口方式,增大了内部存储器空间,不仅可以实现BU‐61580 支持的接口方式,还具有主机访问等待时间更短的特点。
LHB155304 由时钟与复位管理单元、双曼彻斯特 II 型编译码器单元、 BC/RT/MT 多协议处理单元、存储管理单元、中断管理单元、主机接口单元、 16K× 16bit 的双端口存储器单元组成。支持 16 位接口方式,可以和主机以共享存储器的方式协同工作。总线上的信息是以消息的形式调制成曼彻斯特码进行传输的,最长由32个字组成,所有的字分成三类:命令字数据字和状态字(详细参见1553B常识篇,一定要在熟悉了常识后再阅读下面的配置部分)
二.硬件和逻辑
这部分设计只能交给万能的硬件工程师和逻辑工程师来处理,还是跳过来说软件部分吧,就不拿一知半解的一丢丢误人子弟了
三.软件设计
配置17个内部操作寄存器和共享内存是软件接口设计的关键,对于RT的设计,由于1553B传输的特殊性,每个消息都必须由BC主动参与,所以大部分的预设处理等内容都集中在BC部分,RT仅仅需要做好初始化操作和收到BC指令字后作出不同的处理即可完成(是的没有看错,只有这些,仅剩的难点也仅限于寄存器和模式的配置选择了,需要熟读理解后面讲的各种模式啊什么的选择),其实相对简单的
3.1寄存器
首先来说寄存器部分,一共需要配置的17个寄存器,内部映射和定义如下表所示
其简要的功能描述如下表所示
具体每个寄存器初始化的配置见代码和注释部分,这里先概括下一般流程和某些寄存器配置需要注意的地方:
1.LHB155304 共有七种不同的工作模式,各个工作模式的配置方式如下表 所示:
注意:
1.模式选择
( 1)软件或者硬件复位后,初始化为空闲 BC 模式。
( 2) RT 或 RT/MMT 组合模式只能通过软件或硬件复位退出该模式运行。
bit13:当前区域 B/A*
该位用来选择当前工作区域。如果在BC帧处理、RT消息MMT消息处理过程中改变该位的值,那么主机访问该位时得到的依然是改变之前的值,直到BC当前帧、RT当前消息、MMT当前消息处理结束。对于WMT 模式,改变该位不产生任何影响。(所以呢,在后面的软件部分,出于之前经验结构体里是有AB区域的判别的,但后来发现没起到作用,方才注意到)
2.BIT
此处BIT是build in test的缩写,设计测试中,如果回写测试失败的话,表示收发通路存在问题,包括发送通道,接收通道,隔离变压器,一定要注意此处的不通只会有三种情况,一是压根没发出去,二是发出去了,但是接口芯片没有处理好,三是发出去了也处理好了,但是隔离变压器存在硬件连接错误导致判定为回写测试失败,一旦回写测试失败,是不能发给bc状态字用以判定的
怎么判定呢,软件部分可以做的是,读取块状态字,指令字和接收的BC的数据字这些,可以读到RT是否收到了BC的指令,如果正确,那么肯定是发出去了(总线协议就是如此,眼神坚定一点,做到这一步就和软件设计没啥关系了放弃这边的排查),情况1排除;情况2呢就是接口协议芯片厂家的问题了,不过出故障的概率也很小;极大的可能会是情况3,这就只能交给万能的硬件工程师来解决了(比如1553的地需要和gnd共一起之类的)。
3.2存储组织
LHB155304 向主机提供了 16K× 22bit 的 RAM 用以存放消息的数据及 RT 的控制和管理信息。在 RT 模式下,内部共享 RAM 存储器中存储空间的典型分配如下表所示:
RT 在宏观上将 16K 的共享 RAM 分为 A、 B 两个区域,实现全局双缓冲机制。用户可以通过配置寄存器#1 的 bit13 指定两个区域之一为“活跃”区(工作区),则另一个为“非活跃”区(非工作区)。两个区域各包含一个堆栈指针( A 区和 B 区分别占用 0100H 和 0104H 单元)、一个若干大小的堆栈区(可以是满足大小要求的存储映射表内任何非固定单元的连续区域)、一个查询表( A 区和 B 区分别占用起始地址是 0140H和 01C0H 的 128 个连续单元)和一系列数据块。表中,标记“固定”的单元具有特定的含义,不能作为数据块等其它用途。而堆栈和数据块可以被分配到共享 RAM 中任意非固定区域。对特定用途固定单元的含义及作用解释如下
3.2.1堆栈指针
A 区和 B 区的堆栈指针( 0100H 和 0104H 单元)会被初始化为堆栈区的起始地址,并随着RT 接收消息而改变。每条消息在接收到指令字后将会加4并以堆栈区的大小模除。如堆栈大小是 256 的情况下,当前值为 252 时消息结束后将变为‘ 0’。堆栈的起始地址必须要能被 4 整除。例如,将堆栈指针初始化为 0003H 是错误的,而初始化为 0000H 及 0004H 则是合法的。
3.2.2堆栈
这里的堆栈是特指的接口芯片物理存储部分划分的堆栈,也称为描述符堆栈或者指令堆栈。当前消息在描述符堆栈中占用四个连续的字单元作为该条消息的描述信息。这四个单元提供了消息的四项信息:块状态字(Block Status Word)、时间标志字(Time Tag Word)、数据块指针(Data Block Pointer)以及接收指令字(Received Command Word)。堆栈区的大小可以通过配置寄存器#3 的bit14、 bit13 编程指定,配置寄存器#3 中 bit14 和 bit13 的取值与指令栈大小的对应关系如下(为了描述方便,这里以消息数计算,实际大小应该是消息数乘以 4,即每条消息在描述堆栈中占用 4 个字单元):
00: 64 条消息(缺省值);
01: 128 条消息;
10: 256 条消息;
11: 512 条消息;
块状态字
块状态字存储在描述符堆栈的最低位字单元,各位的详细定义及解释参考芯片手册吧
时间标志字
在消息开始或者结束时用于存放时间标志寄存器的当前内容。时间标志寄存器可由配置寄存器#2 的 bit9‐bit7 选择设定分辨率为 0.5μs/LSB、 1μs/LSB、 2μs/LSB、 4μs/LSB、8μs/LSB 或 16μs/LSB。
数据块指针或方式指令数据字
描述符堆栈的第三项用于两个不同的目的。对于非方式指令或者方式指令(方式指令在非增强方式处理模式下处理),从查询表中读得的值被存储在这个单元,这个值是该消息数据块的起始地址。对于方式指令消息且增强方式指令处理使能,在 RT 消息结束序列中,将带数据字方式指令接收或发送的数据字写入该项。对于不带数据字的方式指令,此项中不写任何信息。
3.2.3查询表
RT 为 A 区和 B 区各指定一个 RT 查询表,查询表包含接收数据块指针、发送数据块指针、广播数据块指针和子地址控制字四个部分。 RT 查询表是子地址数据块指针与控制字的查询表。 RT 查询表的数据块指针单元在 RT 单消息存储管理模式下始终保持用户配置的初值不变,直到主机将其更新;在双缓冲存储管理模式下,交替工作的两个数据块的地址指针的 bit5 的值相反,其余位相同。因此,每条消息处理结束后,子地址的数据块地址指针将自动更新,在×…×1×××××和×…×0×××××之间切换。循环缓冲存储管理模式下,每条消息处理结束后相应的子地址的数据指针会更新为缓冲的下一单元。
子地址 0 到子地址 31 对应存储区域的起始地址都可以从表中查出。比如,对于子地址 1,接收指令的数据块起始地址由 0141H 单元指定,而发送指令的数据字则来源于0161H 单元指向的数据块;对于子地址 2,接收指令的数据块起始地址在 0142H 单元指定,而发送指令的数据字来源于 0162H 单元所指向的数据块……等等。在非增强方式指令处理模式下,子地址为‘ 0’(或者 31)的方式指令在指令字 T/R*=‘ 0’时数据字的地址在 0140H(或者 015FH)单元,在指令字 T/R*=‘ 1’时数据字地址由 0160H(或者 017FH)单元指定。广播子地址对应的指针查询表为可选项,广播消息的数据可以存放在接收子地址的数据区。在分离广播数据( CFG#2.0=‘ 1’)的配置下, RT 才需要查询广播消息的数据块指针来确定广播数据的存储区域。查询表中的 RT 子地址控制字,在 RT 增强存储管理模式下使用。可见,每个子地址控制字单元包含了对应子地址 0‐31 的存储管理控制信息 “ MM2‐MM0”、 消息结束中断控制信息和循环缓冲中断控制信息。 依照消息格式的不同,控制字对该子地址的控制分为发送消息( Tx)控制、接收消息( Rx) 控制和广播消息( BCST)控制。控制字的最高位是“子地址全局性双缓冲使能”,它从总体上控制是否对所有的接收子地址都使用双缓冲存储管理机制。
注意:
对于方式指令消息,只有在非增强方式指令处理(非增强模式下或者 CFG#3.0=‘ 0’)的条件下,子地址控制字才有效。
3.2.4 方式指令中断选择表
RT 的方式指令表达了 BC 对 RT 的指令传输要求,分为带数据的方式指令和不带数据的方式指令。由于方式指令在 1553B 总线协议的控制和管理方面的特殊性和重要性,LHB155304 针对 RT 方式指令消息向主机提供了灵活的中断机制。这种机制将共享存储器RAM 从 0108H 到 010FH 的 8 个字单元作为方式指令的中断选择表。通过该选择表用户可以方便的选择需要通过主机中断服务处理的方式指令消息。方式指令与中断选择表字位的对应关系详见 6.4 增强方式指令处理部分说明和表 6‐12 所示。
3.2.5 方式指令数据区
增强方式指令处理模式下, RT 为方式指令提供了固定的数据访问单元。方式指令与具体字单元的对应关系见 增强方式指令处理部分说明和相应表格所示。
3.2.6 子地址忙配置位表
为了实现协议中状态字的忙位, RT 在存储空间中占用 8 个字单元,向用户提供了指定消息类型的子地址忙的选择机制。消息类型基于广播地址或专有地址/发送或接收。每种类型占用 32 位,按低位字的最低位与子地址 0 对应,高位字的最高位与子地址 31 对应顺序分配。
3.2.7 指令非法表
在实际应用中,各个 RT 及子系统并非使用所有的消息传输格式, LHB155304 利用256 字的 RAM 空间在 RT 模式下向用户提供了使指令字非法化的机制,其好处之一是不必使用外部 PROM(或者 PLD、 RAM)器件实现指令字非法化的功能,从而减少了印制电路板的尺寸。该机制的另一优点是使用 RAM 的非法化技术提供了自测试能力。这一非法化机制具有很大的灵活性,允许广播地址或专有地址/发送或接收/数据字个数或方式指令码的 4096 种可能组合的任意子集非法。指令非法表的任一单元的任一位置‘ 1’时,与之相对应的指令就被指定为非法;指令非法表的任一单元的任一位为‘ 0’时,表示与之相对应的指令为合法。
RT 加电时默认指令非法化使能。通过配置 CFG#3.15=‘ 1’且 CFG#3.7=‘1’ ,可以禁止非法化指令。指令的非法会造成以下影响:
( 1) RT 若判断出某种非广播消息被设置为非法,会将 RT 状态字中的消息错误位置1。如果某个发送指令被设置为非法, RT 将响应一个(消息错误位置1的)状态字而不发送任何数据字。
( 2)如果某个接收指令被设置为非法并且 RT 处于非增强模式下(或配置寄存器#3.4=0),包含该接收指令的 BC‐RT 消息或者 RT‐RT 消息传输的数据字将被存储在共享RAM 中。 RT 在增强模式下且禁止非法接收(配置寄存器#3.4=1)时,非法指令的数据字将不存储在 RAM 中。
( 3)如果某个广播指令设置为非法, RT 将不响应该广播消息,同时将 RT 状态寄存器中的“消息错误”及“广播指令接收”置1 。如果下一条消息是“发送状态字”或 “发送上一指令字”的方式指令, RT 将响应一个(“消息错误”置1的)状态字。对广播接收指令,数据字的存储也由“非法接收禁止”控制,如前所述。
( 4)当 RT 接收到非法指令时, RT块状态字的 bit6“非法指令字”将置1。
3.3 RT存储管理
LHB155304 将共享 RAM 分为“活跃”区(工作区)与“非活跃”区(非工作区)两个部分。任一时刻只有一个堆栈指针、一个堆栈区、一个查询表、一系列数据块被指定为“活跃”,而另一组数据结构被指定为“非活跃”。主机处理器可随时访问“活跃”区与“非活跃”区两个存储区域。在 RT 模式下, LHB155304 提供了单消息存储管理、循环缓冲存储管理以及双缓冲存储管理三种存储管理模式供用户选择。存储管理基于子地址和消息类型由 RT 子地址控制字配置。
对每个发送子地址,有两种存储管理机制可供选择:
—单消息存储管理机制;
—循环缓冲存储管理机制。
对于每个接收子地址及广播子地址,可以选择三种存储管理机制,即:
— 单消息存储管理机制;
— 循环缓冲存储管理机制;
— 双缓冲存储管理机制。
存储管理的占用空间是以子地址数据块的大小及组织来划分的:单消息的数据块占用连续的 32 个字单元;双缓冲占用两个分别连续的数据块,每个数据块占用 32 个字单元, RT 每处理一条消息就在这两个数据块间切换一次;循环缓冲的每个子地址占用指定大小的一个数据区,数据区的存储空间最小为 128 字,最大为 8192 字。
单消息存储管理机制是 LHB155304 默认的存储管理模式,使用时在每条消息结束后主机必须及时读取该消息数据或填写下一消息的发送数据。
对于给定的子地址,通过使用双缓冲机制,主机可以方便地访问刚刚接收的有效数据块。主机处理器可以在 LHB155304 访问一个消息块进行消息处理的同时访问另一个数据块,保证了各块数据的完整性和一致性。
循环缓冲不仅保证了数据的一致性,还有效减小了主机处理器对成块数据进行传输的开销。
所有消息依照其指令的接收子地址、发送子地址、广播子地址或是方式指令的不同可在错误后或是循环缓冲到达下边界时产生中断。主机可通过中断状态寄存器中的数值获取中断原因信息。 建议用户使用循环缓冲管理机制,这样能极大的发挥出 LHB155304的智能特性,降低主机通信的开销。
3.3.1 单消息存储管理机制
RT 的缺省存储管理模式是非增强模式下的单消息存储管理。单消息存储管理是 RT模式下最简单的一种存储管理模式。
单消息存储管理模式的使用条件:
( 1)在非增强的存储管理模式( CFG#2.1=‘ 0’ )下, RT 工作于非增强模式(缺省模式)。此时对于所有的子地址,发送、接收和广播操作均使用单消息存储管理机制。
( 2)在增强存储管理模式( CFG#2.1=‘ 1’ )下,通过对 RT 子地址控制字寄存器中相应的接收位、发送位、广播进行配置, RT 也可以使用单消息存储管理机制。当 RT 子地址控制字 bit15(双缓冲使能)为‘ 0’,将 RT 子地址控制字 bit12‐bit10 接收存储管理MM2‐MM0、 RT 子地址控制字 bit7‐bit5 发送存储管理 MM2‐MM0、 RT 子地址控制字bit2‐bit0 广播存储管理 MM2‐MM0 都配置为‘ 0’ ,则 RT 将使用单消息存储管理模式。当RT 子地址控制字 bit15(双缓冲使能)为‘ 1’,将接收、发送、广播的 MM2‐MM0 都配置为“ 000”,则 RT 对发送操作采用单消息存储管理模式,而对接收操作和广播操作将采用双缓冲存储管理模式。
RT 单消息存储管理机制如图所示。用户可以通过配置寄存器#1 的 bit13 指定两个区域之一为“活跃”区(工作区),则另一个为“非活跃”区(非工作区)。图中用阴影表示“非活跃”区,空白区域为“活跃”区。主机能够访问 A、 B 两个区域的各种数据结构,而 RT 的协议处理单元只能访问“活跃”区中的数据。
单消息存储管理模式下 RT 的运行RT 接收到消息后,首先将接收到的指令字存放在描述符堆栈(又叫指令堆栈、堆栈)的第四项字单元中。然后,通过访问 RT 查询表, RT 找到指令字中接收、发送或广播子地址对应的数据块指针单元,确定当前消息对应的数据块起始地址。接收到的数据字和要发送的数据字就存放在这个指定的数据块中。同时, RT 将数据块指针的值写入描述符堆栈的第三项“数据块指针”中,然后将时间标志寄存器的值写入时间标志字。最后, RT 访问描述符堆栈的最低位字单元“块状态字”,将其 bit14“消息开始位”置1。在接收(或者发送)完数据(即消息结束)后, RT 将再次访问块状态字和时间标志字,写入消息的有关信息和时间标志寄存器的值。每个数据块的存储空间最大为 32 字。
注意:
对于增强方式指令处理模式,在带字的方式指令消息格式中,数据块指针项将存放方式指令的数据字而非数据块指针。
在单消息管理机制中,对于某个特定的子地址,其查询表值始终不变,因而处理若干条包含该子地址的消息将导致其对应数据块的内容被反复地读写。当然,在单消息存储管理机制中,若主机处理器在每条消息结束后重新配置查询表,则同一个子地址也可以访问多个数据块。
在单消息存储管理模式下,用户必须在初始化 RT 查询表时,指定每个接收子地址( CFG#2.0=‘ 1’时,还包括广播子地址)和发送子地址数据块的起始地址。比如,对于子地址 1,接收指令的数据块起始地址由 0141H 单元中的值指定,而发送指令的数据字则来源于 0161H 所指向的数据块;对于子地址 2,接收指令的数据块起始地址在 0142H单元中的值指定,而发送指令的数据字来源于 0162H 单元所指向的数据块……等等。在非增强方式指令处理模式下,对于子地址为‘ 0’ (或‘ 31’ )的方式指令则在指令字的T/R*=‘ 0’时有关数据字的地址在 0140H(或 015FH)单元。当 T/R*=‘ 1’时,由 0160H(或 017FH)单元指定。 RT 查询表占用地址空间及与子地址的对应关系参见存储的表。
3.3.2 循环缓冲存储管理机制
循环缓冲存储管理机制如下图 所示。其中阴影部分表示“非活跃”区,空白区域表示“活跃”区。
循环缓冲的使用条件
在增强 RT 存储管理模式下( CFG#2.1=‘1’ ,配置寄存器#3 的 bit15 可为任意值),RT 才可以使用循环缓冲存储管理机制。如果 CFG#2.1=‘0’, RT 将使用单消息存储管理机制,每个子地址由其查询表对应的数据块指针分配一个单独的数据块。
循环缓冲的运行过程及特征
与单消息存储管理机制一样,主机首先要初始化每个查询表项。在接收到一条消息后, RT 将接收到的指令字存放在描述符堆栈的最高位字单元中。接着,通过访问 RT 查询表, RT 找到指令字中包含的子地址所对应的数据块地址指针,确定处理当前消息所需的数据块起始地址。 RT 接收到的数据字或 RT 发送的数据字就存放在这个指定的数据块中。同时, RT 将数据块指针值写入描述符堆栈的第三项中,然后将时间标志寄存器的值写入时间标志字。最后, RT 访问描述符堆栈的最低位字单元“块状态字”,将其 bit14“消息开始位”置‘1’。在接收(或者发送)完数据(即消息结束)后, RT 将再次访问块状态字和时间标志字,写入消息的有关信息和时间标志寄存器的值,并更新 RT 查询表的相应指针项和堆栈指针项。
使用循环缓冲机制时, RT 必须考虑“覆写无效数据”可能产生的影响。若忽略无效字( CFG#2.11=‘ 1’),当存在错误的消息结束时, RT 查询表中的数据块地址指针将不更新,下一条消息的接收数据将覆盖当前错误消息的数据。当然,发送数据也将从当前错误消息的数据块起始地址读取。若忽略无效字不使能( CFG#2.11=‘ 0’),无论消息是否正确, RT 查询表中的数据块地址指针都将更新。这样,在一条(有效或者无效)消息处理结束时, RT 查询表对应的数据块地址指针将更新为与当前消息所访问的地址相邻的下一地址。因此,若下一条消息包含同一接收、发送或广播子地址,其数据字将访问循环缓冲区中的下一相邻数据块。若配置寄存器#2 的 bit11(忽略无效字)为‘ 1’,当 RT 接收到的消息(或者广播)异常时, RT 查询表将不会更新数据块地址指针。这样, BC(总线控制器)可以通过消息重发功能,用有效数据覆盖之前的无效数据,无需连接 RT 的主机处理器的干预。当指针到达了循环缓冲区(大小为 128 字、 256 字、……或 8192 字)的最高地址后,将指回循环缓冲区的最低地址。
循环缓冲描述堆栈的各项含义与单消息管理机制时的相同,可以参考单消息管理机制部分和 RT 存储组织部分的说明。
注意:
在 RT 模式下,无论配置寄存器#2 的 bit0(分离广播数据)是否置位,要想使用循环缓冲机制存储广播消息,必须要配置 RT 子地址控制字中广播子地址相关的存储管理控制位
3.3.3 双缓冲存储管理机制
在很多 RT 的应用中,主机需要访问指定子地址刚接收到的消息。在这种情形下,RT 子地址双缓冲机制使得主机处理器方便地确定数据块地址并读取指定子地址相关的数据字,从而确保相邻两条消息数据的完整性。双缓冲存储管理机制只适用于接收子地址或广播子地址,主机能够方便地访问刚接收的与指定子地址相关的数据。双缓冲存储管理机制在数据块中给每个接收(或是广播)子地址分配两个 32 字的数据块(数据块 0 和数据块 1)。主机只需在 RT 查询表中初始化数据块 0 的地址指针即可。数据块 1 起始地址与数据块 0 起始地址的 bit5 值相反,这两个指针的其余位则相同。消息处理结束后,子地址的数据块地址指针将自动更新,在“ ×…×1×××××”和“ ×…×0×××××”之间切换。若 RT 查询表中某子地址对应的数据块地址指针被初始化为 0800H(即数据块 0 的起始地址),则对应的数据块 1 起始地址为 0820H(即0800H 的 bit5 取反)。
RT 将接收的数据字交替存储到数据块 0 和数据块 1 中。在任一给定的时刻,两个数据块只有一个处于“活跃”状态,则另一数据块为“非活跃”区。针对该子地址的消息,其数据将存放在“活跃”的数据块。假如消息是有效的, RT 将在消息完成后立即切换“活跃”区与“非活跃”区,保证主机处理器始终能够访问刚刚接收到的有效数据块。
双缓冲存储管理可以基于子地址控制字,显示在子地址控制字配置下, RT 采用双缓冲存储管理模式,则 RT 将数据字存储到“活跃”的数据块 0 中, RT 查询表中对应的数据块地址指针更新为“非活跃”的数据块 1 的起始地址。图中阴影部分表示 “非活跃”区,空白区域表示“活跃”区。当再接收到针对该子地址的消息时,双缓冲存储管理机制将使能数据块 1,使得接收到的有效数据存入数据块 1, RT 查询表中对应的数据块地址指针将更新为“非活跃”的数据块 0 的起始地址。
RT 双缓冲存储管理机制可以实现使用子地址控制字的控制方式和全局双缓冲工作、方式两种配置模式:
双缓冲存储管理的两种方式
( 1) 全局性双缓冲方式: RT 增强模式( CFG#3.15=‘ 1’)下,配置寄存器#2 的 bit12(接收子地址双缓冲使能)为‘ 1’,配置寄存器#2 的 bit1( RT 增强存储管理模式)为 ‘ 0’,则对所有接收子地址和广播子地址, RT 都采用双缓冲存储管理机制(如果广播数据分离存放)。
( 2) 由子地址控制字控制的双缓冲方式: RT 增强模式( CFG#3.15=‘ 1’)下,配置寄存器#2 的 bit12(接收子地址双缓冲使能)为‘ 1’,配置寄存器#2 的 bit1( RT 增强存储管理模式)为‘ 1’。当子地址控制字的最高位为‘ 1’ 且接收子地址的 MM2‐MM0为“ 000”时,该控制字的接收子地址采用双缓冲管理机制。若广播数据分离存放,当广播子地址的 MM2‐MM0 为“ 000”时,广播数据块采用双缓冲管理机制。
双缓冲描述堆栈的各项含义与单消息管理机制时的相同,可以参考单消息管理机制部分和 RT 存储组织部分的说明。
双缓冲的运行过程
RT 接收到 BC 指令后首先将接收到的指令字存放在消息描述符堆栈的最高位字单元中。然后, RT 访问 RT 查询表,找到相应子地址的数据块地址指针。当前消息接收到的数据字或要发送的数据字就存放在以该地址指针为起始地址的数据块中。同时, RT 将数据块地址指针的值写到描述符堆栈的“数据块指针”项,然后将时间标志寄存器的值写入时间标志字,最后描述符堆栈的最低位字单元(块状态字)的消息开始位置1。消息处理结束时, RT 再次访问块状态字和时间标志字,分别写入消息的相关信息和当前的时间标志寄存器值,并更新 RT 查询表的相应指针项和堆栈指针项。
3.4 增强方式指令处理
对于正常工程而言,一般都会选择增强模式。由于方式指令在 1553B 总线中用于控制和管理的特殊性, LHB155304 为方式指令处理提供了更加丰富的方式。增强方式指令处理是只适用于方式指令的处理机制,它以牺牲共享存储器的可用空间为代价,在 RAM 中将若干空间单元指定给方式指令专用,向主机提供了更加自由的选择空间。
增强方式指令处理主要是指方式指令的数据字在共享 RAM 中具有固定的访问单元并且用户可以配置选择向主机产生中断的方式指令。增强方式指令处理模式的使用条件是:增强 RT 模式( CFG#3.15=‘ 1’ )且增强方式指令处理使能( CFG#3.0=‘ 1’)。该模式下,对于方式指令的处理有三方面的影响:
( 1)对于所有非方式指令和增强方式指令处理不使能的方式指令,描述堆栈第三项存储的是数据块单元的指针。对于带数据字的方式指令,如果增强方式指令处理使能,则描述堆栈的第三项直接写入的是方式指令的数据字(发送或接收的数据)而不是数据单元的指针。对于不带数据字的方式指令描述堆栈的第三项不写任何值。
( 2)增强方式指令处理时的方式指令数据字由固定单元存取,这需要注意的是,如果广播数据分离不使能(CFG#2.0=0)时, RT 将接收到的广播方式指令数据存储在非广播接收数据字的相应单元。
3)RT 将 RAM 地址空间从 0108H 到 010FH 的 8 个字单元作为方式指令的中断选择表。通过选择表用户可以方便的选择需要通过主机中断服务处理的方式指令消息。在增强方式指令处理使能并且中断屏蔽寄存器的 bit1( RT 方式指令)为‘ 1’的条件下,在消息结束时 RT 将会查询方式指令中断表。如果中断表中方式指令位被配置为 1,则在该消息结束时将会向主机产生中断。
注意:
无论当前方式指令是否非法或无效,只要该指令字满足 1553B 总线有效字规则,都将在当前消息结束时产生中断。
忙位和广播选项没有用到,统一按照默认处理了,方式指令的具体内容在常识篇也有描述,不重复了。
四.配置例程
就以典型的一种初始化配置和中断处理来作为例子,把以上内容做个总结吧
例子要求对 4 个子地址和方式指令进行配置,要求:
( 1) 子地址 1,发送,单消息存储管理,使能发送消息结束中断
( 2) 子地址 7,接收(包括广播消息), 1024 字循环缓冲存储管理模式、使能接收循环缓冲回卷中断和广播循环缓冲回卷中断
( 3) 子地址 19,接收(包括广播消息),双缓冲存储管理模式,使能接收消息结束中断和广播消息结束中断
( 4) 子地址 30,接收、广播和发送,单消息存储管理,中断禁止为了满足要求并充分利用 LHB155304 的 RT 功能,现在配置如下:
— 使用增强模式;
— 增强中断使能。使能 RT 子地址控制字中断、 RT 循环缓冲回卷中断、 RT 方式指令中断和格式错误中断;
— 实现广播数据分离存放;
考虑子地址 2 的要求使能增强存储管理、使能覆写无效数据、不使能 256 字边界禁止;
— 时标分辨率采用默认的 16μs/LSB;
— 忙表使能,但不设置任何子地址为忙;
— 回写测试失败将导致 RT 故障位置位;
— 非方式指令的接收数据字不存储,但是方式指令的数据字要存储;
— 增强方式指令处理使能。这样,发送矢量字和带字同步方式指令就会使用不同的数据地址。此外,可以选择使能同步方式指令(包括带字和不带字两种)、复位方式指令、自检方式指令中断。对于广播地址,这些中断也被使能;
— 假设 RT 地址为 20(由于硬件设置的原因不可软件编程);
— 使用16MHz时钟,使能GAP检查;
— 所有要使用的子地址和除过“选择的发送器切断”与“忽略选择的发送器切断”外
的所有 1553B 定义的方式指令都配置为合法;所有未被使用的子地址和方式指
令以及没有定义和保留的方式指令均被设置为非法;
— 子地址 1 的大小为 32 字的发送数据块被初始为 0、 1、 2、 …、 1F;
— 所有的 RT 状态字位初始化为‘ 0’。
文字概括一下,有的步骤可以省略,16步
( 1)复位 RT,即向启动/复位寄存器写 0001H。
( 2)如果要使用 RT 的增强模式(例如,子地址双缓冲模式的使用),向配置寄存器#3 写 8000H。
( 3)初始化中断屏蔽寄存器。大多数应用中, RT 消息结束中断应当被使能; RT 子地址控制字中断、 RT 循环缓冲回卷中断、 RT 方式指令中断和格式错误中断一般也要被使能。 RT 子地址控制字中断指定在某个子地址的消息结束时产生中断, RT 模式方式指令中断使能时在编程指定的方式指令结束时产生中断, RT 循环缓冲回卷中断使能时,当指定的子地址的数据栈栈地址发生回卷时在消息结束时产生中断。
( 4)将指令堆栈的地址写入当前活动区域的堆栈指针 RAM 单元。
( 5)作为可选的一个步骤,初始化活跃区的指令堆栈。如果用户需要在消息的处理过程中查询消息的块状态字,消息的块状态字单元最好就在此时清零。值为“ 0000H”的块状态字单元意味着消息还没有收到。
( 6)初始化活跃区的 RT 查询表。 RT 查询表指定了每个子地址的各种消息的数据字地址,用户在初始化数据单元前必须在这里先将规划的消息数据单元地址填入 RT 查询表。如果 RT 增强存储管理模式使能,用户还必须通过查询表的子地址控制字项为每个子地址选择存储管理模式和中断。需要注意的是,一般的应用中 RT 只带极少量的子地址,此时最好将没有使用的子地址的数据指针也进行初始化,并且最好将指针值初始化为同一个值。
( 7)如果用户没有使用增强方式指令处理模式(配置寄存器#3.0 控制),接收子地址 0 和 31(对带字的同步方式指令)的数据指针一般初始化为同一个值,发送子地址 0和 31(对发送矢量字方式指令)的数据指针一般也初始化为同一个值。如果使用了增强方式指令处理模式,同步方式指令接收到的同步数据字将被存放在 0111H 单元,而发送矢量字指令的消息字从 0120H 单元取得。
( 8)初始化配置寄存器#2。需要选择的功能包括:如果想给子地址设置循环缓冲或子地址双缓冲就必须选择增强 RT 存储管理;如果广播消息想遵循 1553B 协议的 Notice2就必须将广播数据分离存放使能,这样广播消息和非广播接收消息就会使用不同的数据指针;时标分辨率也应当在此选择;如果主机想查询中断状态寄存器或者如下任何一种情况需要产生中断就必须设置为增强中断模式:发送超时(暂时没有实现)、 RT 指令堆栈发生回卷、 RT 方式指令中断。还有中断信号类型(电平、脉冲)的选择、中断状态自动清除的选择也在此设置。如果希望 RT 在接收“发送矢量字”发生指令后自动清除状态字的服务请求位,就必
须将清除服务请求位设置为‘ 1’。如果忙表使能,就要按照需要在忙表中置位选中的子地址和消息类型忙控制位。如果子地址使用循环缓冲,将覆写无效字置位是我们推荐的配置。子地址双缓冲也在这里设置。
( 9)初始化配置寄存器#3。如果使用增强模式, bit15 应该为‘ 1’。这里主要配置指令堆栈的大小( 256 字、 512 字…)。 RT 指令栈大小通过 bit14 和 bit13 在 256 字(缺省配置)、 512 字、 1024 字和 2048 字之中选择指定。配置寄存器#3 控制的其它一些功能还包括:非法表的禁止、另一种 RT 状态字模式的选择、忙或指令非法时数据是否存储、增强方式指令处理的选择、 1553A 方式指令使能、 RT 故障显示( RT FAIL/RT FLAG* WRAP)的使能。 RT 故障显示使能时, RT 一旦监测到回写测试失败就会置位状态字的故障标记位。增强方式指令处理模式下各个方式指令的数据字有固定的存储单元。
( 10)初始化配置寄存器#4。如果外部 BIT 字使能,发送 BIT 字的方式指令就会从RAM 中读取数据,否则从寄存器中读取。
( 11) 初始化配置寄存器#5。主要是 16MHz 时钟的选择和响应超时时间标准的选择。
( 12)如果必要,初始化非法表。非法表地址是 0300H‐03FFH。
( 13)如果必要,初始化忙表。忙表地址是 0240H‐0247H。
( 14)如果增强中断使能并且增强方式指令处理使能,配置 0108H‐010FH 单元选择某些方式指令产生中断。
( 15)将发送的数据写入相应的数据块,将接收数据区清零。
( 16)配置的最后一步,初始化配置寄存器#1。选择 RT 模式,选择当前活动区域。
根据两种状态模式的选择,初始化 RT 状态字的控制位。
头文件
#ifndef SRC_1553RT_DRIVER_H_ #define SRC_1553RT_DRIVER_H_ #include "xil_io.h" #include "xparameters.h" #include "xstatus.h" #include "xil_printf.h" #include "xgpiops.h" #include "sleep.h" #include "xil_exception.h" #include "xscugic.h" #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #define INTC XScuGic #define INTC_HANDLER XScuGic_InterruptHandler #define RT_BASE_ADDR 0x43C00000 #define RT_RAM_BASE 0x43C00000 INTC IntcInstance; #define RT_WriteReg(BaseAddress, RegOffset, Data) \ Xil_Out32((BaseAddress) + (RegOffset), (Data)) #define RT_ReadReg(BaseAddress, RegOffset) \ Xil_In32((BaseAddress) + (RegOffset)) #define MEM_Write(BaseAddress, RegOffset, Data) \ Xil_Out32((BaseAddress) + (RegOffset), (Data)) #define MEM_Read(BaseAddress, RegOffset) \ Xil_In32((BaseAddress) + (RegOffset)) #define BUREG 0x43C00000 //???????????????? reg??? #define BUMEM 0x43C00000 //???????????????????mem??? #define BURTA 0x00000 /*?????????????????????????????????????????????????????????????????????*/ #define BUMSGDATANUM 0x20 //1553 message data size 32 #define BUCHANNELA 0x0 #define BUCHANNELB 0x1 #define BURX 0x0 #define BUTX 0x1 #define ERR1 0x0 #define ERR3 0x1 #define ERR 0x2 #define OK 0x0 #define INTMASK 0x0 #define BUZERO 0x0 #define BUMSGDATANUM 0x20 //1553 message data size 32 #define BUSUBADDR0 0x0 #define BUSUBADDR31 0x20 //1553 subaddress 31 #define BUMSGBUFSIZE 0x40 //1553 message buffer size 64 #define BUEOMINT 0x1 #define BUMSGBUFBGN 0x0 //1553 message buffer begin 0 #define BUINTMASK 0x0 #define BUCFG1 0x1 #define BUCFG2 0x2 #define BURST 0x3 #define BUCMDSTACKPOINT 0x3 #define BURTSUBADDRCTRL 0x4 #define BUTIMETAG 0x5 #define BUINTSTATUS 0x6 #define BUCFG3 0x7 #define BUCFG4 0x8 #define BUCFG5 0x9 #define BURTDATASTACKADDR 0xa #define BUBCFRAMETIME 0xb #define BUBCTIMEREMAIN 0xc #define BURTLASTCMD 0xd #define BURTSTATUSWORD 0xe #define BURTBITWORD 0xf #define BUTSTMODE0 0x10 #define BUTSTMODE1 0x11 #define BUTSTMODE2 0x12 #define BUTSTMODE3 0x13 #define BUTSTMODE4 0x14 #define BUTSTMODE5 0x15 #define BUTSTMODE6 0x16 #define BUTSTMODE7 0x17 // 1553B typedef struct { unsigned int channelAB; unsigned int blockStatusWord; unsigned int timeTagWord; unsigned int dataBlockPointer; unsigned int commandWord; unsigned int remoteTerminalAddr; unsigned int tr; unsigned int subAddModeCode; unsigned int dataCntModeCode; unsigned int data[BUMSGDATANUM]; }BUMSGIFM; // 1553B typedef struct { BUMSGIFM buRxRPool[BUMSGBUFSIZE]; unsigned int buRxRPoint; BUMSGIFM buRxTPool[BUMSGBUFSIZE]; unsigned int buRxTPoint; } BUBUFFER; extern void RTInit(); extern void interrupt_handle(); int showreg(); int RTdemo(); static int rt1553BSetupIntrSystem(INTC *IntcInstancePtr,u16 rt1553bIntrId); #endif /* SRC_1553RT_DRIVER_H_ */
驱动部分
void RTInit() { int Status; int i,mem; XGpioPs_Config *ConfigPtr; ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID); Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr); if (Status != XST_SUCCESS) { return XST_FAILURE; } XGpioPs_SetDirectionPin(&Gpio, MEMCTR, 1); //设置指定引脚的方向: 0 输入, 1 输出 XGpioPs_SetOutputEnablePin(&Gpio, MEMCTR, 1); //使能指定引脚输出: 0 禁止输出使能, 1 使能输出 XGpioPs_WritePin(&Gpio, MEMCTR, 0x0);//禁用mem usleep(10); RT_WriteReg(RT_BASE_ADDR,(0x03)*4,0x0001);//软件复位 LHB155304, RT_WriteReg(RT_BASE_ADDR,(0x07)*4,0x8000);/*配置寄存器#3 的增强模式位置位(因为忙表、增强方式指令处理、增强中断处理等功能必须在增强模式下才能有效)*/ xil_printf("startreg\r\n"); RT_WriteReg(RT_BASE_ADDR,0x00,0x0037);/*初始化中断屏蔽寄存器:使能 RT 子地址控制字中断、 RT 循环缓冲回卷中断、 RT 方式指令中断和格式错误中断*///0013,0037 RT_WriteReg(RT_BASE_ADDR,(0x02)*4,0xB833);/*初始化配置寄存器#2:使能增强中断、忙表、接收子地址双缓冲、覆写无效数据字、增强 RT 存储管理和广播数据分离存放*///803A,B80B RT_WriteReg(RT_BASE_ADDR,(0x07)*4,0x801D);/*初始化配置寄存器#3:增强模式、禁止非法和忙时接收数据、使能增强方式指令处理、使能 RT 故障显示*///809D,801Dbit7非法禁止 RT_WriteReg(RT_BASE_ADDR,(0x08)*4,0x2008);/*初始化配置寄存器#4:使能方式指令忽略忙位和 RT 地址锁存*///2008,2000bit3保留 RT_WriteReg(RT_BASE_ADDR,(0x09)*4,0x0A00);/*初始化配置寄存器#5:选择 16MHz 时钟、使能 GAP 检查*///0800,0100bit15时钟选择bit11保留 XGpioPs_WritePin(&Gpio, MEMCTR, 0x1);//使能mem usleep(10); for(i=0; i<256; i++) { MEM_Write(RT_RAM_BASE,(0x000+i)*4,0000);//块状态字单元清零 } //设置堆栈指针 MEM_Write(RT_RAM_BASE,(0x0100)*4,0000);//初始化区域 A 指令堆栈指针为‘0 /*初始化方式指令中断*/ MEM_Write(RT_RAM_BASE,(0x0108)*4,0x0000);//接收方式指令 0‐15 不产生中断 MEM_Write(RT_RAM_BASE,(0x0109)*4,0x0002);//接收方式指令中断:带字同步方式指令中断使能 // mem = MEM_Read(RT_BASE_ADDR,(0x109)*4); // xil_printf("mem the address at %x data is :0X %x \n\r" ,RT_BASE_ADDR+(0x109)*4, mem); MEM_Write(RT_RAM_BASE,(0x010A)*4,0x010A);//发送方式指令中断:无字同步、复位 RT 和自检指令中断使能 MEM_Write(RT_RAM_BASE,(0x010B)*4,0x0000);//发送方式指令 16‐31 不产生中断 MEM_Write(RT_RAM_BASE,(0x010C)*4,0x0000);//广播接收方式指令 0‐15 不产生中断 MEM_Write(RT_RAM_BASE,(0x010D)*4,0x0000);//广播接收方式指令中断:带字同步方式指令中断使能 MEM_Write(RT_RAM_BASE,(0x010E)*4,0x010A);//广播发送方式指令中断:无字同步、复位 RT 和自检指令中断使能 MEM_Write(RT_RAM_BASE,(0x010F)*4,0x0000);//广播发送方式指令 16‐31 不产生中断 /*初始化方式指令数据字*/ MEM_Write(RT_RAM_BASE,(0x0111)*4,0x0000);//为同步方式指令接收数据保留,清零 MEM_Write(RT_RAM_BASE,(0x0120)*4,0x1234);//发送矢量字方式指令的数据 /*初始化RT查询表*/ MEM_Write(RT_RAM_BASE,(0x0147)*4,0x0800);//接收子地址 7 的数据指针 MEM_Write(RT_RAM_BASE,(0x0153)*4,0x0440);//接收子地址 19 的数据指针 MEM_Write(RT_RAM_BASE,(0x0161)*4,0x0400);//发送子地址 1 的数据指针 MEM_Write(RT_RAM_BASE,(0x015E)*4,0x0480);//接收子地址 30 的数据指针 注意:子地址 30 的发送、接收和广播数据指针都被指定为 0480 MEM_Write(RT_RAM_BASE,(0x017E)*4,0x0480);//发送子地址 30 的数据指针 MEM_Write(RT_RAM_BASE,(0x0187)*4,0x0C00);//广播接收子地址 7 的数据指针 MEM_Write(RT_RAM_BASE,(0x0193)*4,0x04A0);//广播接收子地址 19的数据指针 MEM_Write(RT_RAM_BASE,(0x019E)*4,0x0480);//广播接收子地址 30的数据指针 //初始化 RT 子地址控制字 没有使用的子地址控制字单元应当清零,这里没有给出 MEM_Write(RT_RAM_BASE,(0x01A1)*4,0x0400);//子地址 1:发送消息使用单消息管理机制,发送消息结束中断 MEM_Write(RT_RAM_BASE,(0x01A7)*4,0x018C);//接收和广播消息使用 1024 字循环缓冲管理机制,使能接收循环缓冲回卷中断,使能广播循环缓冲回卷中断 MEM_Write(RT_RAM_BASE,(0x01B3)*4,0x8210);//子地址 19:接收和广播接收使用双缓冲管理机制,使能接收消息结束中断,使能广播消息结束中断 MEM_Write(RT_RAM_BASE,(0x01BE)*4,0x0000);//子地址 30:所有消息类型使用单消息管理机制,不产生中断 //初始化忙表(所有子地址初始化为不忙) for(i = 0; i < 8; i++) { MEM_Write(RT_RAM_BASE,(0x0240+i)*4,0000); } //初始化非法表 //广播接收字地址 MEM_Write(RT_RAM_BASE,(0x0300)*4,0xFFFF);//子地址 0,广播接收方式指令设置 MEM_Write(RT_RAM_BASE,(0x0301)*4,0xFFFD);//子地址 0,广播接收方式指令设置:只有带字同步指令被指定为合法 for(i = 0; i < 12; i++) { MEM_Write(RT_RAM_BASE,(0x0302+i)*4,0XFFFF);//广播接收子地址 1‐广播接收子地址 16 非法 } MEM_Write(RT_RAM_BASE,(0x030E)*4,0000);//广播接收子地址 7 合法 MEM_Write(RT_RAM_BASE,(0x030F)*4,0000); for(i = 0; i < 22; i++) { MEM_Write(RT_RAM_BASE,(0x0310+i)*4,0XFFFF);//广播接收子地址 1‐广播接收子地址 16 非法 } MEM_Write(RT_RAM_BASE,(0x0326)*4,0000);//广播接收子地址 19 合法 MEM_Write(RT_RAM_BASE,(0x0327)*4,0000); for(i = 0; i < 20; i++) { MEM_Write(RT_RAM_BASE,(0x0328+i)*4,0XFFFF);//广播接收子地址 20‐广播接收子地址 129 非法 } MEM_Write(RT_RAM_BASE,(0x033C)*4,0000);//广播接收子地址 30 合法 MEM_Write(RT_RAM_BASE,(0x033D)*4,0000); MEM_Write(RT_RAM_BASE,(0x033E)*4,0xFFFF);//广播接收方式指令设置 MEM_Write(RT_RAM_BASE,(0x033F)*4,0xFFFD);//子地址 31,广播接收方式指令设置:只有同步方式指令合法 /*广播发送子地址*/ MEM_Write(RT_RAM_BASE,(0x0340)*4,0xFE05);//子地址 0,广播发送方式指令设置 MEM_Write(RT_RAM_BASE,(0x0341)*4,0xFFFF);/*子地址 0,广播发送方式指令设置:无字同步、启动自检、发送器 切断、忽略发送器切断、禁止故障标记位、忽略故障禁止标记和复位 RT 方式指令合法*/ /*( M0342‐037D 单元无需配置)*/ MEM_Write(RT_RAM_BASE,(0x037E)*4,0xFE05);//子地址 31,广播发送方式指令设置: MEM_Write(RT_RAM_BASE,(0x037F)*4,0xFFFF);/*子地址 31,广播发送方式指令设置:无字同步、启动自检、发送器切断、忽略发送器切断、禁止故障标记位、忽略故障禁止标记和复位 RT 方式指令合法*/ /*;非广播接收子地址*/ MEM_Write(RT_RAM_BASE,(0x0380)*4,0xFFFF);//子地址 0,非广播接收方式指令设置 MEM_Write(RT_RAM_BASE,(0x0381)*4,0xFFFD);//子地址 0,非广播接收方式指令设置,只有带字同步方式指令设置为合法 for(i = 0; i < 12; i++) { MEM_Write(RT_RAM_BASE,(0x0382+i)*4,0XFFFF);//广播接收子地址 1‐广播接收子地址 16 非法 } MEM_Write(RT_RAM_BASE,(0x038E)*4,0000);//接收子地址 7 合法 MEM_Write(RT_RAM_BASE,(0x038F)*4,0000); for(i = 0; i < 22; i++) { MEM_Write(RT_RAM_BASE,(0x0390+i)*4,0XFFFF);//非广播接收子地址 8‐非广播接收子地址 18 非法 } MEM_Write(RT_RAM_BASE,(0x03A6)*4,0000); //非广播接收子地址 19 合法 MEM_Write(RT_RAM_BASE,(0x03A7)*4,0000); for(i = 0; i < 20; i++) { MEM_Write(RT_RAM_BASE,(0x03A8+i)*4,0XFFFF);//非广播接收子地址 20‐非广播接收子地址 29 非法 } MEM_Write(RT_RAM_BASE,(0x03BC)*4,0000); //非广播接收子地址 30 合法 MEM_Write(RT_RAM_BASE,(0x03BD)*4,0000); MEM_Write(RT_RAM_BASE,(0x03BE)*4,0xFFFF); //子地址 31,非广播接收方式指令设置: MEM_Write(RT_RAM_BASE,(0x03BF)*4,0xFFFD); //子地址 31,非广播接收方式指令设置:只有无字同步方式指令合法 /*非广播发送子地址*/ MEM_Write(RT_RAM_BASE,(0x03C0)*4,0xFE00); //子地址 0,非广播发送方式指令设 MEM_Write(RT_RAM_BASE,(0x03C1)*4,0xFFF2); /*子地址 0,非广播发送方式指令设置:动态总线控制、无字同步、发送状态字、启动自检、发送器切断、忽略发送器切断、禁止终端故障标记、忽略禁止终端故障标记、复位 RT、发送矢量字、发送上一指令字和发送 BIT 字合法*/ MEM_Write(RT_RAM_BASE,(0x03C2)*4,0000); //非广播发送子地址 1 合法 MEM_Write(RT_RAM_BASE,(0x03C3)*4,0000); for(i = 0; i < 56; i++) { MEM_Write(RT_RAM_BASE,(0x03C4+i)*4,0XFFFF);//非广播接收子地址 20‐非广播接收子地址 29 非法 } MEM_Write(RT_RAM_BASE,(0x03FC)*4,0000); //非广播发送子地址 30 合法 MEM_Write(RT_RAM_BASE,(0x03FD)*4,0000); MEM_Write(RT_RAM_BASE,(0x03FE)*4,0xFE00); //子地址 31,非广播发送方式指令设置 MEM_Write(RT_RAM_BASE,(0x03FF)*4,0xFFF2); /*子地址 31,非广播发送方式指令设置:动态总线控制、无字同步、发送状态字、启动自检、发送器切断、忽略发送器切断、禁止终端故障标记、忽略禁止终端故障标记、复位 RT、发送矢量字、发送上一指令字和发送 BIT 字合法 */ /*初始化各个子地址的数据块*/ /*初始化子地址 1 的发送数据字*/ for(i = 0; i < 32; i++) { MEM_Write(RT_RAM_BASE,(0x400+i)*4,(0x001+i)); } /*0440‐045F 为接收子地址 19 的数据块 1,不需要初始化 0460‐047F 为接收子地址 19 的数据块 2,不需要初始化 0480‐049F 为子地址 30 的数据块(接收、发送、广播接收),不需要初始化 04A0‐04BF 为广播接收子地址 19 的数据块 1,不需要初始化 04C0‐04DF 为广播接收子地址 19 的数据块 2,不需要初始化 04E0‐04FF,为其它需要使用的子地址保留,不需要初始化 0800‐0BFF 为接收子地址 2 的 1024 字循环缓冲,不需要初始化*/ XGpioPs_WritePin(&Gpio, MEMCTR, 0x0);//禁用mem usleep(10); /*初始化配置寄存器#1,启动 RT */ RT_WriteReg(RT_BASE_ADDR,(0x01)*4,0x8F80);/*选择 RT 模式, RT 状态字的动态总线控制、忙、服务请求、子地址故障标记和 RT 故障标记位设置为‘ 0’。*/ // showreg(); sleep(1); // Status = rt1553BSetupIntrSystem(&IntcInstance1553,XPS_FPGA0_INT_ID); // // if (Status != XST_SUCCESS) // { // xil_printf("1553B Init Failed\r\n"); // return XST_FAILURE; // } }
和逻辑工程师协商,对寄存器和存储的访问由gpio控制,默认访问寄存器,使能访问存储,偏移地址的*4也是协商结果,读写寄存器内存的函数原型为Xil_In32和Xil_Out32,也定义了相应的结构体
typedef struct { unsigned int channelAB; unsigned int blockStatusWord; unsigned int timeTagWord; unsigned int dataBlockPointer; unsigned int commandWord; unsigned int remoteTerminalAddr; unsigned int tr; unsigned int subAddModeCode; unsigned int dataCntModeCode; unsigned int data[BUMSGDATANUM]; }BUMSGIFM;
对整个模式配置和收发数据的流程做个研究,发现RT接收到的指令字中的收发标志位作为逻辑判断比较合适,那么相应的中断处理函数的流程图如下
咳咳咳咳咳咳
嗯,那中断处理部分也就出来了
void rt1553B_handle() { int Status; // XGpioPs_Config *ConfigPtr; // ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID); // Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, // ConfigPtr->BaseAddr); // if (Status != XST_SUCCESS){ // return XST_FAILURE; // } // // XGpioPs_SetDirectionPin(&Gpio, MEMCTR, 1); // //设置指定引脚的方向: 0 输入, 1 输出 // XGpioPs_SetOutputEnablePin(&Gpio, MEMCTR, 1); // //使能指定引脚输出: 0 禁止输出使能, 1 使能输出 XGpioPs_WritePin(&Gpio, MEMCTR, 0x0);//禁用mem usleep(10); // showreg(); int i = 0; unsigned int temp,temp1; int tempVar = 0; int blk; tempVar = (RT_ReadReg(RT_BASE_ADDR,(BUINTSTATUS)*4))& BUEOMINT;//读中断状态寄存器,判断现在状态 // tempVar = *(unsigned int *)(BUREG |BUINTSTATUS) & BUEOMINT;//(bit 0 = 1表示消息结束) xil_printf("tempVar is 0x%x\r\n",tempVar); if(tempVar == BUEOMINT) { //temp1=BUREG | BUCFG1;//配置寄存器#1 temp = RT_ReadReg(RT_BASE_ADDR,(BUCFG1)*4); //temp = *(unsigned int *) (temp1); xil_printf("cfg1 is 0x%x\r\n",temp); BUMSG.channelAB=(temp>>13) & 0x1;//判断当前工作区域// xil_printf("channelAB is 0x%x\r\n",BUMSG.channelAB); /***************************************堆栈四个单元分别读写************************************************************/ //BUMSG.blockStatusWord = *(unsigned int *) (BUMEM | (*(unsigned int *)(BUREG | BUCMDSTACKPOINT))); blk = RT_ReadReg(RT_BASE_ADDR,(BUCMDSTACKPOINT)*4); XGpioPs_WritePin(&Gpio, MEMCTR, 0x1); BUMSG.blockStatusWord = MEM_Read(RT_RAM_BASE,blk*4); xil_printf("blockStatusWord is 0x%x\r\n",BUMSG.blockStatusWord ); //BUMSG.timeTagWord = *(unsigned int *) ((BUMEM | (*(unsigned int *)(BUREG | BUCMDSTACKPOINT))) + 1); BUMSG.timeTagWord = MEM_Read(RT_RAM_BASE,(blk+1)*4); //BUMSG.dataBlockPointer = *(unsigned int *) (BUREG | BURTDATASTACKADDR); xil_printf("timeTagWord status is 0x%x\r\n",BUMSG.blockStatusWord ); BUMSG.dataBlockPointer = MEM_Read(RT_RAM_BASE,(blk+2)*4); xil_printf("data block pointer is 0x%x\r\n",BUMSG.dataBlockPointer); // BUMSG.commandWord = RT_ReadReg(RT_BASE_ADDR,(blk+3)*4); // xil_printf("commandword1 is 0x%x\r\n",BUMSG.commandWord); XGpioPs_WritePin(&Gpio, MEMCTR, 0x0); // BUMSG.dataBlockPointer = RT_ReadReg(RT_BASE_ADDR,(BURTDATASTACKADDR)*4); // xil_printf("data block pointer2 is 0x%x\r\n",BUMSG.dataBlockPointer); //BUMSG.commandWord = *(unsigned int *) (BUREG | BURTLASTCMD ); BUMSG.commandWord = RT_ReadReg(RT_BASE_ADDR,(BURTLASTCMD)*4); xil_printf("receive commandword is 0x%x\r\n",BUMSG.commandWord); /***************************************************************************************************/ BUMSG.remoteTerminalAddr = (BUMSG.commandWord >> 11) & 0x1f;//远程终端地址 BUMSG.tr = (BUMSG.commandWord >> 10) & 0x01;//(=0收=1发) BUMSG.subAddModeCode = (BUMSG.commandWord >> 5) & 0x1f;//字地址/方式指令 BUMSG.dataCntModeCode = (BUMSG.commandWord ) & 0x1f;//数据字指令/方式指令 // xil_printf("BUMSG.dataCntModeCode is %x\r\n",BUMSG.dataCntModeCode); if(BUMSG.tr == BURX)//表示接受 { memset(BUMSG.data,0,sizeof(BUMSG.data)); // for(i = 0; i < BUMSGDATANUM; i++) // { // BUMSG.data[i] = BUZERO; // xil_printf("%x\r\n",BUMSG.data[i]); // } if(!BUMSG.dataCntModeCode) tempVar = BUMSGDATANUM; else tempVar = BUMSG.dataCntModeCode; xil_printf("length is 0x%x\r\n",tempVar); for(i = 0; i < tempVar; i++) { XGpioPs_WritePin(&Gpio, MEMCTR, 0x1); // BUMSG.data[i] = *(unsigned int *)((RT_RAM_BASE | (BUMSG.dataBlockPointer) + i)*4) & 0xffff;//要改 BUMSG.data[i] = MEM_Read(RT_RAM_BASE,(BUMSG.dataBlockPointer+i)*4);// xil_printf("0x%x\r\n",BUMSG.data[i]); } } if(BUMSG.tr == BUTX) { memset(BUMSG.data,0,sizeof(BUMSG.data)); for(i = 0; i < 32; i++) { XGpioPs_WritePin(&Gpio, MEMCTR, 0x1); MEM_Write(RT_RAM_BASE,(BUMSG.dataBlockPointer+i)*4,(0x001+i)); BUMSG.data[i] = MEM_Read(RT_RAM_BASE,(BUMSG.dataBlockPointer+i)*4); xil_printf("0x%x\r\n",BUMSG.data[i]); } } } }
很明显可以看到 对于方式指令什么的好像也没做什么什么处理,RT—RT啊广播啊什么的也没有做,好像只是做了BC-RT和RT-BC的收发,实际上方式指令这部分在memory的初始化那块做了配置,只是RT-RT和广播这些,只能发送一次初始化后的设置的数据字了,发送完一次后memory的值会改变,嗯只能暂时当做一次性用品了,直接除了收发都else为发送的数据字有点不太严谨,后续在修改吧,反正,嗯反正好像一般也不怎么用吧?先偷个懒,有需要再继续深入研究吧(懒腰)。
五.测试记录
串口每行打印以下信息
第一行:中断状态标志寄存器的bit0,为1表示进入中断
第二行:配置寄存器#1的值,检查和预设是否一致
第三行:判断channelAB,由于LHB155304的特殊性,,该值不可取,可忽略此打印
第四行:RT的块状态字信息
第五行:RT的时间标志字
第六行:数据块指针,也就是存放数据字的memory地址
第七行:接收到来自BC的指令字
第八行:表示数据字的长度
第九行往后表示数据字的内容
RT-BC消息
BC端设置RT-BC的指令,RT地址为20,子地址为1,我们的RT设备会将初始化好的0001—0020的数据字发送至BC,在我们本地接调试串口的话会打印发送信息,最直观的方法是在BM设备中观察消息记录,BC每运行一次消息执行一次
Msg:1 TimeTag:(053):16:53:01.685.158.975 Bus:A RT->BC Cmd1=<A420> RT20 TX SAO1 WC32 Rsp=2.375 us 0001 0002 0003 0004 0005 0006 0007 000809 OOA OOOB OOOC OOOD OOE OOF O10011 0012 0013 0014 0015 0016 0017 001819 1A 01B OO1C OO1D OIE 1F 20 StatusWord:A000 MessageTime:680.375us Msg:2 TimeTag:(053):16:53:03.549.160.512 Bus:A RT->BC Gap:1863619 13 Cnd1=<A420> RT20 TK SA01 WC32 Rsp=2.375 us 0001 0002 0003 0004 0005 0006 0007 000809 O00A 000B OO0C OOOD OOOE OOOF 0O10011 0012 0013 0014 0015 0016 0017 00180019 0014 001B 001C 001D 001E 001F 0020 StatusWord:4000 MessageTime:680.375us EMsg:3 TimeTag:(053):16:53:06 221 161 937 Bus:A RT->BC Ga0:2671813 13 Cmd1=<A420> RT20 TX SAO1 WC32 Rsp=2.375 us 0001 0002 0003 0004 0005 0006 0007 00080009 000A 000B 0OOC OOOD OOOE OOOF 00100011 0012 0013 0014 0015 0016 0017 00180019 001A 001B 001C 001D OO1E 001F 0020 StatusWord:4000 essageTime:680.375us Msg:4 TimeTag:(053):16:53:08.950.160.662 Hx--1024 Bus:A RT->BC Gap:2727795 us
如图所示BM设备将会显示收到的数据字和下发的命令字A420,RT地址20,子地址01,数据长度为32,RT设备返回的状态字为A000,无异常(最低位为1为异常等)串口打印信息如下:
tempVar is 0x1 cfg1 is x8F80 charnelAB is x blockStatusWord is 0x8000 timeTagWord status is x686A data block pointer is 0x400 receive commandword is xA4200x10x2 Ox3 x4 x5 x6 Ox 7 x8 x9 xA xB OxC xD OxE OxF0x10 x110x120x130x14 x15 x16 x170x18 x19 x1A x1B0x1C x1D x1E x1F x20 Hx--1024
BC-RT消息
BC端设置BC-RT消息,RT地址仍为20,我们设置了三种存储管理方式的子地址07 19 30 分别测试
子地址7 1024 字循环缓冲存储管理模式
&emspBC端注入数据字1111,长度为1依旧运行3次BC,循环缓冲存储的memory每次其实是不一样的,datablock的指针分别指向了0x800,0x801,0x802可以参考串口部分打印信息
Msg:1 TimeTag:(053):16:01:14.929.165.675 Bus:A BC->RT Cmd1=<AOE1> RT20 RK SAOT WCOI Rsp=2.5 us1111 StatusWord:A000 MessageTime:60.5us Msg:2 TimeTag:(053):16:01:17.250.160.087 Bus:A BC->RT Gap:2319732 18 Cmd1=<AOE1> RT20 RK SAOT WCOI Rsp=2.5 us1111 StatusWord:A000 MessageTime:60.5us Msg:3 TimeTag:(053):16:01:21.194.159.487 Bus:A BC->RT Gap:3943960 us Cmd1=<AOE1> RT20 RK SAOT WCO1 Rsp=2.5 us1111 StatusWord:A000 MessageTime:60.5us Hx--1024
tempVar is x1 cfg1 is x8F80 channelAB is x0 blockStatusWord is 0x8000 timeTagWord status is 0x4C90 data block pointer is x800 receive commandword is xAOE1 length is 0x1 x1111 tempVar is 0x1 cfg1 is x8F80 channelAB is x0 blockStatusWord is x8000 timeTagWord status is 0xEE53 data block pointer is x801 receive commandword is 0xAOE1 length is 0x10x1111 tempVar is 0x1 cfg1 is x8F80 channelAB is x0 blockStatusWord is 0x8000 timeTagWord status is xD869 data block pointer is x802 receive commandword is xAOE1 length is 0x1 x1111 Hx--1024
子地址19 采用双缓冲存储管理模式
BC设置发送长度为2,内容为1111,2222,设置RT地址为20,子地址为19,运行3次,datablock的指针指向了0x440和0x460循环
Msg:1 TimeTag:(053):15:56:58.166.159.362 Bus:A BC->RT Cmd1=<A262> RT20 RX SA19 WCO2 Rsp=2.5 us1111 2222 StatusWord:A000 MessageTime:80.5us Msg:2 TimeTag:(053):15:56:59.166.159.762 Bus:A BC->RT Gap:999794 us Cmd1=<A262> RT20 RX SA19 WCO2 Rsp=2.5 us1111 2222 StatusWord:A000 MessageTime:80.5us Msg:3 TimeTag:(053):15:57:02.773.177.787 Bus:A BC->RT Gap:3608123 us Cmd1=<A262> RT20 RX SA19 WCO2 Rsp=2.5 us1111 2222 StatusWord:A000 MessageTime:80.5us Hx--1024
子地址30 采用单消息存储管理
BC设置发送长度为3,内容为1111,2222,3333设置RT地址为20,子地址为30,运行3次,数据字均存放在memory的固定地址也就是预设的0x480
Msg:1 TimeTag:(053):16:02:09.170.159.925 Bus:A BC->RT Cmd1=<A3C3> RT20 RX SA30 WCO3 Rsp=2.5 us 1111 2222 3333 StatusWord:A000 MessageTime:100.5us Msg:2 TimeTag:(053):16:02:10.907.160.500 Bus:A BC->RT Gap:1735725 us Cmd1=<A3C3> RT20 RX SA30 WC03 Rsp=2.5 us 1111 2222 3333 StatusWord:A000 MessageTime:100.5us Msg:3 TimeTag:(053):16:02:13.234.164.987 Bus:A BC->RT Gap:2327937 us Cmd1=<A3C3> RT20 RX SA30 WCO3 Rsp=2.5 us 1111 2222 3333 StatusWord:A000 MessageTime:100.5us Hx--1024
tempVar is 0x1 cfg1 is x8F80 channelAB is x0 blockStatusWord is x8000 timeTagWord status is xEOBB data block pointer is x480 receive commandword is xA3C3 length is x3 Ox1111 x2222 x3333 tempVar is 0x1 cfg1 is x8F80 charnelAB is x0 blockStatusWord is 0x8000 timeTagWord status is xBB48 data block pointer is x480 receive commandword is xA3C3 length is 0x30x1111 x2222 x3333 tempVar is x1 cfg1 is x8F80 charnelAB is x blockStatusWord is 0x8000 timeTagword status is 0xBEE5 data block pointer is 0x480 receive commandword is xA3C3 length is 0x3 x1111 x2222 0x3333 Hx--1024
RT-RT消息
验证通过上位机软件模拟个RT地址为19的模拟RT,和本机(20)测试,结果如下
Msg:1 TimeTag:(053):16:58:34.875.164.850 Bus:A RT->RT Cmd1=<9820> RT19 RX SAO1 WC32 Rsp=2.5 us Cmd2=<A420> RT20 TX SAO1 WC32 Rsp=4.375 us 0001 0002 0003 0004 0005 0006 0007 00080009 000A 000B 000C OOOD 0OOE 0OOF 00100011 0012 0013 0014 0015 0016 0017 00180019 001A 001B 001C OO1D OOIE 001F 0020 StatusWord:A000 StatusWord:9800 MessageTime:722.875us Msg:2 TimeTag:(053):16:58:39.243.161.462 Bus:A RT->RT Gap:72590 us Cmd1=<9820> RT19 RX SAO1 WC32 Rsp=2.375 us Cmd2=<A420> RT20 TX SAO1 WC32 Rsp=4.375 us 0001 0002 0003 0004 0005 0006 0007 0008 O009 000A 00OB OOOC OOOD OOOE OOOF 0O100011 0012 0013 0014 0015 0016 0017 00180019 001A 001B 001C 001D 001E 001F 0020 StatusWord:A000 StatusWord:9800 MessageTime:722.75us Msg:3 TimeTag:(053):16:58:42.731.159.637 Bus:A RT->RT Gap:3487776 us Cmd1=<9820> RT19 RX SAO1 WC32 Rsp=2.375 us Cmd2=<A420> RT20 TX SAO1 WC32 Rsp=4.375 us Hx--1024
广播的RT-RT同样
aMsg:1 TimeTag:(053):17:03:38.416.185.937 Bus:A RT->RT Cmd1=<F820> RT31 RX SAO1 WC32 Rsp=2.5 us Cmd2=<A420> RT20 TX SAO1 WC32 0001 0002 0003 0004 0005 0006 0007 000800091 OOOA OOOB OOOC OOOD OOOE OOOF OO100011 0012 0013 0014 0015 0016 0017 00180019 001A 001B 001C 001D 001E 001F 0020 StatusWord:A000 MessageTime:700.5us 日Msg:2 TimeTag:(053):17:03:42.400.159.337 Bus:A RT->RT Gap:3983718 us Cmd1=<F820> RT31 RX SAO1 WC32 Rsp=2.5 us Cmd2=<&420> RT20 TX SA01 WC32 0001 0002 0003 0004 0005 0006 0007 00080009 000A 000B 000C OOOD 0OOE 00OF 00100011 0012 0013 0014 0015 0016 0017 00180019 001A 001B 001C 001D 0O1E 001F 0020 StatusWord:A000 MessageTime:700.5us 日Msg:3 TimeTag:(053):17:03:45.904.159.937 Bus:A RT->RT Gap:3503596 us Cmd1=<F820> RT31 RX SAO1 WC32 Rsp=2.5 us Cmd2=<&420> RT20 TX SA01 WC32 0001 0002 0003 0004 0005 0006 0007 00080009 O00A 00OB OOOC OOOD OOOE OOOF 00100011 0012 0013 0014 0015 0016 0017 00180019 001A 001B 001C 001D 0O1E 001F 0020 StatusWord:A000 Hx--1024
方式指令
测试如下,选取发送自检测字方式指令,发送上一个状态字和发送上一个指令字
aMsg:1TimeTag:(053):17:06:18.443.160.362 Bus:a Mode Code Cmd1=<A413> RT20 TX SAOO WC19 发送自检测字 Rsp=2.5 us0000 StatusWord:A00O MessageTime:60.5us Msg:2 TimeTag:(053):17:07:07.868.159.937 BusA Mode Code Gap:2178754 us Cmd1=<A402> RT20 TX SAOO WCO2 发送上一状态字 Rsp=2.375 us StatusWord:A00O MessageTime:40.375us 日Msg:3 TimeTag:(053):17:07:19.763.165.850 Bus:A Mode Code Gap:3305894 us Cmd1=<A412> RT20 TX SAOO WC18 发送上一指令字 Rsp=2.375 us A402 StatusWord:A000 MessageTime:60.375us Hx--1024
暂时先测了这几种消息,其余的有需要在进行测试吧