在AUTOSAR分层架构中,MCAL是最基础的一层。由于该层直接和单片机打交道,在整个开发流程中往往最靠前,在PCB测试过程中也发挥着至关重要的作用。
本文以MCAL的串口模块为例,分别讲述UART手工和工具链编程的方法。对于MCAL的其它模块,设计思路和步骤是类似的,可参照本文的要点进行开发。
为表述方便,首先对本文中出现的概念或术语进行说明,文中黑体字为“官方定义”,红体字加入了本人的理解。
MCAL(Microcontroller Abstraction Layer)指微控制器抽象层,是实现不同硬件接口统一化的特殊层。通过微控制器抽象层可将硬件封装起来, 避免上层软件直接对微控制器的寄存器进行操作。微控制器抽象层包括微控制器驱动(Microcontroller Drivers)、存储器驱动(Memory Drivers)、通信驱动(Communication Drivers)以及I/O驱动(I/O Drivers)。
简单来说,MCAL就是主控芯片(单片机)的外设驱动。
静态代码(Static Code)指各模块功能的具体实现代码;动态代码(Dynamic Code)指由配置工具根据相关配置信息生成的代码,也称为配置代码。
在AUTOSAR应用过程中,静态代码实现了某模块的全部功能,且其内容在工具链不更新的前提下是不会改变的。而具体用到该模块的哪些功能以及用何种方式实现这些功能,是由用户通过工具配置出来的,配置结果生成在动态代码的程序文件中。
在工具链开发过程中,文档的编写显得尤为重要。原因是各个功能块都是用工具配置出来的且生成代码量极其庞大,通过代码研读的方式分析查找问题不太现实,需要把整个工作过程记录下来。在MCAL开发过程中最好输出如下2个文档。
设计文档:记录MCAL模块的整个设计过程,包括MCAL相关模块的配置、初始化函数的调用、功能具体实现和调试过程等。
配置文档:作为设计文档的一部分,聚焦MCAL本模块配置的详细步骤。
MCAL用户手册(User Manual)作为MCAL开发过程中最重要的文档,存在于“EB Tresos Studio”(MCAL配置工具)的安装包中。
下面着重讲述手工方式和工具链方式设计主控芯片外设驱动在思路上的差别。
单片机底层驱动手工编程的设计步骤如图3-1所示。
图3-1: 手写代码实现单片机外设驱动步骤
单片机底层驱动工具链开发的设计步骤如图3-2所示。
图3-2: 工具链开发实现单片机外设驱动步骤
这里着重强调一点,在用工具链开发单片机外设驱动的过程中,千万不要像传统方法那样研究单片机的寄存器和时序。AUTOSAR工程数据结构复杂,函数调用层级众多,在短时间内将某个模块的静态代码研究明白不太现实。从实例和配置项含义入手,再配合以局部改动和调试,往往能取得事半功倍的效果。
用手工编程方式实现单片机UART模块,主要包括初始化、中断处理、数据收发等几部分,收发数据往往以字节为单位进行,图4-1和图4-2为手工方式实现UART模块的代码段截图。
图4-1: UART手写代码截图-寄存器配置
图4-2: UART手写代码截图-功能实现
下面列出AUTOSAR工具链实现UART功能的步骤,这里将TC275的P14.10和P14.8用做UART的发送和接收管脚。
注:EcuM、OS等模块配置在前面的文章中讲述过,本文不再赘述,感兴趣的读者可参照本公众号之前的文章。
《从手写代码到AUTOSAR工具链_RTE入门篇》;
《从手写代码到AUTOSAR工具链_EcuM应用篇》;
《从手写代码到AUTOSAR工具链_BswM应用篇》;
《从手写代码到AUTOSAR工具链_工程创建与模块集成》。
表5-1: 主控芯片和工具一览表
序号 | 项 | 内容 |
1 | 主控芯片 | Infinean TC275 |
2 | MCAL工具 | EB Tresos Studio 16.0 |
3 | AUTOSAR工具 | ETAS ISOLAR-AB 4.0 |
4 | OS工具 | RTA-OS 5.6.3 |
5 | IDE | Hightec 4.9.2 |
首先需要配置参与串口通信的P14.8和P14.10,重点是将P14.10的功能配置为“ATX1”。
表5-2: P14.8参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | PortPinId | 232 | 每个管脚唯一的ID号,不可配置 |
2 | PortPinSymbolicName | PORT_14_PIN_8 | 用户为P14.8管脚定义的名字 |
3 | PortPinDirection | PORT_PIN_IN | 管脚用作输入 |
4 | PortPinDirectionChangeable | NC | 因未使能相应API函数,不可配置 |
5 | PortPinInputCharacteristic | PORT_PIN_IN_NO_PULL | 无上下拉输入 |
6 | PortPinInputHysteresis | FALSE | 不启用滞后功能 |
7 | PortPinOutputCharacteristic | NC | 输入管脚不可配置 |
8 | PortPinLevelValue | PORT_PIN_LEVEL_LOW | 管脚缺省值为0 |
9 | PortPinInitialMode | PORT_PIN_MODE_GPIO | 用作通用输入输出管脚 |
10 | PortPinModeChangeable | NC | 因未使能相应API函数,不可配置 |
11 | PortPinDriverStrength | NC | 输入管脚不可配置 |
12 | PortPinPadLevel | PORT_PDR_CMOS_AUTOMOTIVE_LEVEL | 管脚电平级别:车辆电平 |
13 | PortPinAnalogInput | NC | 非特定管脚不可配置 |
14 | PortPinControllerSelect | NC | 非特定管脚不可配置 |
表5-3: P14.10参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | PortPinId | 234 | 每个管脚唯一的ID号,不可配置 |
2 | PortPinSymbolicName | PORT_14_PIN_10 | 用户为P14.10管脚定义的名字 |
3 | PortPinDirection | PORT_PIN_OUT | 管脚用作输出 |
4 | PortPinDirectionChangeable | NC | 因未使能相应API函数,不可配置 |
5 | PortPinInputCharacteristic | NC | 输出管脚不可配置 |
6 | PortPinInputHysteresis | NC | 输出管脚不可配置 |
7 | PortPinOutputCharacteristic | PORT_PIN_OUT_PUSHPULL | 推挽输出 |
8 | PortPinLevelValue | PORT_PIN_LEVEL_LOW | 管脚缺省值为0 |
9 | PortPinInitialMode | PORT_PIN_MODE_ALT4 | 可选输出功能1:TOUT71 |
10 | PortPinModeChangeable | NC | 因未使能相应API函数,不可配置 |
11 | PortPinDriverStrength | PORT_CMOS_SPEED_GRADE1 | 驱动强度:CMOS速度等级1 |
12 | PortPinPadLevel | PORT_PDR_CMOS_AUTOMOTIVE_LEVEL | 管脚电平级别:车辆电平 |
13 | PortPinAnalogInput | NC | 非特定管脚不可配置 |
14 | PortPinControllerSelect | NC | 非特定管脚不可配置 |
Mcu配置分为AscLin和Clock两部分。
按照图5-1和图5-2所示将AscLin1配置为UART驱动。
图5-1: MCU配置进入
图5-2: ASCLIN配置
按照图5-3和图5-4配置ASCLIN模块的时钟,本文示例配置为100MHz。
图5-3: 时钟配置进入
图5-4: ASCLIN时钟配置
依次进行通用箱配置和UART集配置。
下面介绍UART模块通用(General)箱的配置情况,图5-5为配置界面,表5-4为各项的配置参数和简要说明。
图5-5: UART模块通用箱配置界面
表5-4: UART模块通用箱参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | Config Variant | VariantPostBuildSelectable | |
2 | Name | UartGeneral | 配置箱名称 |
3 | UartDevErrorDetect | false | 开发错误检测禁止 |
4 | UartIndex (0 -> 255) | 0 | Uart索引,必须为0 |
5 | UartVersionInfoApi | false | 版本信息API禁用 |
6 | UartDeInitApi | false | Uart反向初始化API禁用 |
7 | UartAbortReadApi | false | Uart中止接收API禁用 |
8 | UartAbortWriteApi | false | Uart中止发送API禁用 |
9 | UartPBFixedAddress | false | 配置参数集不存放固定地址 |
10 | UartDebugSupport | false | Uart调试功能禁用 |
11 | UartResetSfrAtInit | false | 禁止在Uart初始化前复位相关SFR的缺省值 |
12 | UartSleepEnable | true | 当收到MCU的休眠请求时ASCLIN模块进入休眠状态 |
13 | UartRunningInUser0Mode | false | |
14 | UartUserModeInitApiEnable | false | |
15 | UartUserModeDeInitApiEnable | false | |
16 | UartUserModeRuntimeApiEnable | false |
下面介绍Uart集(UartConfigSet)箱的配置情况,图5-6为其配置界面。
图5-6: Uart集配置界面
1.通用配置
图5-7为Uart集通用(General)箱的配置界面,表5-5为各项的配置参数和简要说明。
图5-7: Uart集通用参数配置界面
表5-5: Uart集通用参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | UartSysClockRef | /Mcu/Mcu/McuModuleConfiguration_0/McuClockSettingConfig_0/McuClockReferencePoint | Uart系统时钟引用,MCU模块配置值为100MHz |
2.Uart通道配置
图5-8为Uart通道(UartChannel)箱的配置界面,表5-6为各项的配置参数和简要说明。
图5-8: Uart通道配置界面
表5-6: Uart0通道参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | Name | UartChannel_0 | 配置箱名称 |
2① | UartBaudRate | 19200 | Uart通信波特率 |
3 | UartHwUnit | ASCLIN1 | 硬件ASCLIN通道,使用P14.8(RXD)和P14.10(TXD)口 |
4 | UartChannelId | 0 | Uart通道ID,不可配置 |
5 | UartAutoCalcBaudParams | true | 自动波特率计算使能 |
6 | UartChanBaudNumerator | - | BRG寄存器的分子域,自动计算波特率时无需配置 |
7 | UartChanBaudDenominator | - | BRG寄存器的分母域,自动计算波特率时无需配置 |
8 | UartChanBaudPrescalar | - | BITCON寄存器的分频域,自动计算波特率时无需配置 |
9 | UartChanBaudOverSampling | - | BITCON寄存器的采样过密域,自动计算波特率时无需配置 |
10 | UartRxPinSelection | SELECT_DATALINE_D | Rx口选择:P14.8为ASCLIN1的数据线D |
11 | UartDataLength | 8 | Uart数据长度 |
12 | UartStopBits | 1 | Uart停止位 |
13 | UartParityBit | NOPARITY | Uart奇偶校验 |
14 | UartCTSEnable | false | CTS功能禁止 |
15 | UartCTSPolarity | - | CTS功能禁止时无需配置 |
16 | Name | UartNotification | 配置箱名称 |
17 | UartTransmitNotifPtr | UartTransmitNotifPtr | 发送完毕的通知函数 |
18 | UartRecieveNotifPtr | UartReceiveNotifPtr | 接收到数据的通知函数 |
19 | UartAbortTransmitNotifPtr | NULL_PTR | 中止发送操作后调用 |
20 | UartAbortReceiveNotifPtr | NULL_PTR | 中止接收操作后调用 |
①波特率计算公式(fA = 100MHz)
下面介绍Uart模块版本(Published Information)箱的配置情况,图5-9为配置界面,表5-7为各项的配置参数和简要说明。
图5-9: Uart模块版本箱配置界面
表5-7: Uart模块版本箱参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | ArMajorVersion | 0 | Autosar主版本,不可配置 |
2 | ArMinorVersion | 0 | Autosar子版本,不可配置 |
3 | ArPatchVersion | 0 | Autosar补丁版本,不可配置 |
4 | SwMajorVersion | 1 | 软件主版本,不可配置 |
5 | SwMinorVersion | 3 | 软件子版本,不可配置 |
6 | SwPatchVersion | 0 | 软件补丁版本,不可配置 |
7 | ModuleId | 255 | 模块ID,不可配置 |
8 | VendorId | 17 | 供应商ID,不可配置 |
9 | VendorApiInfix | - | API中缀,不可配置 |
10 | Release | _TRICORE_TC275 | 发布,不可配置 |
根据需要配置UART模块的中断类型和中断类别,UART的中断类型包括Tx中断、Rx中断和Err中断;中断类别分为一类中断和二类中断,两者的区别和配置方法如表5-8所列。
表5-8: 中断类别说明
事项 | 一类中断 | 二类中断 |
含义 | 中断服务子程序直接响应 | 由操作系统接管 |
类别配置① | 在MCAL的Irq模块配置为CAT1 | 在MCAL的Irq模块配置为CAT23 |
优先级配置② | 在MCAL的Irq模块中配置 | 在RTA-OS中配置,MCAL的Irq模块写0 |
应用③ | 通常用于与DMA配合的收发中断 | 用于不需要与DMA配合的中断 |
中断初始化函数调用④ | 必须调用相应的中断初始化函数 | 无需调用相应的中断初始化函数 |
①配置的目的是为了打开Xxx_Irq.c中的相应宏,如图5-10所示
图5-10: 中断服务子程序示例
②数值越大优先级越高
③与DMA配合的中断,处理源(Irq
④中断初始化函数的格式:Irq
按照图5-11和图5-12配置MCAL的Irq模块,配置参数如表5-9所列,其余项使用缺省值。
图5-11: AscLin中断配置进入
图5-12: AscLin中断配置
表5-9: AscLin中断参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | IrqAscLin1TxCat | CAT23 | 选择二类中断 |
2 | IrqAscLin1RxCat | CAT23 | 选择二类中断 |
3 | IrqAscLin1ErrorCat | CAT23 | 选择二类中断 |
4 | IrqAscLin1TxPrio | 0 | 二类中断优先级在RTA-OS中配置 |
5 | IrqAscLin1RxPrio | 0 | 二类中断优先级在RTA-OS中配置 |
6 | IrqAscLin1ErrorPrio | 0 | 二类中断优先级在RTA-OS中配置 |
7 | IrqAscLin1TxTos | CPU0 | 处理源为CPU0 |
8 | IrqAscLin1RxTos | CPU0 | 处理源为CPU0 |
7 | IrqAscLin1ErrTos | CPU0 | 处理源为CPU0 |
在RTA-OS环境下按照图5-13配置表5-10列出的中断。
图5-13: OS中断配置
表5-10: OS中断配置参数
序号 | 名称 | 类别 | 优先级 | 地址 |
1 | ASCLIN1EX_ISR | CATEGORY_2 | 37 | ASCLIN 1 Error (SRC_ASCLIN1ERR) |
2 | ASCLIN1RX_ISR | CATEGORY_2 | 38 | ASCLIN 1 Receive (SRC_ASCLIN1RX) |
3 | ASCLIN1TX_ISR | CATEGORY_2 | 39 | ASCLIN 1 Transmit (SRC_ASCLIN1TX) |
注意:上表中的“名称”项非自行命名,须与Xxx_Irq.c中的名称一致,否则编译无法通过。
图5-14: 中断配置名称示例
需在RTA-OS中生成OS代码,再在ISOLAR-AB中进行抽取、BSW代码生成、RTE代码生成等操作。
UART模块初始化函数调用在EcuM模块中进行。
在ISOLAR-AB中按照图5-15和图5-16的步骤配置表5-11中的参数。
图5-15: EcuM配置启动
图5-16: EcuM串口初始化配置
表5-11: Uart初始化参数配置
序号 | 配置项 | 配置值 | 说明 |
1 | ShortName | Uart | 配置箱名称 |
2 | EcuMModuleID | Uart | 初始化模块的短名称 |
3 | EcuMModuleParameter | POSTBUILD_PTR | 函数原型和输入参数定义 |
4 | EcuMModuleService | Init | 模块初始化方式,按照这里配置的初始化函数调用方式为Uart_Init(&Uart_Config) |
5 | EcuMRbDriverInitCoreId | - | 指定驱动初始化被哪个核调用 |
6 | EcuMRbMonitoringCapable | - | 指定模块不生成监控服务 |
7 | EcuMRbSequenceID | - | 生成的功能桩基于模块配置的顺序 |
8 | EcuMModuleRef | - | 模块示例的外部引用,不配置EcuMModuleID时有效 |
在程序文件中编写如图5-17所示的宏定义。
图5-17: Uart初始化宏定义
UART模块常用的API函数如表5-12所列。
表5-12: UART模块API函数功用
序号 | 函数名 | 输入参数 | 输出参数 | 说明 |
1 | Uart_Init | Uart配置集指针 | 无 | UART模块初始化 |
2 | Uart_Read | Channel:接收数据的Uart通道 MemPtr:接收数据存储首地址 Size:准备接收的字节数 | 无 | UART接收 |
3 | Uart_Write | Channel:发送数据的Uart通道 MemPtr:发送数据存储空间首地址 Size:要发送的字节数 | 无 | UART发送 |
4 | UartTransmitNotifPtr | ErrorId:错误ID | 无 | UART发送完毕通知函数 |
5 | UartReceiveNotifPtr | ErrorId:错误ID | 无 | UART接收完毕通知函数 |
调试代码的功用:将接收到的25字节数据发出,图5-18为其主要代码的截图。
如果接收的数据少于25字节,只有在收全25字节后,才执行数据发送的操作;如果接收的数据多于25字节,只接收前25字节并发出。
图5-18: UART收发调试核心代码
来源:你好旧时光追忆
- THE END -