[TriCore][官方例程][TC397以太网例程详解] - 4.ASCLIN 串口配置

关键词

TC397 官方例程;TC397 以太网例程;TC397 GETH;


简介

本篇为 Aurix TriCore TC397 以太网官方例程分析,重点关注其硬件行为

调试所用的开发板型号:KIT-A2G-TC397-5V-TFT

所使用的例程:Ethernet_1_KIT_TC397_TFT

英飞凌 TriCore 官方例程下载地址

GitHub - Infineon/AURIX_code_examples


系列文章链接

TC397以太网例程 - 1.概览

TC397以太网例程 - 2.STM 定时器初始化

TC397以太网例程 - 3.LwIP 配置及初始化

TC397以太网例程 - 4.ASCLIN 串口配置

TC397以太网例程 - 5.IP 地址声明

TC397以太网例程 - 6.内存 & 协议等初始化

TC397以太网例程 - 7.netif 网卡配置

TC397以太网例程 - 8.硬件初始化

TC397以太网例程 - 9.基本设置

TC397以太网例程 - 10.默认/用户配置

TC397以太网例程 - 11.RTL8211F 复位

TC397以太网例程 - 12.GETH 初始化

TC397以太网例程 - 13.PHY 初始化

TC397以太网例程 - 14.Tx/Rx 使能

TC397以太网例程 - 15.其他配置

TC397以太网例程 - 16.ECHO 应用 - 初始化

TC397以太网例程 - 17.ECHO 应用 - 轮询定时器

TC397以太网例程 - 18.ECHO 应用 - 接收报文


目录

1.串口相关的宏定义

2.ASCLIN 模块定义

3.串口发送的中断向量

4.串口初始化

4.1.配置项声明

4.2.配置项赋初值

4.3.用户配置

4.4.使用配置项初始化串口


// 函数调用栈
core0_main()
    |--> Ifx_Lwip_init()
        |--> initUART()

LwIP 的调试信息通过 ASCLIN 模块打印,因此需要在其他部分初始化前先配置该模块:

// Libraries/Ethernet/lwip/port/src/Ifx_Lwip.c
/* LWIP initialization function */
void Ifx_Lwip_init(eth_addr_t ethAddr)
{
    // 配置调试输出所需的 ASCLIN 串口
#ifdef __LWIP_DEBUG__ // 仅当该宏存在定义时才会进行 ASCLIN 的初始化
    //Init uart for debugging
    initUART();
#endif

注意,仅当启用调试信息时才会进行串口模块 ASCLIN 的初始化:

// Configurations/lwipopts.h
#define __LWIP_DEBUG__ /* Enable debugging through UART interface */

1.串口相关的宏定义

串口配置相关的宏定义如下所示:

// Libraries/UART/UART_Logging.c
// 串口波特率
#define SERIAL_BAUDRATE         115200                  /* Baud rate in bit/s */

// 串口模块及引脚选择 ASCLIN0
#define SERIAL_PIN_RX           IfxAsclin0_RXA_P14_1_IN /* RX pin of the board */
#define SERIAL_PIN_TX           IfxAsclin0_TX_P14_0_OUT /* TX pin of the board */

// 串口发送中断优先级 19
#define INTPRIO_ASCLIN0_TX      19                  /* Priority of the ISR */

// 缓冲区大小
#define ASC_TX_BUFFER_SIZE      64                  /* Definition of the buffer size */

串口选择 ASCLIN0 模块,发送中断优先级为 19(仅有输出功能,所以未配置接收中断),buffer 大小为 64KB

2.ASCLIN 模块定义

英飞凌对异步串口的定义如下所示:

// Libraries/iLLD/TC39B/Tricore/Asclin/Asc/IfxAsclin_Asc.h
/* Module Handle */
typedef struct
{
    Ifx_ASCLIN                   *asclin;                 /**< \brief pointer to ASCLIN registers */
    Ifx_Fifo                     *tx;                     /**< \brief Transmit FIFO buffer */
    Ifx_Fifo                     *rx;                     /**< \brief Receive FIFO buffer */
    volatile boolean              txInProgress;           /**< \brief Ongoing transfer. Will be set by IfxAsclin_Asc_initiateTransmission, and cleared by IfxAsclin_Asc_isrTransmit */
    volatile boolean              rxSwFifoOverflow;       /**< \brief Will be set by IfxAsclin_Asc_isrReceive if the SW Fifo overflowed */
    IfxAsclin_Asc_ErrorFlagsUnion errorFlags;             /**< \brief error reported by ASCLIN during runtime (written by IfxAsclin_Asc_isrError) */
    Ifx_DataBufferMode            dataBufferMode;         /**< \brief Rx buffer mode */
    volatile uint32               sendCount;              /**< \brief Number of byte that are send out, this value is reset with the function Asc_If_resetSendCount() */
    volatile Ifx_TickTime         txTimestamp;            /**< \brief Time stamp of the latest send byte */
} IfxAsclin_Asc;

其中,需要重点关注如下几点:

  • *asclin:ASCLIN 模块全部寄存器的定义,软件通过其与硬件交互;

  • txInProgress:该标志位指示当前模块是否被占用(串口处于发送状态),正常流程开始进行串口发送时,先将其置 TRUE,中断服务程序完成后,由中断服务程序将其置 FALSE;

  • sendCount:待发送的字节数;

3.串口发送的中断向量

UART/ASC 模式中,正常流程发送一个字符触发中断,后续字符的发送均由中断服务程序完成,该例程使用的串口发送的中断向量如下所示:

// Libraries/UART/UART_Logging.c
/* Adding the Interrupt Service Routine */
IFX_INTERRUPT(asclin0TxISR, 0, INTPRIO_ASCLIN0_TX); 
void asclin0TxISR(void)
{
    IfxAsclin_Asc_isrTransmit(&g_asc);
}

中断触发后跳转至 asclin0TxISR() 执行,具体的工作由 IfxAsclin_Asc_isrTransmit() 完成,这么做的目的是缩小中断向量的大小(中断服务例程仅包含简单的几条指令),具体处理中断请求的函数如下所示:

// Libraries/iLLD/TC39B/Tricore/Asclin/Asc/IfxAsclin_Asc.c
void IfxAsclin_Asc_isrTransmit(IfxAsclin_Asc *asclin)
{
    ...
    if (Ifx_Fifo_isEmpty(asclin->tx) == FALSE)
    {
        ...
            uint8          ascData[16]; // buffer
            ...
// --------------------------------------------------------
            // 计算需要发送的字节数量和 FIFO 剩余空间,FIFO 一次最大只能发送 16 字节的数据
            count            = Ifx_Fifo_readCount(asclin->tx); /*SW FIFO fill level*/
            hw_tx_fill_level = IfxAsclin_getTxFifoFillLevel(asclin->asclin);
            i_count          = (16 - hw_tx_fill_level);
            if (i_count > count)
            {
                i_count = count;
            }
// --------------------------------------------------------

// --------------------------------------------------------
            // 将数据保存至 buffer,随后通过串口发送
            Ifx_Fifo_read(asclin->tx, &ascData[0], i_count, TIME_NULL);
                |--> data  = Ifx_CircularBuffer_read8(&buffer, data, blockSize);
                |--> count = Ifx_Fifo_readEnd(fifo, count, blockSize);
            IfxAsclin_write8(asclin->asclin, &ascData[0], i_count);
                |--> txData->U = *data++;
// --------------------------------------------------------
        ...
    }
    else
    {
// --------------------------------------------------------
        // 解除串口占用
        /* Transmit buffer is empty */
        asclin->txInProgress = FALSE;
// --------------------------------------------------------
    }
}

其中,有两点需要关注:

  1. 实际向硬件寄存器写入数据由函数 IfxAsclin_write8() 完成:txData->U = *data++;

  2. 串口占用标记由中断服务程序负责清除:asclin->txInProgress = FALSE;

4.串口初始化

串口初始化大致可以分为三个部分:

  1. 声明配置项并赋初值:波特率、FIFO 大小等默认值;

  2. 用户配置:中断优先级设置、波特率修改、IN/OUT 引脚定义等操作;

  3. 初始化 ASCLIN 模块:将相关值写入内存或寄存器;

具体的函数如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
// --------------------------------------------------------
    // 声明配置项并赋初值
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module);
// --------------------------------------------------------

// --------------------------------------------------------
    // 用户配置
    /* Set the desired baud rate */
    ascConfig.baudrate.baudrate = SERIAL_BAUDRATE;
    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority = INTPRIO_ASCLIN0_TX;
    ascConfig.interrupt.typeOfService = IfxCpu_Irq_getTos(IfxCpu_getCoreIndex());
    /* FIFO configuration */
    ascConfig.txBuffer = &g_ascTxBuffer;
    ascConfig.txBufferSize = ASC_TX_BUFFER_SIZE;
    /* Port pins configuration */
    const IfxAsclin_Asc_Pins pins =
    {
        NULL_PTR,         IfxPort_InputMode_pullUp,     /* CTS pin not used                         */
        &SERIAL_PIN_RX,   IfxPort_InputMode_pullUp,     /* RX pin not used                          */
        NULL_PTR,         IfxPort_OutputMode_pushPull,  /* RTS pin not used                         */
        &SERIAL_PIN_TX,   IfxPort_OutputMode_pushPull,  /* TX pin                                   */
        IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;
// --------------------------------------------------------

// --------------------------------------------------------
    // 初始化 ASCLIN 模块(相关值写入)
    IfxAsclin_Asc_initModule(&g_asc, &ascConfig); /* Initialize module with above parameters  */
// --------------------------------------------------------
}

4.1.配置项声明

串口配置项保存在 ascConfig 中,其类型为 IfxAsclin_Asc_Config,具体如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
    // 声明配置项并赋初值
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module);
-------------------------------------------------------------------------------------

// Libraries/iLLD/TC39B/Tricore/Asclin/Asc/IfxAsclin_Asc.h
/* Configuration structure of the module */
typedef struct
{
    Ifx_ASCLIN                    *asclin;       /* pointer to ASCLIN registers */
    IfxAsclin_Asc_BaudRate         baudrate;     /* structure for baudrate */
    IfxAsclin_Asc_BitTimingControl bitTiming;    /* structure for bit timings */
    IfxAsclin_Asc_FrameControl     frame;        /* structure for frame control */
    IfxAsclin_Asc_FifoControl      fifo;         /* structure for FIFO control */
    IfxAsclin_Asc_InterruptConfig  interrupt;    /* structure for interrupt configuration */
    IFX_CONST IfxAsclin_Asc_Pins  *pins;         /* structure for ASC pins */
    IfxAsclin_ClockSource          clockSource;  /* CSR.CLKSEL, clock source selection */
    IfxAsclin_Asc_ErrorFlagsUnion  errorFlags;   /* structure for error flags */
    Ifx_SizeT                      txBufferSize; /* Size of the tx buffer */
    void                          *txBuffer;     /* The buffer parameter must point on a free memory location where the buffer object will be Initialised.
                                                  *
                                                  * The Size of this area must be at least equals to "txBufferSize + sizeof(Ifx_Fifo) + 8". Not tacking this in account may result in unpredictable behavior.
                                                  *
                                                  * If set to NULL_PTR, the buffer will  be allocated dynamically according to txBufferSize */
    Ifx_SizeT rxBufferSize;                      /* Size of the rx buffer */
    void     *rxBuffer;                          /* The buffer parameter must point on a free memory location where the buffer object will be Initialised.
                                                  *
                                                  * The Size of this area must be at least equals to "rxBufferSize + sizeof(Ifx_Fifo) + 8". Not tacking this in account may result in unpredictable behavior.
                                                  *
                                                  * If set to NULL, the buffer will be allocated dynamically according to rxBufferSize */
    boolean            loopBack;                 /* IOCR.LB, loop back mode selection, 0 for disable, 1 for enable */
    Ifx_DataBufferMode dataBufferMode;           /* Rx buffer mode */
} IfxAsclin_Asc_Config;

这里需要注意的是 *asclin 模块是如何进行绑定的,以及中断相关的配置

4.2.配置项赋初值

配置项结构体声明后需要写入初始值,如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
    // 声明配置项并赋初值
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module);

首先需要绑定对应的 ASCLIN 模块,在前文的串口相关宏定义中可以看到,其定义了串口所使用的引脚:

// Libraries/UART/UART_Logging.c
#define SERIAL_PIN_RX           IfxAsclin0_RXA_P14_1_IN   /* RX pin of the board */
#define SERIAL_PIN_TX           IfxAsclin0_TX_P14_0_OUT   /* TX pin of the board */

此处 IfxAsclin0_TX_P14_0_OUT 引脚类型为 IfxAsclin_Tx_Out,为一个结构体,该结构体中包含了绑定的 ASCLIN 模块(引脚创建时绑定):

// Libraries/iLLD/TC39B/Tricore/_PinMap/IfxAsclin_PinMap.h
/* TX pin mapping structure */
typedef const struct
{
    Ifx_ASCLIN*       module;   /* Base address */
    IfxPort_Pin       pin;      /* Port pin */
    IfxPort_OutputIdx select;   /* Port control code */
} IfxAsclin_Tx_Out;
----------------------------------------------------------------------------

// Libraries/iLLD/TC39B/Tricore/_PinMap/IfxAsclin_PinMap.c
IfxAsclin_Tx_Out IfxAsclin0_TX_P14_0_OUT = {&MODULE_ASCLIN0, {&MODULE_P14, 0}, IfxPort_OutputIdx_alt2};

因此,通过引脚可以查找到对应的 ASCLIN 模块,具体如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module); // SERIAL_PIN_TX.module --> &MODULE_ASCLIN0

IfxAsclin_Asc_initModuleConfig() 设置配置项的初始值(默认值),具体如下所示:

// Libraries/iLLD/TC39B/Tricore/Asclin/Asc/IfxAsclin_Asc.c
void IfxAsclin_Asc_initModuleConfig(IfxAsclin_Asc_Config *config, Ifx_ASCLIN *asclin)
{
    config->asclin = asclin;

    /* loop back disabled */
    config->loopBack = FALSE;                                                  /* no loop back*/

    /* Default values for baudrate */
    config->clockSource           = IfxAsclin_ClockSource_ascFastClock;        /* Asclin fast clock, fasclinf*/
    config->baudrate.prescaler    = 1;                                         /* default prescaler*/
    config->baudrate.baudrate     = 115200;                                    /* default baudrate (the fractional dividier setup will be calculated in initModule*/
    config->baudrate.oversampling = IfxAsclin_OversamplingFactor_4;            /* default oversampling factor*/

    /* Default Values for Bit Timings */
    ...
    /* Default Values for Frame Control */
    ...

    /* Default Values for Fifo Control */
    config->fifo.inWidth              = IfxAsclin_TxFifoInletWidth_1;          /* 8-bit wide write*/
    config->fifo.outWidth             = IfxAsclin_RxFifoOutletWidth_1;         /* 8-bit wide read*/
    config->fifo.txFifoInterruptLevel = IfxAsclin_TxFifoInterruptLevel_0;      /* txFifoInterruptLevel = 0. optimised to write upto 16 bytes at a time */
    config->fifo.rxFifoInterruptLevel = IfxAsclin_RxFifoInterruptLevel_1;
    config->fifo.buffMode             = IfxAsclin_ReceiveBufferMode_rxFifo;    /* RxFIFO*/
    config->fifo.txFifoInterruptMode  = IfxAsclin_FifoInterruptMode_combined;
    config->fifo.rxFifoInterruptMode  = IfxAsclin_FifoInterruptMode_combined;

    /* Default Values for Interrupt Config */
    config->interrupt.rxPriority    = 0;                                /* receive interrupt priority 0*/
    config->interrupt.txPriority    = 0;                                /* transmit interrupt priority 0*/
    config->interrupt.erPriority    = 0;                                /* error interrupt priority 0*/
    config->interrupt.typeOfService = IfxSrc_Tos_cpu0;                  /* type of service CPU0*/

    /* Enable error flags */
    config->errorFlags.ALL = ~0;                                        /* all error flags enabled*/

    /* init pointers */
    ...

    config->txBufferSize   = 0;                                         /* Rx Fifo buffer size*/
    config->rxBufferSize   = 0;                                         /* Rx Fifo buffer size*/

    config->dataBufferMode = Ifx_DataBufferMode_normal;
}

这里主要关注以下三点:

  1. ASCLIN 模块绑定:执行配置项初始化时便会进行 ASCLIN 模块的绑定(由参数直接传入);

  2. 中断相关:默认中断优先级为 0,服务请求对象为 CPU0;

  3. Buffer Mode:默认值为普通模式 Ifx_DataBufferMode_normal;

4.3.用户配置

写入串口默认配置后,需要将用户设置的波特率、中断以及 FIFO 相关值写入(修改)配置项,如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
// --------------------------------------------------------
    // 声明配置项并赋初值
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module);
// --------------------------------------------------------

// --------------------------------------------------------
    // 用户配置
    /* Set the desired baud rate */
    ascConfig.baudrate.baudrate = SERIAL_BAUDRATE;
    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority = INTPRIO_ASCLIN0_TX;
    ascConfig.interrupt.typeOfService = IfxCpu_Irq_getTos(IfxCpu_getCoreIndex());
    /* FIFO configuration */
    ascConfig.txBuffer = &g_ascTxBuffer;
    ascConfig.txBufferSize = ASC_TX_BUFFER_SIZE;
    /* Port pins configuration */
    const IfxAsclin_Asc_Pins pins =
    {
        NULL_PTR,         IfxPort_InputMode_pullUp,     /* CTS pin not used                         */
        &SERIAL_PIN_RX,   IfxPort_InputMode_pullUp,     /* RX pin not used                          */
        NULL_PTR,         IfxPort_OutputMode_pushPull,  /* RTS pin not used                         */
        &SERIAL_PIN_TX,   IfxPort_OutputMode_pushPull,  /* TX pin                                   */
        IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;
// --------------------------------------------------------

其中,中断优先级 INTPRIO_ASCLIN0_TX = 19,但中断服务对象并未直接指明,而是采用 IfxCpu_getCoreIndex() 间接指定,如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
    ...
    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority = INTPRIO_ASCLIN0_TX;
    ascConfig.interrupt.typeOfService = IfxCpu_Irq_getTos(IfxCpu_getCoreIndex());
----------------------------------------------------------------------------------

// Libraries/iLLD/TC39B/Tricore/Cpu/Std/IfxCpu.h
IFX_INLINE IfxCpu_ResourceCpu IfxCpu_getCoreIndex(void)
{
    uint32 reg;
    reg = __mfcr(CPU_CORE_ID);
    return (IfxCpu_ResourceCpu)__minu(reg, 5);
}
----------------------------------------------------------------------------------

// Libraries/iLLD/TC39B/Tricore/Cpu/Irq/IfxCpu_Irq.c
/* API to get type of service of the caller CPU. */
IfxSrc_Tos IfxCpu_Irq_getTos(IfxCpu_ResourceCpu coreId)
{
    const IfxSrc_Tos tos[IFXCPU_NUM_MODULES] = {
        IfxSrc_Tos_cpu0, IfxSrc_Tos_cpu1,
        IfxSrc_Tos_cpu2, IfxSrc_Tos_cpu3,
        IfxSrc_Tos_cpu4, IfxSrc_Tos_cpu5,
    };

    return tos[coreId];
}
----------------------------------------------------------------------------------

// Libraries/iLLD/TC39B/Tricore/_Impl/IfxSrc_cfg.h
/* Identifier of interrupt service provider, which handles the interrupt service request. */
typedef enum
{
    IfxSrc_Tos_cpu0 = 0,  /* CPU0 interrupt service provider, which handles the interrupt service request. */
    IfxSrc_Tos_dma  = 1,  /* DMA  interrupt service provider, which handles the interrupt service request. */
    IfxSrc_Tos_cpu1 = 2,  /* CPU1 interrupt service provider, which handles the interrupt service request. */
    IfxSrc_Tos_cpu2 = 3,  /* CPU2 interrupt service provider, which handles the interrupt service request. */
    IfxSrc_Tos_cpu3 = 4,  /* CPU3 interrupt service provider, which handles the interrupt service request. */
    IfxSrc_Tos_cpu4 = 5,  /* CPU4 interrupt service provider, which handles the interrupt service request. */
    IfxSrc_Tos_cpu5 = 6   /* CPU5 interrupt service provider, which handles the interrupt service request. */
} IfxSrc_Tos;

IfxCpu_getCoreIndex() 通过 MFCR 指令,从 CPU_CORE_ID 寄存器中获取硬件的 CPU ID,然后通过 IfxCpu_Irq_getTos() 转换为服务请求对象的 ID(因为多了一个 DMA,所以两个编号存在差异)

4.4.使用配置项初始化串口

使用配置项初始化 ASCLIN 模块,如下所示:

// Libraries/UART/UART_Logging.c
void initUART(void)
{
    // 声明配置项并赋初值
    /* Initialize an instance of IfxAsclin_Asc_Config with default values */
    IfxAsclin_Asc_Config ascConfig;
    IfxAsclin_Asc_initModuleConfig(&ascConfig, SERIAL_PIN_TX.module);

    // 用户配置
    /* Set the desired baud rate */
    ascConfig.baudrate.baudrate = SERIAL_BAUDRATE;
    /* ISR priorities and interrupt target */
    ascConfig.interrupt.txPriority = INTPRIO_ASCLIN0_TX;
    ascConfig.interrupt.typeOfService = IfxCpu_Irq_getTos(IfxCpu_getCoreIndex());
    /* FIFO configuration */
    ascConfig.txBuffer = &g_ascTxBuffer;
    ascConfig.txBufferSize = ASC_TX_BUFFER_SIZE;
    /* Port pins configuration */
    const IfxAsclin_Asc_Pins pins =
    {
        NULL_PTR,         IfxPort_InputMode_pullUp,     /* CTS pin not used                         */
        &SERIAL_PIN_RX,   IfxPort_InputMode_pullUp,     /* RX pin not used                          */
        NULL_PTR,         IfxPort_OutputMode_pushPull,  /* RTS pin not used                         */
        &SERIAL_PIN_TX,   IfxPort_OutputMode_pushPull,  /* TX pin                                   */
        IfxPort_PadDriver_cmosAutomotiveSpeed1
    };
    ascConfig.pins = &pins;

    // 初始化 ASCLIN 模块(相关值写入)
    IfxAsclin_Asc_initModule(&g_asc, &ascConfig);        /* Initialize module with above parameters  */
}

串口初始化具体可以分为如下几个部分:

  • 获取 ASCLIN 寄存器:从配置项 ascConfig 中获取 ASCLIN 寄存器,SFR 意为 Special Function Registers,是模块所属寄存器的统称;

  • 模块使能、中断等初始化:发送模块使能请求、波特率设置、中断基本信息设置等;

  • 引脚设置;

  • 时钟使能;

  • 标志位初始化;

  • 缓冲区设置/清空;

  • FIFO 设置:这里会初始化软件的 FIFO,包括软件分配内存、元素大小设置、元素计数清空等;

  • 中断请求管理单元设置(SRC):设置并使能串口对应的 SRC;

  • 清空 ASCLIN TXDATA/RXDATA 寄存器并允许收发;

// Libraries/iLLD/TC39B/Tricore/Asclin/Asc/IfxAsclin_Asc.c
IfxAsclin_Status IfxAsclin_Asc_initModule(IfxAsclin_Asc *asclin, const IfxAsclin_Asc_Config *config)
{
// --------------------------------------------------------
    // 获取 ASCLIN 相关寄存器
    Ifx_ASCLIN      *asclinSFR = config->asclin;                        /* pointer to ASCLIN registers*/
    ...
    asclin->asclin = asclinSFR;                                         /* adding register pointer to module handler*/
// --------------------------------------------------------

// --------------------------------------------------------
    // 模块使能、中断等初始化
    IfxAsclin_enableModule(asclinSFR);                                  /* enabling the module*/
    IfxAsclin_setClockSource(asclinSFR, IfxAsclin_ClockSource_noClock); /* disabling the clock*/
    ...
    IfxAsclin_setClockSource(asclinSFR, config->clockSource);           /* temporary set the clock source for baudrate configuration*/
    status = (IfxAsclin_Status)IfxAsclin_setBitTiming(asclinSFR,        /* setting the baudrate bit fields to generate the required baudrate*/
        config->baudrate.baudrate,
        config->baudrate.oversampling,
        config->bitTiming.samplePointPosition,
        config->bitTiming.medianFilter);
    IfxAsclin_setClockSource(asclinSFR, IfxAsclin_ClockSource_noClock);              /* disabling the clock again*/
    ...
    IfxAsclin_setTxFifoInterruptLevel(asclinSFR, config->fifo.txFifoInterruptLevel); /* setting Tx FIFO level at which a Tx interrupt will be triggered*/
    IfxAsclin_setRxFifoInterruptLevel(asclinSFR, config->fifo.rxFifoInterruptLevel); /* setting Rx FIFO interrupt level at which a Rx interrupt will be triggered*/
    IfxAsclin_setTxFifoInterruptMode(asclinSFR, config->fifo.txFifoInterruptMode);   /* setting Tx FIFO interrupt generation mode */
    IfxAsclin_setRxFifoInterruptMode(asclinSFR, config->fifo.rxFifoInterruptMode);   /* setting Rx FIFO interrupt generation mode */
    ...
// --------------------------------------------------------

// --------------------------------------------------------
    // 引脚设置
    /* Pin mapping */
    ...
// --------------------------------------------------------

// --------------------------------------------------------
    // 使能时钟
    IfxAsclin_setClockSource(asclinSFR, config->clockSource); /* select the clock source*/
    ...
// --------------------------------------------------------

// --------------------------------------------------------
    // 标志位设置
    /* HW error flags */
    ...

    /* transmission flags */
    asclin->rxSwFifoOverflow = FALSE;
    asclin->txInProgress     = FALSE;
// --------------------------------------------------------

// --------------------------------------------------------
    // 缓冲区设置
    /* Buffer mode */
    ...
// --------------------------------------------------------

// --------------------------------------------------------
    // FIFO 设置
    /* SW Fifos */
    if (config->txBuffer != NULL_PTR)
    {
        asclin->tx = Ifx_Fifo_init(config->txBuffer, config->txBufferSize, elementSize);
            |--> fifo = (Ifx_Fifo *)buffer;
            |--> ...
            |--> fifo->shared.count = 0;
    }
    ...
// --------------------------------------------------------

// --------------------------------------------------------
    // 中断请求管理单元设置(SRC)
    /* initialising the interrupts */
    IfxSrc_Tos tos = config->interrupt.typeOfService;
    if ((config->interrupt.rxPriority > 0) || (tos == IfxSrc_Tos_dma))
    ...
    
    if ((config->interrupt.txPriority > 0) || (tos == IfxSrc_Tos_dma))
    {
        volatile Ifx_SRC_SRCR *src;
        src = IfxAsclin_getSrcPointerTx(asclinSFR);
        IfxSrc_init(src, tos, config->interrupt.txPriority);
            |--> src->B.SRPN = priority;     // 中断优先级
            |--> src->B.TOS  = typOfService; // 中断请求对象
            |--> IfxSrc_clearRequest(src);
                |--> src->B.CLRR = 1;
        IfxAsclin_enableTxFifoFillLevelFlag(asclinSFR, TRUE);
            |--> asclin->FLAGSENABLE.B.TFLE = enable ? 1 : 0;
        IfxSrc_enable(src);
            |--> src->B.SRE = 1;  // SRC 中断使能,允许中断控制器响应该 SRC 的中断请求
    }
    
    if (config->interrupt.erPriority > 0) /*These interrupts are not serviced by dma*/
    ...
// --------------------------------------------------------

// --------------------------------------------------------
    // 清空 ASCLIN TXDATA 并允许收发
    /* enable transfers */
    IfxAsclin_enableRxFifoInlet(asclinSFR, TRUE);  // enabling Rx FIFO for recieving
        |--> asclin->RXFIFOCON.B.ENI = enable ? 1 : 0;
    IfxAsclin_enableTxFifoOutlet(asclinSFR, TRUE); // enabling Tx FIFO for transmitting
        |--> asclin->TXFIFOCON.B.ENO = enable ? 1 : 0;
    // 清空 ASCLIN RXDATA 并允许收发
    IfxAsclin_flushRxFifo(asclinSFR);              // flushing Rx FIFO
        |--> asclin->RXFIFOCON.B.FLUSH = 1;
    IfxAsclin_flushTxFifo(asclinSFR);              // flushing Tx FIFO
        |--> asclin->TXFIFOCON.B.FLUSH = 1;
// --------------------------------------------------------

    return status;
}

其中,有几点需要注意:

  • 设置波特率时需要先打开时钟,设置完成后需要禁用时钟,在完成一些基本寄存器的初始化后再重新使能时钟;

  • 串口中断优先级、服务请求对象等,需要写入 ASCLIN 模块相关的 SRC 寄存器,而 SRC 寄存器实际上由中断控制器统一负责管理;

  • 仅当 SRC 寄存器的中断使能标志位 SRC.SRE = 1 时,中断控制器才会响应其中断请求;


下一篇:TC397以太网例程 - 5.IP 地址声明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值