AUTOSAR笔记:IO系列驱动

I/O架构

Application SWC、Sensor SWC、Actuator SWC是什么关系?它们如何利用硬件读取数据、处理数据、执行动作?

下图展示了它们的关系:

img
from ref. [1]

Application SWC、Sensor SWC、Actuator SWC都是位于应用层,它们通过Port通信,利用RTE层接口访问硬件.

IoHwAb 可在Davinci中申请一个SWC为“I/O - Hardware Abstraction(application layer)”,来作为一个c文件,在其中添加c代码. 也就是当成SWC使用.

MCAL Drivers 是芯片原厂提供的MCU驱动.

I/O系列驱动

AUTOSAR中,I/O ≠ GPIO,而是指DIO(数字输入输出)、PORT、PWM、ICU(Input Compare Unit)、OCU(Output Compoare Unit)、ADC.

EB中配置MCAL,类似于CubeMX中配置MCU、ProcessorExpert中配置MCU,用图形工具配置底层,自动生成C代码.

PORT驱动

PORT驱动主要能配置以下功能:

  • IO口模式选择:GPIO/功能复用
  • IO口方向:输入/输出
  • IO口是否允许在运行过程中改变方向:是/否
  • IO口的初始化电平:高/低
  • IO口的转换速率
  • IO口是否上拉:是/否
  • IO口的输入阈值
  • IO口的驱动模式:推挽/开漏
  • IO口的回读支持类型:电平、输出寄存器值

DIO驱动

DIO常用于
1)给IO口重命名,如pin33 ➡ LED_RED
2)将一些功能相近的通道分到一个组统一管理

PWM驱动

提供常用PWM操作,如:

  • 访问硬件通道
  • PWM周期
  • PWM占空比
  • PWM极性:高/低
  • PWM空闲状态:高/低
  • 相位移(Phase Shift)

下图展示了PWM使用方法:

img
from ref. [2]

ICU驱动

ICU(Input Compare Unit,输入比较单元),主要功能:

  • 边沿计数(Edge Count)
  • 边沿检测和通知
  • 时间戳
  • 信号测量
  • 作为唤醒源用

边沿计数

捕获输入的脉冲信号的边沿.

支持以下API:

  • Icu_Init: ICU初始化,设置计数模式
  • Icu_EnableEdgeCount: 使能ICU边沿计数,这之后开始计数
  • Icu_DisableEdgeCount:禁用ICU边沿计数,数据不会清零,会一直保持
  • Icu_GetEdgeNumbers: 获取当前ICU的边沿计数
  • Icu_ResetEdgeCount: 重置计数

下面例子,配置为边沿计数模式,对双边沿都进行计数:

img
from ref.[2]

边沿检测(Signal Edge Detection)

检测到对应类型边沿(上升沿、下降沿),会产生一个硬件中断,然后通知上层.

示例1:配置为检测下降沿,但通知函数设为NULL,因此即使能通知EnableNotification,也不会调用上层通知函数

  • Icu_EnableNotification: 使能通知功能. 需要搭配通知函数使用,否则无效
  • Icu_GetInputState: 获取输入状态,获取后状态重置为IDLE

img
from ref. [2]

示例2:启用通知功能,初始配置为检测下降沿,但在通知函数中修改为检测上升沿

  • Icu_SetActivationCondition: 变更激活条件,由下降沿变为上升沿
  • Icu_DisableNotification: 禁止通知

img
from ref. [2]

示例3:信号测量(signal measurement),测量信号的时间长度,支持低电平时长、高电平时长、周期时长、占空比

  • Icu_StartSignalMeasurement: 开始信号测量
  • Icu_GetTimeElapsed: 获取时间长度
  • Icu_GetDutyCycleValue:过去pwm的周期和占空比

img
from ref. [2]

示例4:时间戳(Timestamping)

1)线性buffer模式

在Bsw层,设置一个数组作为缓存buffer,记录一定连续数量的边沿时间戳

  • BufferSize,buffer元素个数. 设置BufferPtr size=4,对应4个黄色方块(buffer 4个元素),后面4个是指随着时间变化后的buffer

  • NotifyInterval,通知间隔. 根据设置的间隔大小进行触发通知,如设置为4,那么bufferPtr[3]存入数据时触发通知

  • Icu_SetActivationCondition,设置触发条件,如下降沿,即下降沿到来时,写一个时间戳到buffer中

  • Icu_GetTimestampIndex,当前时间戳目录,每当周期循环一遍(从0x0000->0xFFFF),index+1. 注意不是每写一个时间戳,index加1

  • Icu_StartTimestamp,激活时间戳功能. 线性buffer模式下,记录的buffer满了,就会停止时间戳的记录,需要手动再次激活

img

2)循环buffer模式

线性buffer写满后,会停止记录时间戳,需要调用Icu_StartTimestamp重新激活. 而循环buffer则会一直自动记录

注:目前还不确定buffer满后,从头开始记录,还是丢弃最开始记录的时间戳(个人推测是后者)

OCU驱动

OCU(Output Compare Unit,输出比较单元),类似于PWM的生成机制,计数器值达到设定阈值时,比较成功,就执行某个指定动作. OCU主要功能:

  • 开始或停止一个比较过程
  • 设置比较阈值
  • 使能或禁用通知机制
  • 获取计数值
  • 改变输出引脚状态
  • 触发硬件资源(如ADC、PWM等)

ADC驱动

功能:

  • 模拟信号 ➡ 数字信号
  • 封装转换信号的访问接口
  • 配置不同的模式
  • 对转换的一个通知机制

分组(ADC Groups):

将某些功能相近ADC Channels划分到某个组里(每组至少1个通道). 一个组必须在一个ADC硬件单元内,不能跨硬件单元组成ADC组

转换模式:

  • 循环转换
  • 单词转换

触发模式:

  • 硬件触发:配置后,可由其他外设触发ADC,如周期定时器,在定时中断内触发ADC;IO口上升沿触发ADC
  • 软件触发:用户对芯片软件触发寄存器写值触发ADC. 软件调用API,直接触发

Buffer初始化:

ADC结果最终需要存放到一个buffer数组(用户定义)中,供用户使用. 但如何将设定好的buffer自动存入ADC数据?

可以通过MCAL中的Adc_SetupResultBuffer注册数组

/*
如果我们的ADC0的一个ADC_Group_0 包含5个通道,我们要将结果存入ADC_SW_GRP_RES[5]数组
*/

// 申请数组存放ADC数据
Adc_ValueGroupType ADC_SW_GRP_RES[5];
// 注册指针到ADC0的group 0(AdcGroup0_0)
Adc_SetupResultBuffer(AdcConf_AdcGroup_AdcGroup0_0, ADC_SW_GRP_RES);

Stream模式:

ADC可以存放多个时刻的采样值. 相当于为每个通道申请一个数组,该数组能存放多个ADC值.

例如,假设ADC0包含ADC_Group_0组,其中5个通道,每个通道开启Stream模式,且深度为2. 那么存放结果的ADC_SW_GRP_RES数组需要存放5x2=10个元素

这10个数据的存放如下:

img

每个通道有个FIFO,每个FIFO深度2. 有2种模式:循环模式、线性模式,都是针对每个FIFO刷新数据的.

参考

[1] AutoSAR系列讲解(入门篇)4.2-BSW的I/O功能

[2] AutoSAR系列讲解(实践篇)8.2-IO相关驱动(上)

posted @ 2025-07-08 16:57  明明1109  阅读(292)  评论(0)    收藏  举报