MCAL配置中Port和Dio模块及IO抽象层源码分析详解

Port及Dio模块是独立于MCU时钟的两个模块,因此最容易上手,不过在配置前需要充分了解硬件原理图以及硬件手册中的接口相关内容。

1. Port界面分析

在Port界面中,分为General及PortContainer两个配置选项卡。其中Genaral选项卡中可配置是否使用DET监控(DevErrorDetect)、是否使能SafetyCheck(PortSafetyEnable)以及相关API是否能使用。

在PortContainer选项卡中,显示了TC377的所有Port号以及相关pin脚数量。

在每一个Port选项卡中,包含了其中每一个Pin脚的方向、复用模式、初始电压状态等属性。在下一节中将结合数据手册和硬件原理图对部分重要选项作详细介绍。

2. Port关键配置选项

①PortPinDirection

这个选项的含义很好理解,讨论这个选项的目的是区别PORT_PIN_OUT和PORT_PIN_IN两种配置对其他选项的影响。两者的其余可配置项基本是相反的,暗显的选项在生成代码时不会被包含,在配置时可以不予考虑。

②PortPinInitialMode

该选项对PORT_PIN_OUT有作用,选项中包含GPIO和ALT1~ALT7,分别对应数据手册中的O0至O7部分。以P00.0为例,针对原理图中的定义,该引脚用作CAN10的TXD口,在数据手册中对应于O5类型的复用模式,故选择ALT5。

③PortPinLevelValue

该选项对PORT_PIN_OUT有作用,指定该Pin脚的初始输出电压状态,和其他连接芯片的输入初始状态有关,一般配置为PORT_PIN_LEVEL_LOW。但也有特殊情况,比如某个唤醒引脚,工作时处于低电压,上电时需要在程序中手动将该引脚拉至低电压,故配置时将其置为PORT_PIN_LEVEL_HIGH。

④PortPinOutputPadDriveStrength

该选项对PORT_PIN_OUT有作用,指定输出端口的驱动强度。在当前的TC3XX系列芯片中,大多数引脚都可配置为PORT_PIN_DEFAULT_DRIVER。特例为:RGMII的以太网数据发送端口配置为PORT_PIN_RGMII_DRIVER、PWM波输出端口需配置为PORT_PIN_MEDIUM_DRIVER。

⑤PortPinOutputPinDriveMode

该选项对PORT_PIN_OUT有作用,指定输出端口的驱动模式,分为推挽输出和开漏输出。两种模式的区别如下:1.推挽输出:能输出真正的高低电平,两种电平都具有驱动能力;2.开漏输出:默认只能输出低电平,没有能力输出高电平驱动负载,需借助外部上拉电阻才可输出高电平。

在配置时一般会选择推挽输出,并将初始电压设置为低电频。若芯片在上电时发生漏电现象,则需将初始电压配置为高电压,并设置开漏输出以组成高阻态。

⑥PortPinInputPullResistor

指定输入引脚电压在处理时按照上拉、下拉或按照实际电压值处理。一般此项配置为NO PULL,读取实际电压值即可。

⑦PortPinInputPadLevel

指定输入电平的类型,当前默认选择为CMOS类型,但在千兆以太网输入的前提下,该选项应当为RGMII类型。

3. Dio界面分析

Dio模块存在的目的是可通过上层控制Port口的电平值,同时也可读出该电平值。在Dio界面中,分为General及DioPort两个配置选项卡。其中General选项卡中包含了DET使能、SafetyCheck等类似于Port界面的选项。

在DioPort选项卡中,显示了TC377的所有能够被上层访问的DioPort信息。

4. Dio关键配置选项

①DioPortId

需要被上层访问的Port ID号。

②DioChannelId

需要被上层访问的Channel ID号,也就是Pin脚号。

5. IoHwAb层相关源码

DIO部分包含输入和输出部分的引脚编号定义。值得注意的是,管理它们使用的是枚举体,最后会使用IoHwAb_Dx_Signal_MAX得到引脚总数。之后定义了状态的输入和输出函数。这两个函数会被其他模块使用,比如电源管理模块、CAN TRCV模块等等。

typedef enum
{
    MCU_CAN00_DIS_FB,
    MCU_CAN00_ERR_N,
    AURIX_HWCONFIG_4,
    AURIX_HWCONFIG_5,
    MCU_J3_SW_IRQOUT_N,
    MCU_J3_TICKOUT_MCU,
    AURIX_HWCONFIG_2,
    AURIX_HWCONFIG_3,
    AURIX_HWCONFIG_6,
    AURIX_HWCONFIG_1,
    
    IoHwAb_DI_Signal_MAX
} IoHwAb_DI_Signal;

typedef enum
{
  MCU_CAN00_EN,
  MCU_CAN00_STB_N,
  MCU_9000BR_DISB,
  MCU_9000BR_PHYRSTB,
  MCU_7920_EN,
  MCU_2179_Power_Down,
  MCU_RSTOUT_J3,
  MCU_J3_WKUPIN_N,
  MCU_SYS_5V0_EN,
  MCU_SYS_1V2_EN,
  MCU_SYS_0V9_EN,
  MCU_WDO,
  MCU_SMU_FSP,
  MCU_CAM_3V3_EN,
  MCU_J3_SPI2_M_INT,
  MCU_J3_SPI0_M_INT,
  
  IoHwAb_DO_Signal_MAX
} IoHwAb_DO_Signal;

extern Std_ReturnType IoHwAb_DIO_GetStatus(IoHwAb_DI_Signal in_signal, IOHWAB_DIO_Status* out_status);
extern Std_ReturnType IoHwAb_DIO_SetStatus(IoHwAb_DO_Signal in_signal, IOHWAB_DIO_Status in_status);

在输入和输出函数中,核心的函数是Dio_ReadChannel和Dio_WriteChannel。

Std_ReturnType IoHwAb_DIO_GetStatus(IoHwAb_DI_Signal in_signal, IOHWAB_DIO_Status* out_status)
{
    Std_ReturnType op_status = E_OK;

    if (in_signal > IoHwAb_DI_Signal_MAX)
    {
        op_status = E_NOT_OK;
    }
    else
    {
        *out_status = (IOHWAB_DIO_Status)Dio_ReadChannel(IoHwAb_DI_Channels[in_signal]);
    }

    return op_status;
}

Std_ReturnType IoHwAb_DIO_SetStatus(IoHwAb_DO_Signal in_signal, IOHWAB_DIO_Status in_status)
{
    Std_ReturnType op_status = E_OK;

    if (in_signal > IoHwAb_DO_Signal_MAX)
    {
        op_status = E_NOT_OK;
    }
    else
    {
        Dio_WriteChannel(IoHwAb_DO_Channels[in_signal], (Dio_LevelType)in_status);
    }

    return op_status;
}
物联沃分享整理
物联沃-IOTWORD物联网 » MCAL配置中Port和Dio模块及IO抽象层源码分析详解

发表评论