NXP S32K3系列学习笔记:FlexCAN驱动开发实践

“点点的学习日记”

前言

一、FlexCAN是什么?

1.概括

2.  邮箱结构   

二、通信波特率设置

三、FlexCAN模块初始化

四、发送、接收与匹配过程

1. 发送过程

2. 接收过程

3. 匹配过程

五、特殊功能

1. 邮箱锁机制

2. MCR[SRXDIS] 自接收功能


前言

学习NXP S32K3系列芯片笔记,内容大多通过阅读官方RM手册与自我理解得出,小白笔记,如有错误请谅解。

一、FlexCAN是什么?

1.概括

        FlexCAN 模块是 CAN 协议的一个高完成度版本,带有动态数据率(Flexible Data rate,CAN FD)协议和 CAN 2.0 B 版本协议,支持标准和拓展数据帧和长达 64 字节的数据传输,频率最大可达到 8Mbps。数据缓冲器存在于中一个嵌入FlexCAN的 RAM 中。

上图为FlexCAN各模块关系,其功能如下:
        协议引擎Protocol Engine (PE)用于管理CAN总线上的串行通讯:请求RAM访问用于接收、发送消息帧;验证接收的消息;运行错误处理;探测CAN FD帧。
        控制器主机接口Controller Host Interface (CHI)用于管理接收、发送的消息缓存邮箱(Message Muffers),负责仲裁和ID匹配。
        总线接口单元Bus Interface Unit (BIU)用于控制访问内部总线,建立与CPU和其他模块的联系。包括时钟、寻址、数据总线、中断、DMA的访问都是通过BIU。

2.  邮箱结构   

        本文开发基于S32K344芯片,介绍下K344的资源,如下图所示,其具有6个CAN模块,均支持CAN FD。在传统模式下CAN0~CAN5分别具有96、64与32个邮箱。

邮箱结构如下:地址偏移0h~4h为CS控制字段,主要存储报文属性与邮箱状态CODE码。地址偏移4h~8h为ID字段,用于存储报文ID或设置接收邮箱的专用ID。

CODE —邮箱代码 代表该邮箱状态,由4位组成。可通过访问CODE段得知邮箱状态或操控邮箱。

EDL —扩展数据长度
该位用于区分CAN格式帧和CAN FD格式帧。对于配置为RANSWER的代码字段1010b的消息缓冲区,不能设置EDL位。
BRS —bit速率开关
该位定义了是否在CAN FD格式帧内切换码率。
ESI —错误状态指示
该位表示发送节点是错误主动还是错误被动。

二、通信波特率设置

        CAN模块进行通信需要相同的波特率才可以进行正常的通信。在CAN的底层协议里,CAN数据的每一位时间(CAN Bit Time)被分为若干份时间,其组成为:

位同步时间(Tsync)、时间段1(Tseg1 = PROPSEG + PSEG1 + 2)、时间段2(Tseg2 +1)

        位同步时间固定为1份,时间段1与时间段2可在一定范围内调整。

符合博世CAN 2.0B标准的位段设置范围如图所示:

 注意一点:在设置时间位段数量时,必须要确保位时间设置符合CAN协议标准(ISO 11898-1)。

        当确定了位段时间数量后,通过计算单位时间的长度Tq即可知道CAN单帧时间,进而可以得到波特率。CAN模块的时钟设置这里不再介绍。

Tq = \frac{PRESDIV + 1}{fCANCLK}

波特率设置公式如下:

CAN Bit Time = (Tsync + Tseg1 +Tseg2) * Tq

Baud = \frac{1}{ CAN Bit Time}

根据下图所示,SYNC+SEG+(PROP_SEG+PSEG1+2)+(PSEG2+1)就是总的Tq,因此FlexCAN 的波特率就是CAN时钟频率除以Tq的数量:

CAN Baud=\frac{f_{Tq}}{TqQuantity}

如上图所示,采样点位于 Tseg1与Tseg2之间。计算方式为:

\frac{Tsync + Tseg1}{Tsync + Tseg1 +Tseg2}*100%

例如,假设Tsync = 1,Tseg1 = 14,Tseg2 = 5。那么采样点为:

((1+14) / 20)*100% = 75%

部分配置代码:

	numPresDivUB = (CAN_NUM_BAUDRATE_FREQ/(20*numBRUI))-1;
	/*SYNCSEG[1] | 	  TSEG1[2,16]  	 |采样点| TSEG2[2,8]*/
	/*SYNCSEG	 | (PROPSEG+PSEG1+2) |采样点| (PSEG2+1)*/

	/* 该配置采样点约为75%位置 */

	infoCanRegPS->CTRL1 |= FLEXCAN_CTRL1_PSEG2(4);	/*TSEG2=5=4+1*/
	infoCanRegPS->CTRL1 |= FLEXCAN_CTRL1_PSEG1(5);	/*TSEG1=14=PROPSEG+PSEG1=7+5+2*/
	infoCanRegPS->CTRL1 |= FLEXCAN_CTRL1_PROPSEG(7);
	infoCanRegPS->CTRL1 |= FLEXCAN_CTRL1_PRESDIV(numPresDivUB);

三、FlexCAN模块初始化

        对于FlexCAN模块的设置,初始化或更改配置都需要将FlexCAN设置为Freeze模式。注意,每次重置后都需要初始化模块。
下面是FlexCAN模块的通用初始化步骤:
1. 初始化模块配置寄存器(MCR)。
        a. 通过设置IRMQ启用每MB单独过滤和接收队列特性。
        b. 通过设置WRNEN使能警告中断。
        c. 如果需要,可以通过设置SRXDIS来禁用帧自接收。
        d. 通过配置RFEN使能Legacy Rx FIFO,通过配置ERFEN使能Enhanced Rx FIFO
        e. 如果使能了Legacy Rx FIFO或Enhanced Rx FIFO且需要使用DMA,则需要设置DMA。
        f. 通过设置AEN使能终止机制。
        g. 通过设置LPRIOEN使能本地优先级特性。
2. 初始化控制1寄存器(CTRL1)和CAN位定时寄存器(CBT)。如果使用CANFD,还需要初始化CAN FD、CAN位定时寄存器(FDCBT):
        a. 确定位定时参数:PROPSEG、PSEG1、PSEG2和RJW。
        b. 可选择位定时参数:EPROPSEG、EPSEG1、EPSEG2、ERJW。
        c. 确定CAN FD位定时参数:FPROPSEG、FPSEG1、FPSEG2、FRJW。
        d. 通过编程PRESDIV字段和可选的EPRESDIV字段来确定比特率。
        e. 通过编程FPRESDIV字段确定CAN FD比特率。
        f. 确定内部仲裁方式(LBUF)。
3. 如果ECC (Error Code Correction)使能,必须初始化所有FlexCAN内存。
4. 初始化邮箱。
        a. 所有邮箱的CS字段必须初始化。
        b. 如果使能了Rx FIFO,则需要对ID过滤表进行初始化。
        c. 每个邮箱中的其他条目应根据需要初始化。
5. 初始化Rx单个掩码寄存器(RXIMRn)。
6. 设置所需的中断掩码位

        •IMASK寄存器 (用于所有邮箱中断)
        •CTRL1 / CTRL2寄存器 (用于总线断开和错误中断)
7. 将MCR(HALT)失能。
在完成上面的初始化步骤后,FlexCAN将会尝试同步到CAN总线。

四、发送、接收与匹配过程

1. 发送过程

要想传输一条消息,需要准备一个消息缓冲区(MB),然后执行以下步骤:

1. 检查相应的中断位是否设置,同时清除中断标志。
2. 检查邮箱是否为活动邮箱,如果邮箱是活动的,将中止代码(1001b)写入CODE字段,请求中止      该邮箱传输。
3. 等待相应的IFLAG位变化。再次读取CODE字段,检查确认传输是否被中止。
4. 清除相应的中断标志。
5. 向ID段寄存器写入ID。
6. 写入数据字节(DATA)。
7. 向CS字段写入控制配置。
        a. MB_CS[IDE]——设置报文ID。
        b. MB_CS[RTR]——设置远程传输请求帧(如果需要的话)。
        c. MB_CS[DLC]——设置数据长度,以字节为单位。
        d. MB_CS[CODE]——设置邮箱CODE字,激活邮箱并发送。

/* 在程序中,建议将CS字段中的所有配置只配置在一次32位写操作中,可以提高性能。如果是单独写入,CS[CODE]必须是C/S字中最后一个写入 */

当邮箱被激活时,它会参与仲裁过程,并最终根据它的优先级进行传输。在成功发送之后:
        运行计时器的值会被写入时间戳Time Stamp字段。
        更新CS字段中的CODE字。
        更新CRC和FDCRC寄存器
        在中断标志寄存器中设置中断标志。
        如果相应的中断掩码寄存器位允许,产生中断。

2. 接收过程

对于Can消息的接收,可以采用以下的方式完成消息接收功能,具体步骤如下:

1. 首先检查邮箱是是否为活动邮箱(CODE为0100b),若是活动邮箱需要将邮箱停用(CODE段置0000b),建议使用安全停用邮箱的方式进行停用。
2. 将ID字段写入邮箱。
3. 将EMPTY代码(0100b)写入邮箱CS字段中CODE位以激活邮箱。CS段内的EDL、BRS和ESI位不需要设置,它们会被接收到的CAN报文中各自对应的位字段覆盖掉。
4. 在邮箱被激活后,它将能够接收到与程序设置的滤波器(MASK)相匹配的帧。在成功接收结束时,邮箱将通过移入过程更新(由FlexCAN模块执行,此更新过程CODE[0]=1,CPU无法访问)。

当FlexCAN成功接收CAN消息并移入对应邮箱后,官方参考手册中建议的CPU处理(读取)邮箱接收到的帧的方法如下:
        a. 读取该邮箱的控制和状态字(CS字段)。
        b.检查BUSY位是否被取消(CODE[0]),表示邮箱被锁定。在中断时重复步骤1。
        c. 读取邮箱的内容。在邮箱被锁定后,邮箱内容将不会被FlexCAN的Move-in进程修改。
        d. 在IFLAG寄存器确认标志位状态。
        e. 读取空闲运行计时器以解锁邮箱。

3. 匹配过程

待补充

五、特殊功能

1. 邮箱锁机制

—–邮箱锁机制—–

        除了邮箱失活以外,FlexCAN还有另一种在接收过程中保护数据一致性的机制。当CPU读取如果一个接收邮箱(Rx MB)的CS字段中CODE代码为FULL或OVERRUN时。FlexCAN假设CPU想要在一个操作中读取整个MB。因此,它为该MB设置了一个内部锁标志。当CPU读取空闲运行计时器(全局解锁操作)时,或者当它读取另一个MB的CS字段时,不管它的代码是什么,锁就会被释放。CPU写入C/S字也会解锁MB,但这个过程不建议用于普通解锁,因为它会取消正在处理的移入过程,可能会丢失接收到的消息。当CPU正在读取邮箱时,邮箱锁机制可以防止新接收到的帧写入邮箱。

        邮箱锁定机制只适用于不属于Legacy Rx FIFO的接收邮箱,并且与CODE字段中INACTIVE (0b0000)或EMPTY[1] (0100b)代码功能不同。注意,发送邮箱不能被锁定。

举个例子:假设Legacy Rx FIFO功能被禁用,2号邮箱与5号邮箱使用相同的ID,且FlexCAN已经接收并存储CAN消息到这两个邮箱中。

        假设现在CPU决定读取5号邮箱,同时另一条具有相同ID的信息到达。当CPU读取5号邮箱的控制状态字,这个邮箱就会被锁定。当新消息到达时,FlexCAN匹配算法发现没有空闲的接收邮箱,因此它决定覆盖5号邮箱。但是5号邮箱是锁定的,因此不能在5号邮箱写入新消息。它将留在Rx SMB(临时RX邮箱)中,等待邮箱被解锁,然后才会被写入邮箱。

        如果MB没有及时解锁,而另一个具有相同ID的新消息到达,那么新消息将覆盖Rx SMB上的消息,在MB的CODE字段或CS字段中都不会有丢失消息的指示。此时Rx SMB中丢失的消息将不会有任何的提示。当消息从Rx SMB移动到MB时,将置位CODE字段上的BUSY位。当CPU读取CS字段发现BUSY位显示正忙,应推迟访问邮箱,直到BUSY位被取消。

2. MCR[SRXDIS] 自接收功能

        在MCR寄存器中,具有一个可以设置自接收功能的位。这个位定义了是否允许FlexCAN接收自己传输的帧(自发自收)。如果这个位被设置启用,不管邮箱是否被设置为与发送帧相匹配的ID,FlexCAN模块发送的帧都不会被存储在任何MB中。而且,信息帧的接收不会产生中断标志或中断信号。注意,这个位只能在冻结模式下进行写入。

0b     /*  启用自接收  */
1b     /* 自接收被禁用 */

物联沃分享整理
物联沃-IOTWORD物联网 » NXP S32K3系列学习笔记:FlexCAN驱动开发实践

发表评论