小猫爪:AWR294x学习笔记01-AWR294x之MCAN
1 前言
这一篇文章来记录一下AWR2944的MCAN。
2 MCAN简介
列出MCAN的一些基本特性:
- Conforms with ISO 11898-1:2015
- Full CAN FD support (up to 64 data bytes)
- AUTOSAR and SAE J1939 support
- Up to 32 dedicated Transmit Buffers
- Configurable Transmit FIFO, up to 32 elements
- Configurable Transmit Queue, up to 32 elements
- Configurable Transmit Event FIFO, up to 32 elements
- Up to 64 dedicated Receive Buffers
- Two configurable Receive FIFOs, up to 64 elements each
- Up to 128 filter elements
- Internal Loopback mode for self-test
- Maskable interrupts, two interrupt lines
- Two clock domains (CAN clock/Host clock)
- Parity/ECC support - Message RAM single error correction and double error detection (SECDED) mechanism
- Local power-down and wakeup support
- Timestamp Counter
下图为MCAN的功能框图:
首先看一些MCAN模块与外部常见的信号有:
- MCAN_ICLK:接口时钟,为CAN Host提供模块时钟,应尽量小于或等于MCAN_FCLK。
- MCAN_FCLK:外设异步时钟,为外部CAN总线提供bit时钟,其时钟源为:DPLL_DSP_HSDIV0_CLKOUT2。
- Interrupt Requests:MCAN可以产生各种中断,包括收发中断以及错误等中断,详情请见寄存器MCAN_IE。
- DMA Requests: MCAN可以产生DMA请求,分别是TX event和两个Filter匹配event。
再来看看MCAN模块的一些组成部分:
- CAN Core:CAN控制器
- 各种Interface:MCAN模块内部信息交互的接口
- Message RAM:MCAN的内部RAM存储空间,MCAN接收数据,发送数据,报文Filter都是通过这一块RAM来实现的,总大小为1600words。这个可以说是理解MCAN的重点,后面会详细说明。
3 Feature描述
3.1 MCAN的工作模式
MCAN具有多种工作模式,如下:
- Software Initialization:初始化模式,需要在初始化MCAN的时候进入。
- Normal Operation/CAN FD Operation: 正常工作模式,分别为Clasic CAN和CAN FD模式。
- Restricted Operation Mode:在这个模式,接收功能正常,但是却不能发送数据帧,远程帧,错误指示帧,超载帧,而且如果检测到总线错误,其不会发送显性位。可主动进入该种模式,另外这种模式可以算是MCAN的一种安全模式,当MCAN检测到Tx Handle无法读取Message RAM的时候才会进入这种模式,可通过软件主动退出这种模式。通常可以用这种模式来做自适应bit rate。
- Bus Monitoring Mode:就是ISO中的监听模式。
- Disabled Automatic Retransmission (DAR) Mode:在这个模式中,CAN的自动重发机制被禁用。
- Power Down (Sleep) Mode:MCAN的低功耗模式,可用作芯片的唤醒源。
- Test Mode:测试模式,可通过软件控制MCAN_TX和MCAN_RX引脚状态,也可使能Internal Look Back模式。
3.2 Timer Counter
- MCAN需要一个外部的timer为其提供时间戳功能。
- MCAN内部有一个超时Counter,相当于是一个超时看门狗的保护措施。使能后,如果选择让FIFO控制这个Counter,当一条消息被存储进了FIFO中时看门狗启动,只有当FIFO里的数据被读完后,这个Counter才会被停止,如果在一定时间内,FIFO一直有数据,则会导致超时事件发生;如果选择让Counter工作在Continuous Mode,则需要通过软件来进行喂狗,这一般用于FIFO内报文特别多短时间内读取不完的情况。
3.3 ECC检测
MCAN对其空间提供1bit和2bit检测机制,当MCAN检测到ECC错误时,会报告错误,可触发中断,并记录错误地址。
3.4 Transmitter Delay Compensation
MCAN可配置TDC对第二采样点(SSP)进行补偿。关于对CAN TDC和SSP不太了解的朋友可参考这篇文章:《TDC传输延迟补偿和SSP第二采样点》。
4 Messgae RAM
之前就提过Messgae RAM是MCAN内部的一段1600Words的RAM空间,在不同的应用中对CAN的收发邮箱的数量要求不尽相同,MCAN为了灵活应对各种应用场合干脆就直接整出一点RAM出来,让用户根据自己的应用来配置。配置方法也很简单:
其原理就是将各个部分的首地址偏移告诉CAN Core就行了,因为每个element的大小都是固定的,这样CAN Core和用户软件就能通过首地址和index来访问想要的element。从上面的图中就可以看出,MCAN同时最大支持128个标准帧硬件Filter,64个扩展帧硬件Filter,2个深度64的RX_FIFO,64个RX_Buffer,32个TX_Buffer。还有32深度的Tx_Event_FIFO,这个其实是用来记录发送信息的,当MACN成功发送一帧报文后,可以自动将相关发送信息记录在Tx_Event_FIFO中。
在这里有一个非常重要的点就是,根据上面的描述,MCAN可同时支持32个TX buffer,128深度的RX FIFO以及64个RX Buffer,但是这里需要注意的是MCAN的RAM Size只有1600个Words,在涉及到CANFD的应用场景来说,随着DLC的增加,每一个RX_TX_Buffer所占的空间就会变大,所以在这个时候,MCAN就无法同时支持这么多的buffer存在了,所在在设计MCAN的Buffer数量时,需要注意这个点。Buffer DLC与其所占的RAM大小关系如下图所示:
以上各种element在Message Buffer中的数据结构如下:
每个element的每一位代表什么意思在RM手册都有详细的描写,在这里就不多做赘述。
5 机制描述
5.1 Rx Handling
上面说到MCAN最大同时支持2个深度64的RX_FIFO,64个RX_Buffer,所以MCAN理论上同时可最大存储192条报文,但实际上也根本用不到这么多,64个基本上都满足大部分应用了。MCAN的接收机制比较简单,即MCAN接收到满足硬件ID Filter的报文就会将其存储在RX_FIFO或者RX_Buffer中。每一个RX_Buffer可以指定一个硬件ID Filter,而RX_FIFO则可以同时指定多个硬件Filter。MCAN接收到报文后优先匹配FIFO的Filter再匹配RX_Buffer的Filter。
MCAN的ID Filter支持三种模式分别是:
- (ID1 < IDxz < ID2)? 一个范围
- ( (IDx == ID1) || (IDx == ID2) )? 两个特定的ID
- (IDx & Mask == ID1 & Mask)? 经典ID,Mask组合
除了ID Filter,还有一个全局Filter的概念,全局Filter所限制的则是MCAN是否接收远程帧。如果总线上有远程帧,则直接拒绝接收报文。另外还有一个扩展帧的全局MASK,也就是说如果接收的帧类型是扩展帧,那么会先将该扩展帧的ID与这个全局MASK作与操作,然后接下来再与ID Filter进行匹配。
另外RX_FIFO有两种工作模式,分别是Blocking Mode和Overwrite Mode,它所决定的就是当FIFO满了之后,当新的一条报文来了之后模式选择拒收还是覆盖原有报文。
注意:RX_FIFO有一个非要重要的事情就是FIFO Acknowledge Handling。MCAN的FIFO其实是一个简化版的软件FIFO,它是不支持自己进行数据移位,是需要通过一个硬件层面上的put index和get index进行数据读取和写入的,在写入的时候,RX_FIFO会自动更新put index,但是在读取的时候,需要软件对FIFO进行read ack,然后CAN Core进行FIFO状态更新,所以软件必须确保FIFO Acknowledge的操作被正确执行。RX_FIFO状态更新示意图如下:
另外FIFO对于CPU来说只是一段内存,CPU是可以随意访问FIFO的,所以可以直接去FIFO里面读,不按FIFO的顺序读,这种方式下当然就不需要维护FIFO的get index了,但是不推荐这种方法。
5.2 Tx Handling
对于Tx的处理机制就比较复杂了,MCAN最大支持32个Tx Buffer,然后又可将部分或者全部邮箱配置成FIFO模式(或者Queue模式,,二者只能同时存在一个,唯一的区别就是两个模式下发送报文的优先级不同,FIFO模式为邮箱号小的优先级高,而Queue模式则是根据ID仲裁优先级。而普通的Tx Buffer和配置成FIFO,Queue模式的区别就是Tx Buffer的发送流程完全是通过软件来实现的,而FIFO,Queue模式会有硬件的干预,具体有什么不同我也不知道,总之不推荐混合用就行了,个人觉得怎么简单怎么来,要不就全部配置成Queue模式,要不全部配置成FIFO模式。如果非要混合用,可以参考RM手册中对Tx Handling的具体描述。
Tx Handling这一块还有一个有趣的功能叫做Tx Event Handling,如果使能了这个功能后,在成功发送一帧报文后,那么MCAN会自动将发送成功的报文信息存储到Tx Event FIFO中,具体信息如上文中Tx Event FIFO Element 的结构所示。
6 应用
6.1 SDK的应用
对于SDK的应用就比较简单了,参考一下TI官网的SDK里面的demo,很容易就能把代码整出来,在这里提一下需要注意的两点就是波特率的计算以及CAN ID的处理。
6.1.1 波特率的计算
对于波特率的计算,TI的SDK设计的初始化结构体如下:
typedef struct
{
uint32_t nomRatePrescalar;
/**< Nominal Baud Rate Pre-scaler
* Range:[0x0-0x1FF]
*/
uint32_t nomTimeSeg1;
/**< Nominal Time segment before sample point
* Range:[0x0-0xFF]
*/
uint32_t nomTimeSeg2;
/**< Nominal Time segment after sample point
* Range:[0x0-0x7F]
*/
uint32_t nomSynchJumpWidth;
/**< Nominal (Re)Synchronization Jump Width
* Range:[0x0-0x7F]
*/
uint32_t dataRatePrescalar;
/**< Data Baud Rate Pre-scaler
* Range:[0x0-0x1F]
*/
uint32_t dataTimeSeg1;
/**< Data Time segment before sample point
* Range:[0x0-0x1F]
*/
uint32_t dataTimeSeg2;
/**< Data Time segment after sample point
* Range:[0x0-0xF]
*/
uint32_t dataSynchJumpWidth;
/**< Data (Re)Synchronization Jump Width
* Range:[0x0-0xF]
*/
}MCAN_BitTimingParams;
仲裁段和数据段的计算方式一致,计算波特率的公式如下:
C a n B u a d = S o u r c e C l k / ( R a t e P r e s c a l a r + 1 ) / ( T i m e S e g 1 + T i m e S e g 2 + 3 ) CanBuad = SourceClk / (RatePrescalar + 1) / (TimeSeg1 + TimeSeg2 + 3) CanBuad=SourceClk/(RatePrescalar+1)/(TimeSeg1+TimeSeg2+3)
首先SourceClk就是Can模块的时钟源,这个值在SDK中是通过syscfg工具自动生成的,可以通过查看时钟配置结构体去获取,如下:
这个时候我们再去适当的配置一下RatePrescalar,TimeSeg1和TimeSeg2的值就可以得到自己想要的波特率。采样点的计算就非常简单了,计算方式如下:
S a m p l e P o i n t = 1 − ( T i m e S e g 2 + 1 ) / ( T i m e S e g 1 + T i m e S e g 2 + 3 ) SamplePoint = 1 - (TimeSeg2 + 1) / (TimeSeg1 + TimeSeg2 + 3) SamplePoint=1−(TimeSeg2+1)/(TimeSeg1+TimeSeg2+3)
6.1.2 标准帧ID的处理
还有一点需要注意的地方就是标准帧ID的处理,因为在MCAN的RAM空间映射中,标准帧ID和扩展帧ID存储的位置有一点区别,详情请看RM手册中这个描述,如下:
对于标准帧ID的存储位置是在ID区域的高11bit,所以我们在对报文配置结构体MCAN_TxBufElement进行赋值的时候,如果是标准帧ID,则需要将ID左移18bit后再复制给结构体(对于读取报文时也是一样,需要对ID进行右移),操作如下:
if(txMsg->xtd == TRUE)
{
txMsg->id = canId;
}
else
{
/* Standard message identifier 11 bit, stored into ID[28-18] */
txMsg->id = canId << 18;
}
6.2 MACL的配置
对于MCAL的配置就非常非常简单了,TI的mcal并没有把MCAN的功能全部发挥出来,所以它所提供的配置接口非常的简单,对于FIFO以及Filter等很多复杂的功能都直接在代码中定死了,所以对MCAL的配置也是非常非常的简单,在这里就不多说什么了,参照TI给的mcal例子就可以随便搞出来了。