灵动微电子 · 2023年07月27日

CAN总线开发一本全(3) - 微控制器集成的FlexCAN外设

  • 引言
  • 硬件外设模块
  • 系统概要
  • 总线接口单元 - 寄存器清单
  • 数据结构 - 消息缓冲区MB
  • 初始化过程
  • 接收过程Rx、Rx FIFO及帧过滤机制Filter
  • 发送过程Tx和仲裁机制winner
  • 总结
  • 参考资料

引言

集成在微控制器芯片中的CAN总线通信引擎的外设电路系统,有一些典型的实现,例如飞思卡尔半导体(已并入恩智浦半导体)的ColdFire系列微控制器中用到的MSCAN和Kinetis系列微控制器的FlexCAN(由Silvaco International公司设计),这些CAN总线通信引擎在汽车电子应用中已经被广泛使用,用以实现内存中的数据与CAN总线上串行信号的的相互转换。灵动微电子设计生产的MM32F0140和MM32F5系列微控制器芯片也集成了FlexCAN外设模块。本文以MM32F0140 / MM32F5270 微控制器芯片上集成的FlexCAN作为CAN硬件外设模块的实例,讲述硬件的CAN通信引擎的工作方式,以此展现硬件电路系统对CAN总线控制逻辑的建模,建立起软件系统同硬件电路的关联关系。同本系列的其它文章一样,本文希望以尽量简洁的语言,关注基本的原理和常用的功能,建立起对常规CAN外设模块的概念,为后续适配CAN通信协议栈的软件包做好准备。

硬件外设模块

系统概要

FlexCAN外设模块是CAN总线通信的协议引擎,通过一个非常灵活的邮箱管理系统(消息缓冲区MB)管理发送和接收CAN通信帧。邮箱管理系统由一组消息缓冲区Message Buffer组成,MB中存放了通信帧的配置信息、数据负载、时间戳、消息ID等。完整的FlexCAN外设,在MB队列中的前38个MB可以配置成FIFO模式,配合一个功能强大的ID过滤机制,可以将总线上捕获到的输入帧同一个ID过滤器表的项目进行匹配(多达128个扩展ID,或者256个标准ID,或者512个8位的ID片段),并且可以在独立掩码寄存器中选择多达32个ID过滤器表项。

同时使用FIFO和独立消息邮箱(单通道)接收帧亦是可行的。使用消息邮箱接收帧,就是将选定的MB同ID固定的消息ID绑定后,该MB仅能接收固定消息ID的通信帧,使用ID掩码机制的情况下,可以将匹配一个范围的ID。

在执行发送帧或者接收帧之前,这里需要强调一个很重要的概念,当说明一个MB处于激活(Active)状态时,在意味着它正在参与发送过程的仲裁或是接收过程中的匹配。此处的激活状态,其实就意味着这个MB当前正被FlexCAN外设或CPU占用,它是不可操作的。

FlexCAN外设模块内部包含总线接口单元、发送机构(包含仲裁)、接收机构(包含匹配)、消息缓冲区,以及协议引擎,有功能框图如图x所示。

image.png
图x FlexCAN的系统框图

CPU通过外设总线访问FlexCAN的寄存器,与FlexCAN外设进行交互,除了通过寄存器配置FlexCAN模块的多种工作模式及反馈信息外,CPU主要是向MB(消息缓冲区)中写入CAN通信帧的数据内容。消息缓冲区的存储块中包含多个MB,每个MB对应一个CAN通信帧内容的数据结构,并且可分别配置为将要发送帧的MB或是准备接收帧的MB。当要发送帧时,先将CAN发送帧的内容(包括帧ID、数据负载等)按照MB的存储结构填充到特定的字段,然后配置MB中的CODE字段为发送命令,则协议引擎PE会自动启动发送操作过程,包括自动同总线上的其他设备进行仲裁,以及在超过连续5个同电平位之后自动翻转等。当要接收帧时,需要从多个帧接收过滤器中拿出一个,设定需要匹配接收帧的ID(或者一个范围),并为之绑定一个存放将要匹配到的CAN通信帧数据内容的MB,之后协议引擎PE会监控CAN总线上的信号流,当遇到匹配ID范围内的通信帧,就存下来到预先准备好的MB。发送和接收完成后,协议引擎都会通过寄存器接口向CPU传达状态的变化,产生中断触发进一步的数据搬运过程。

PS:CAN总线对CAN通信帧进行仲裁时,不是以发送通信帧或接收通信帧的CAN总线设备本身作为获得仲裁优先级的评判依据(CAN节点不参与仲裁),而是以CAN通信帧的ID标识符作为获得仲裁的依据(值越小,优先级越高)。类似的概念还存在于以太网应用中IP主机和端口号的关系,应用程序最终是在端口的层面上进行通信,而不仅仅是拥有IP地址的主机。所以,当某一个CAN节点设备可以收纳多个ID的CAN通信帧时,意味着这个节点设备在CAN总线通信系统中可以被抽象成多个节点。但实际上,在后续介绍的CAN总线通信协议中可以看到,不同的ID将对应总线系统中不同的服务,总线系统中总有一个响应服务的线程,可能位于某个节点设备的某一个ID过滤器之后被实现。

总线接口单元 - 寄存器清单

FlexCAN外设模块的总线接口单元以存储空间中的寄存器作为操作界面,可由CPU通过外设总线访问到FlexCAN外设模块内部。虽然不建议开发者通过直接读写外设模块寄存器的方式对FlexCAN外设模块进行开发,因为直接操作寄存器实在是一件繁琐并且容易出错的过程,但本文在这里仍然将FlexCAN外设模块的寄存器清单列写出来,让读者一览FlexCAN外设模块为软件系统开放的应用接口。FlexCAN外设模块的寄存器如表x所示。

表x FlexCAN外设模块寄存器清单

image.png
image.png

数据结构 - 消息缓冲区MB

FlexCAN外设地址空间的0x0080 - 0x017F之间的地址,被映射到RAM中,用于存放MB的数据结构,每个MB占用连续的16个字节,总共16个MB。这些MB将用于存放即将向CAN总线发送的帧数据内容,软件需要先把数据填充到MB中再启动发送工程;或者从CAN总线上捕获的CAN数据内容,之后软件就可以从MB中读到接收帧的信息。MB在存储空间中的数据结构,如图x所示。

image.png
图x MB消息缓冲区结构

其中各字段功能为:

  • CODE (Message Buffer Code):CPU和FlexCAN外设都可能向这个字段写命令。当CPU向CODE字段中写数,用于向FlexCAN外设配置发送和接收的过程;当FlexCAN外设向CODE字段中写数,用于告知CPU当前发送或接收过程已经完成或者正在进行的状态。关于具体的各种命令以及对应的操作和状态,可进一步参见芯片手册中的表格说明(Table 50-5 & Table 50-6)。
  • SRR (Substitute Remote Request),仅用于扩展帧。当表示扩展帧时,必须置1。
  • IDE (ID Extended Bit):标记是否为扩展帧,1表示扩展帧,0表示标准帧。
  • RTR (Remote Transmission Request):设定或表示当前MB中是否为远程请求帧,1表示远程帧,0表示数据帧。
  • DLC (Length of Data in Bytes):发送和接收帧中的数据长度,0表示没有。有效值为1到8。当接收通信帧时,FlexCAN协议引擎会从接收到的帧中提取有效数据填充到数据字段,并复制接收帧的DLC值到MB的DLC字段中。当发送通信帧时,在总线上发送通信帧的字节流时,若DLC小于8,则实际数据负载的字节流长度亦会对应缩短,而不会填充空位。当RTR=1,即发送远程帧时,此时发送数据字段中无有效内容,将会忽略DLC中的值(等价于DLC=0)。
  • TIMESTAMP (Free-Running Counter Time Stamp):接收帧时本机填入时间戳,用于本机处理多个MB中的接收帧时判断先后时序。这个字段将由FlexCAN的协议引擎自动填充,从CAN_TIMER寄存器中复制过来。
  • PRIO (Local Priority):对本机多个MB的发送帧执行仲裁(而不是总线上的设备,CAN总线对设备没有优先级的概念),使用唯一的发送引擎按优先级逐个发送。这个字段的值不会被发送到CAN总线上,可以被附加到常规的ID后面,作为一个配置项,当CAN_MCR[LPRIO_EN]=1时生效,仅作用于发送过程中的多个MB之前进行排序。
  • ID (Frame Identifier):在标准帧的格式中,只用到收发通信帧的高11位(28b - 18b),后续的低18位被忽略。当使用扩展帧时,整个29位的字段全部用于表示通信帧的ID。话说,标准帧和扩展帧的区别就在于ID字段的位数,扩展帧使用更多位的ID,可以在总线系统中表示更多的通信帧类型。
  • DATA Byte 0-7(Data Field):通信帧的有效数据负载。最多8字节,同DLC字段描述的数据字节数对应。当为发送帧时,由CPU写入数据到本字段,供FlexCAN引擎发送到总线上;当为接收帧时,FlexCAN的协议引擎会在总线上捕获到数据帧后,自动复制值到本字段,供CPU读取。

CAN总线标准帧同MB消息缓冲区的有一一对映关系,如图x所示。

image.png
图x CAN总线标准帧同MB消息缓冲区的一一对映

CAN总线扩展帧相对于标准帧,多了SRR的字段,但仍同MB消息缓冲区有一一对映的关系,如图x所示。

image.png
图x CAN总线扩展帧同MB消息缓冲区的一一对映

初始化过程

FlexCAN外设的工作周期从复位状态开始,可以由如下两种情况触发复位过程:

  • 芯片硬件复位,此时包括FlexCAN外设模块在内的所有寄存器都将被复位
  • 配置CAN_MCR[SOFTRST]寄存器位,这会复位FlexCAN中的部分配置寄存器。当软件向CAN_MCR[SOFTRST]寄存器位写1时,向FlexCAN外设模块发出复位请求,当FlexCAN外设模块执行复位操作后,会将这一寄存器位清零,因此软件可通过轮询这个标志位在置1后是否清零,判定内部软复位是否完成。

之后,对FlexCAN模块进行配置。但要注意,任何对FlexCAN外设的配置操作,都需要在FlexCAN外设的冻结模式下才能完成。

一般的初始化FlexCAN外设模块的过程如下:

  1. 写CAN_MCR寄存器,配置FlexCAN引擎的工作模式。
  2. 写CAN_CTRL1和CAN_CBT寄存器,配置FlexCAN的CAN时钟位时间。
  3. 初始化MB列表。MB映射的内存区是带ECC的,需要先写入初值才能正常使用。如果启用了Rx FIFO模式,还必须配置好ID过滤器表。
  4. 写CAN_RXIMRn寄存器。
  5. 写CAN_IMASK寄存器,启用必要的中断。
  6. 将CAN_MCR[HALT]寄存器清零,退出冻结模式。

退出冻结模式之后,FlexCAN外设模块开始同CAN总线同步,接入总线网络。

接收过程Rx、Rx FIFO及帧过滤机制Filter

相对于默认的将每个MB作为一个单独的通道,一帧一帧地接收并处理数据,FIFO模式可以将几个MB的存储空间组织成一个FIFO,FIFO可以缓存更多的帧,在CPU提供同等算力的情况下,提升节点设备的处理CAN总线通信帧的动态吞吐率。

数据结构

当配置CAN_MCR[RFEN]=1时,启用Rx FIFO模式,此时,原MB列表的部分MB存储区域(MB0 - MB5,模块内偏移地址为0x80 - 0xDC的内存区域)将合并成Rx FIFO,由FIFO引擎管理。其中,原MB0的作为CPU访问Rx FIFO的接口,CPU始终可以从原MB0的位置读到最早进入FIFO的帧信息。此时,Rx FIFO的区域为只读模式,复位缺省值为0x00。

另外,还可以通过配置CAN_CTRL2[RFEN]=1,启用Rx FIFO的另一段区域,这个FIFO对应于原MB6 - MB15的区域(模块内偏移地址为0xE0 - 0x17C的内存区域,将用于存放Rx FIFO的ID过滤器表,只有通过ID过滤器表中的表项匹配的CAN通信帧才能被捕获进入Rx FIFO。ID过滤器表可能有多种模式(匹配不同的位数),可被配置为8至40个表项。复位FlexCAN外设模块后,ID过滤器表的内存区域的默认为从0xE0至0xFC,对应使用原MB6和MB7的空间,同未开启Rx FIFO模式的配置兼容。图x展示了Rx FIFO的数据结构。

image.png
图x FlexCAN Rx FIFO数据结构

其中,每个ID过滤器表项(ID Filter Table element)占用32位字的空间,可以被分成1个32位、2个16位或4个8位的匹配接收掩码(IDAF,Identifier Acceptance Filters),这需要在CAN_MCR[IDAM]寄存器中设置。图x中展示了这种可能使用多种格式分割ID过滤器表项的格式,但要特别注意,一旦选定一种格式,所有的ID过滤器表项都会使用同一种格式。

image.png
图x FlexCAN ID过滤器表项的格式

其中,各配置字段的含义如下:

  • RTR (Remote Frame):指定能否捕获匹配ID的远程帧。1指定可以捕获,0指定不捕获。
  • IDE (Extended Frame):指定能否捕获匹配ID的扩展帧。1指定可以捕获,0指定不捕获扩展帧,仅捕获标准帧。
  • RXIDA/B/C (Rx Frame Identifier with Format A/B/C):指定匹配的ID模式,当不满足完整的帧ID时,仅匹配帧的高位。

FIFO中MB结构中多出来的IDHIT (Identifier Acceptance Filter Hit Indicator):表示当前的MB匹配到了哪个ID过滤器。

功能描述

Rx FIFO将6个MB的内存空间整合成一个FIFO,使用FIFO引擎管理先后收到的数据帧。相对于老式的单独管理各个MB,FIFO模式对DMA应用比较友好,并且可以提升从CAN总线上捕获帧的动态吞吐率。

CAN_IFLAG1[BUF5I]标志位,表示Rx FIFO中已经捕获到有效的数据帧,可供CPU读取。这个标志位也可以触发中断,CPU在中断服务程序中读取Rx FIFO的内容后,FlexCAN外设会更新FIFO状态寄存器CAN_RXFIR的值,然后自动清中断标志。如果Rx FIFO中有多个有效的数据帧,则CAN_IFLAG1[BUF5I]会持续置位,触发CPU处理接收帧的过程,直到Rx FIFO中捕获的通信帧全部被读走。

CAN_IFLAG1[BUF6I]标志位,表示Rx FIFO达到警告门限,此时Rx FIFO中已经积压了4个MB(从5个MB读走1个后剩下4个MB的时机),此时意味着Rx FIFO几乎要满到溢出了。这个标志位需要CPU清除。

CAN_IFLAG1[BUF7I]标志位,表示Rx FIFO已经满溢,此时Rx FIFO中已经积压了6个未读的MB,并且有一个新的CAN通信帧被捕获下来。这个标志位需要CPU清除。

CAN_IFLAG1[BUF0I]标志位,可用于清空Rx FIFO。当CPU向该标志位写1时,直接清空Rx FIFO。但这个功能仅在冻结模式下使用,这就意味着,用户不要试图在FlexCAN正常工作的情况下清空Rx FIFO(可以软件读掉Rx FIFO中的数据),这个功能大多用于改变全局配置时,重新初始化FlexCAN模块时使用。

FlexCAN模块中设计了功能强大(略显复杂)的帧过滤器模式,可以由硬件自动过滤掉很多本设备处理不了的帧,这就节约了很多原本需要在接收中断服务程序中判断捕获帧是否能在本机处理的过程。FlexCAN可以同时匹配众多的ID帧标识符,128个Format A格式的IDAF,或者256个Format B格式的IDAF,或者512个Format C格式的IDAF。每个捕获到Rx FIFO中的接收帧都有一个对应的IDHIT,指示它匹配到的过滤器的索引编号,CAN_RXFIR[IDHIT]寄存器字段中也能查看最近捕获的接收帧的IDHIT值。此时,需要在清接收标志之前读CAN_RXFIR寄存器,以确保存放在CAN_RXFIR寄存器中的值不会被后面捕获到帧覆盖掉。

当配置CAN_CTRL2[RFEN]=1时,启用过滤器表,过滤器表中最多可以有16个表项,可以由独立掩码寄存器CAN_RXIMRx分别配置。当CAN_MCR[IRMQ]=0时,过滤器表由CAN_RXFGMASK寄存器配置。

接收过程

为了能让FlexCAN从CAN总线上捕获到通信帧,CPU(软件)需要准备一些工作:

  • 如果选定的MB处于激活状态,正在发送或接收,要么等等,要么强行终止,确保MB处于一个可用的非激活状态
  • 向MB中写入希望捕获通信帧的ID值。
  • 向MB的CODE字段中写入EMPTY(0b0100),激活接收过程。

当MB被激活后,它将会接收到通过ID过滤器匹配的通信帧。

当接收过程成功完成后,FlexCAN外设通过搬运过程将捕获到的通信帧从CAN通信引擎的缓冲中转运至MB中:

  • 接收到通信帧的数据(8字节)将被存放至MB的DATA字段。
  • 接收到的ID将被存放至MB的ID字段。
  • 接收时刻的定时器CAN_TIMER寄存器的值将被写入到MB的时间戳字段中。
  • MB中的SRR、IDE、RTR和DLC字段将被更新。
  • MB中的CODE字段中的状态将被更新。
  • CAN_IFLAG1中的接收中断标志位将会置位,如果在CAN_IMASK1寄存器中启用了对应的中断,也将会触发中断。

因此,建议CPU(软件)在读取CAN接收帧时,遵循如下步骤:

  • 先读一下对应MB的状态位,再看一下BUSY标志位是否置位,若置位,意味着MB被锁着,先等一等。
  • 从MB中读数据。但如果MB被锁着,MB中的数据实际是无效的。
  • 清IFLAG标志位。
  • 读时间戳。

建议当收到CAN接收帧时,尽快把收到的帧读走,解锁MB,为后面接收的帧释放空间。

特别注意的是,在CPU通过轮询过程查看FlexCAN‘释放捕获到接收帧的过程中,应当以CAN_IFLAG1寄存器中的标志位来判定,而不是MB中CODE字段的状态码。读CODE状态码是没有意义的,因为一旦FlexCAN收到通信帧后被CPU读走,CODE不会变为EMPTY,而是仍保持为FULL,需要CPU人为清空。

若是使用FIFO模式,CPU需要在FlexCAN的冻结模式下配置启用Rx FIFO模式,再次启用FlexCAN通信引擎后,FlexCAN将以Rx FIFO模式捕获CAN通信帧:

  • 读CAN_IFLAG中的Rx FIFO的接收标志位
  • 读Rx FIFO头部MB的接收帧ID
  • 读Rx FIFO头部MB的数据负载(8字节)
  • 读CAN_RXFIR寄存器
  • 写1清Rx FIFO捕获到有效帧的标志位CAN_IFLAG[BUF5I]。

Rx FIFO对使用DMA的场景更友好。但目前的ECU系统中,因为附加了协议栈和大量的软件干预,所以实际使用DMA的并不多。如果需要,也可以参见芯片用户手册的相关说明。

发送过程Tx和仲裁机制winner

发送过程

当要发送一个CAN通信帧,CPU需要选出一个MB,然后执行如下的步骤:

  • 查看当前CAN通信引擎是否正忙,如果正忙就等一等,或者通过硬件机制终止通信过程。是否有之前通信过程的遗留标志位,如果有就清零。务必确保CAN通信引擎恢复成初始状态:
  • 确保发送中断和接收中断都是停用的。
  • 如果选用的MB是激活的(Active),正在被占用,可以通过向该MB的CODE字段中写入ABORT命令字(0b1001)终止通信过程。
  • 通过轮询CAN_IFLAG寄存器中对应的IFLAG标志位置位,或者启用中断触发,等待MB转入非激活状态。
  • 再读MB的CODE字段,确认发送过程已经被中断或者完成。
  • 清除对应的中断标志位。
  1. 向MB中写入通信帧:
  • 写入消息ID。如果通过配置CAN_MCR[LPRIO_EN]=1寄存器启用了本地优先级配置,还需要一并写入PRIO配置字段。
  • 写入数据负载。最多8个字节的数据。
  • 配置发送属性,包括:IDE、RTR、DLC。
  • 在CODE字段中写入激活命令码,对应发送帧,CODE=0xC。

当MB被激活之后,它被加入到FlexCAN外设的发送仲裁过程,根据本地优先级(若有),最终被发送到CAN总线上。

在发送过程成功完成后:

  • 定时器CAN_TIMER寄存器的时间戳将被写入到本MB的时间戳字段中。
  • CODE字段中的值将被FlexCAN外设更新。至于更新成什么状态,需要根据具体发送的情况确定。见表x所示。
  • 在CAN_IFLAG1寄存器中的发送完成中断标志位会置位,
  • 如果在CAN_IMASK1寄存器中启用了发送完成中断,那么对应的中断也会被触发。

注意,当通过CAN_MCR[AEN]启用了终止通信的功能后,当发送完整中断标志位置位时,此时MB是被锁住的,需要CPU清中断标志位后,才能再次访问MB,准备写入下一个新的通信帧。

仲裁过程

此处的仲裁过程并不是指CAN总线网络的仲裁机制,而是FlexCAN外设本身的多个通信通道(MB)争用同一个通信引擎发送至CAN总线上的过程。FlexCAN会扫描当前所有待发送的MB,然后根据特定的策略选出其中一个作为本次发送过程的MB。这个策略是可以通过寄存器配置的,如表x所示。

表x 配置发送仲裁优先级策略

image.png

关于仲裁的过程,还有更多的细节,例如,当某个MB被激活发送过程后,如果长时间得不到仲裁优先级,也将会产生一些报警,此时,判断超时和报警的机制,在FlexCAN外设模块上有一些具体的实现策略。这些内容可以根据具体问题具体分析,在遇到具体场景时,再查阅手册一一对症。此处就不做赘述了。

总结

本文描述了一个典型的CAN总线通信引擎FlexCAN外设模块的工作机制。FlexCAN总线以消息缓冲区MB作为数据缓冲单元,收发通信过程同典型的基本通信类引擎(例如UART)相似,但由于CAN总线以通信帧作为基本通信单元(包含ID和最多8个字节的数据负载),而不是基本通信引擎的单元数据,所以需要一个协议引擎,同步地在总线和MB之间搬运包含数据和状态的帧属性信息。CAN总线是一个多对多的网络,因此也引入了网络型通信引擎的问题,例如接收过程的目标地址(ID)匹配,和发送过程中的仲裁(冲突检测)。FlexCAN外设模块在硬件上也提供了对这些问题的解决方案,在接收过程中,设计了非常灵活的接收标识符过滤器组的机制;在发送过程中,设计了(在本地多个待发送MB之间的)本地优先级的机制,至于CAN总线网络上的仲裁,就依赖于网络本身的物理特性完成了。FlexCAN外设还增加实现了Rx FIFO的工作模式,可以将多个MB合在一起以FIFO的方式进行管理,使用FIFO可以提升FlexCAN外设在总线上的动态吞吐率,并且对DMA操作更加友好。本文对于FlexCAN内部机制的一些实现细节仅点到为止,未做详细的拆解,如果读者在具体应用中遇到具体问题,仍可参见芯片用户手册进行针对性阅读。

参考资料

Kinetis KE1xF Sub-Family Reference Manual

MM32F5270 用户手册(中文版)

作者:安德鲁苏
文章来源:安德鲁的设计笔记本

推荐阅读

更多MM32F5系列资料请关注灵动MM32 MCU专栏。如想进行MM32相关芯片技术交流,请添加极术小姐姐微信(id:aijishu20)加入微信群。
推荐阅读
关注数
6143
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息