autosar架构_CAN通讯系列--AUTOSAR架构的CAN Driver6

上篇文章简介了AUTOSAR架构的CAN通讯软件实现,从这篇文章开始将逐一介绍有关的各个模块,本文将介绍CAN Driver模块。


7 文档说明

考虑到这几篇AUTOSAR文档的结构完全一样,在此先对将涉及的文档做一个概括性说明。以CAN Driver规范为例,如下图1所示。

6ec9caf19183f9fd7545eb6565ccad3f.png
图1 CAN Driver规范的内容

总的来说,文档一般有10个章节,前5章相当于先做一个详细的背景知识介绍,只有了解好这个背景与前提,才能更好地解读后面章节的内容。然后列出了底层软件需求与详细软件设计的追溯关系,比如图2所示。

4b97f64b5a7496dd65d80a7fc7927499.png
图2 底层系统需求与软件需求追溯示意,引自[1]

再描述了该模块的功能规范说明,接口与函数定义,以及功能执行时序图等内容,可理解为介绍如何用详细软件设计去实现需求的过程。就如图2所示内容,有一条底层软件需求是 CAN Driver模块必须提供一个接收通知服务,然后分解成2条详细软件设计去实现。类似于通过这种形式,即根据某模块一系列的软件需求,定义了一系列的软件详细设计,最终决定了该模块的软件架构和内容。

最后,配置规范。从配置工具角度来理解,这部分内容相当于定义好了配置工具的项目与内容。比如前面文章讲到的位速率,如果要配置它,那么配置工具应该在这个项目的配置页面设计位速率,SEG1,SEG2和SJW等配置内容。

0f7a162928e67e049a9729e27d669a36.png
图3 配置规范示意,引自[1]

关于AUTOSAR文档的一点感受:当阅读和研究部分AUTOSAR文档后,会有很多方面的收获,比如需求方面,软件方面,项目方面和技术方面。当然如果仅仅基于文档的话,也许会枯燥乏味,去结合实际项目,应该有助于更深入地理解以上提及的这些方面。

好了,关于文档大致说明到这,下面开始进入CAN Driver模块。


8 CAN Driver

为了与文档描述保持一致,下文将使用CAN模块来表示CAN Driver。简单地说,CAN模块属于一部分的最底层内容,其作用是执行硬件访问和为上层提供独立的硬件接口(这里能访问CAN模块的上层只有Can Interface模块)。说到访问硬件,先了解几个概念,如图4所示:

175a216db5a1a3211c8861d9dfe71a89.png
图4 CAN硬件单元示意

对图4内容的解释如下:

  • 一个CAN 硬件单元(CAN Hardware Unit)就相当于某个ECU的CAN硬件部分,它可以包括一个或多个CAN控制器(Controller)。
  • 一个CAN控制器就是一个CAN节点或一条CAN,即对应连接一条物理通道。它有很多个报文邮箱(message object)
  • 一个报文邮箱又有多个寄存器,用来存储报文信息,如下图5所示。

e41cf4891dedb91c3cb8070576777cfa.png
图5 报文邮箱的寄存器,引自[2]

所以关于CAN接收和发送,由上可知CAN模块访问的是CAN硬件单元某个CAN控制器某些寄存器。那么CAN模块在怎样的条件才能访问到呢?下面需要再介绍几个概念:

8.1 驱动状态机(Driver state machine)

CAN模块驱动状态机有两个状态,在上电或重置后,CAN模块进入CAN_UNINIT状态(未初始化状态),初始化后,CAN模块进入CAN_READY状态,这时可执行一些与读、写、总线关闭、唤醒和控制器状态设置相关的功能。也就是说CAN接收和发送必须在驱动状态机处于CAN_READY才能执行。

2c7c14ae9ddea7167fc220cc0b959885.png
图6 CAN驱动状态机,引自[1]

8.2 控制器状态机(Controller state machine)

在驱动状态机处于CAN_READY状态前提下,还需要考虑CAN控制器状态。因为在硬件层面,CAN控制器会执行很复杂的状态机,去实现不同的硬件行为。有时是需要在相应的状态才会去实现某些功能,比如初始化,波特率设置等;有时是外部事件(总线关闭,唤醒事件)会触发状态变化,导致是否能执行某些功能。

出于简化目的,这里将CAN控制器的状态分为4个。

d62cfec0da91358917df58fdad52eab9.png
图7 CAN控制器状态机,引自[1]
CAN控制器未初始化- UNINIT
属于CAN模块的所有寄存器都处于复位状态,不使能CAN中断。 CAN控制器不参与CAN总线。

CAN控制器状态已停止- STOPPED
在这种状态下,CAN控制器已初始化,但不参与总线。另外也不得发送错误帧和确认。

CAN控制器状态已启动- STARTED
控制器处于正常运行模式,具有完整的功能,这意味着它已加入网络。
对于许多控制器而言,离开“初始化”模式会使控制器启动。

CAN控制器状态为睡眠- SLEEP
与STOPPED仅有的不同是:CAN的硬件设置支持睡眠模式(由CAN硬件支持唤醒的CAN总线直接唤醒)
关于CAN硬件支不支持SLEEP,其对应的处理方法有:
支持-- the CAN hardware is triggered to transition into SLEEP state, the Can module shall 
set the controller to the SLEEP state from which the hardware can be woken over CAN Bus.
不支持-- the CAN hardware is triggered to transition into SLEEP state, the Can module shall 
emulate a logical SLEEP state from which it returns only, when it is triggered by software 
to transition into STOPPED state.

通过上述定义可知:CAN接收和发送必须在控制器状态机处于STARTED状态才能执行。怎么能让CAN控制器处于STARTED状态呢,通过上述状态机不难发现,得先进入STOPPED状态才行。一般有以下几种方法来触发CAN控制器的状态转移到STOPPED:

  1. 初始化函数 Can_Init,使控制器状态从UNINIT转移到STOPPED;
  2. 位速率设置函数Can_SetBaudrare,使控制器状态转移到STOPPED;
  3. 控制器模式设置函数Can_SetControllerMode, 使控制器状态转移到目标状态;
  4. 硬件事件触发,比如唤醒事件使控制器从SLEEP转移到STOPPED,总线关闭事件使控制器从STARTED转移到STOPPED。

文档对这4个状态和控制器模式设置函数Can_SetControllerMode都做明确的定义

10519b2c2f6500cfe3aba082ce04f046.png
引自[1]

621e6810ba9f0f3c067f130f383844f6.png
引自[1]

8.3 CAN 模块/控制器初始化

上述两个状态一般都是先通过初始化函数设置,即在使用Can模块的任何其他功能之前,ECU状态管理器模块在启动阶段调用CAN模块的初始化函数(Can_Init)进行初始化,其内容有:

  • 静态变量,包括标志;
  • 完整的CAN硬件单元的通用设置;
  • 每个CAN控制器的CAN控制器特定设置。

e9c31445a45c44c227ad343ba9d39171.png
图8 初始化函数定义,引自[1]

初始化后,CAN驱动状态为CAN_READY,CAN控制器状态为STOPPED。

当CAN模块满足条件,可以访问寄存器了,那么CAN模块怎么去实现CAN发送或接收所需的操作呢?以及需要做哪些操作呢?

8.4 协议数据单元(Protocol Data Unit, PDU)

在回答这两个问题前,为了发送或接收涉及的数据格式,需再介绍下PDU的概念,PDU包括协议控制信息(Protocol Control Information,PCI)和服务数据单元(Service Data Unit, SDU)。

其中SDU是指从上层模块传过来,要求发送的数据;或下层模块接收的,已提取好的数据,需要传给上层。

PCI是指需要将SDU从特定协议层的一个实例传递到另一实例。 例如。 它包含源和目标信息。PCI在发送方的协议层添加,再在接收方被删除。

通俗地理解就是:PDU不仅仅是数据(SDU),还携带了来自哪要去哪的信息(PCI);每到哪都会删掉之前的信息,添加这是哪要去哪的信息(不同层的PCI更新),如下图9所示。

31b25c91b86f9dba4e13e139b6140b64.png
图9 PDU概念,引自[3]

针对OSI参考模型,会根据不同的OSI层相应地给PDU添加前缀,如下图10,在CAN模块中就叫L-PDU。

ce696fda86ffc4afaee47ba3418c69b6.png
图10 基于OSI参考模型的PDU命名,引自[3]

这样也就很好明白前面文章引用过的ISO 11898-1的这张图了,虽然名字不完全一样,但是方法是完全一样的。

8935a74095b8c5662eb8d6e61befa8f9.png

8.5 发送操作

回到上面的两个问题,从前面文章可知,CAN发送时,对于CAN模块有两个操作:一是先访问硬件,将数据写入寄存器;二是发送成功后,向上层CAN Interface模块确认。

0e9e951ca8350fdd649f262eff2c3c9b.png
图11 CAN模块的写数据

2cc35a942ebdce50f6fbe4e22d9d0ff4.png
图12 CAN模块的发送确认

针对写数据操作,CAN Interface模块调用Can_Write函数,其定义如下:

b3cd228d1a00914c4e18368c0fbbd7b8.png
图13 CAN_Write的定义,引自[1]

这里首先要说明下Hth的定义。每一个硬件对象都由ID,DLC和 SDU三部分组成,如下图15。用来存储写入数据的硬件对象就叫Hth,用来存储接收数据的硬件对象就叫Hrh

fa5d6517eee95bc3efc377337f92660d.png
图14 引自[1]

d8c47bd6040f8be70673cc221a189452.png
图15 硬件对象的定义

所以不难理解,Can_Write的输入参数Hth其实就是硬件对象的编号(id),而且实际上是已经定义好了硬件对象的编号与CAN ID的映射关系,比如下图16所示,如果想发送CAN ID 为0x001的数据,那么调用Can_Write函数的输入参数Hth应该为4。

fe88df5821fca5e5ce72329ae60d3d96.png
图16 硬件对象的编号与CAN ID的映射关系

然后引用文档内容说明下Can_Write函数要执行主要动作,如下所示:

5be1ec342891b6ba5dfde59ed3f2b8d5.png

70897f3836cf4ae5f571f24150f65728.png

9273791b3fa0a37fe8951f38cb773883.png

9a12742f82379041718336be27cb07a5.png

0b238448a745c3dcde4c043857f38d80.png
引自[1]

这样我们就知道写数据的过程,最后再了解下发送确认过程,从前面文章可知,BSW调度器会周期性调用Can_MainFunction_Write函数,其定义如下:

c9efb62fd4a9c7fb1d82e223dca74752.png
图17 Can_MainFunction_Write的定义

注意这个函数调用的条件是CAN发送处理方式为POLLING(轮询)。这里说明下CAN发送处理方式,有3种:

(1)轮询模式(polling mode)

轮询模式下Can模块的发送确认被调度模块(BSW Scheduler)触发,执行随后的处理。比如设定CAN发送为轮询模式,那么Can_MainFunction_Write就会在预定义的时间间隔被周期性地调用(比如每几ms调用一次),然后Can_MainFunction_Write中再去调用上层的CAN Interface模块的CanIf_TxConfirmation模块,向上确认。

(2)中断模式(interrupt mode)

中断模式下Can模块的发送确认由CAN控制器的中断触发,执行随后的处理,比如设定CAN发送为中断模式,那么中断触发后,调用Can模块的发送确认处理函数,在该函数中去调用Can Interface模块的CanIf_TxConfirmation函数,向上确认。

(3)混合模式(mixed mode)

即(1)(2)的混合使用,看具体设定,是使用轮询模式还是使用中断模式的处理方式。

所以这里我选择的是轮询方式进行介绍。根据CanIf_TxConfirmation函数的输入参数可知,向上确认的是哪个CAN ID发送成功。(这里不对CanIf的函数介绍,下篇文章再介绍)

b71350f03643b26d112d54d2722ea182.png

8.6 接收操作

从前面文章可知,CAN接收时,对于CAN模块同样有两个操作:一是先访问硬件,从寄存器提取数据;二是通知上层CAN Interface模块,传递数据。

8a800ee5e5510ad19cf84e942ca83f9c.png
图18 CAN模块的接收操作

针对读数据操作,首先BSW调度器周期性调用Can模块的Can_MainFunction_Read函数,其定义如下。同样地CAN接收处理方式有轮询,中断和混合模式 。这里选择的是轮询模式。

90b8c23afeb1742096a17da24d3290da.png

然后Can_MainFunction_Read做访问硬件,提取相应的寄存器数据,这里主要根据CanIf_RxIndication函数需要哪些数据进行提取,如下所示:

7972b8d0522e23b5eaef2eecb48dcadd.png

最后,数据成功提取后,Can_MainFunction_Read函数将通过调用CanIf_RxIndication函数通知CAN Interface模块,向上传递数据。(这里不对CanIf的函数介绍,下篇文章再介绍)

8.7 小结

以上就是本文对CAN Driver在CAN发送与接收过程的有关内容的介绍,总结如下图19。

0797c281a72b0f4f9fa29985575f73de.png
图19

写在此处,突然觉得若想进一步地理解这个模块的话,可投入更多精力去了解芯片的CAN硬件部分。为了更进一步了解CAN发送与接收功能,下篇文章一起去了解CAN Interface模块。

Reference:

[1] Specification of CAN Driver

[2] TC27x D-Step 32-Bit Single-Chip Microcontroller

[3] AUTOSAR Layered Software Architecture

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值