关键词
TC397 官方例程;TC397 以太网例程;TC397 GETH;
简介
本篇为 Aurix TriCore TC397 以太网官方例程分析,重点关注其硬件行为
调试所用的开发板型号:KIT-A2G-TC397-5V-TFT
所使用的例程:Ethernet_1_KIT_TC397_TFT
英飞凌 TriCore 官方例程下载地址:
GitHub - Infineon/AURIX_code_examples
系列文章链接
TC397以太网例程 - 17.ECHO 应用 - 轮询定时器
TC397以太网例程 - 18.ECHO 应用 - 接收报文
目录
// 函数调用栈
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;
// --------------------------------------------------------
}
}
其中,有两点需要关注:
-
实际向硬件寄存器写入数据由函数 IfxAsclin_write8() 完成:txData->U = *data++;
-
串口占用标记由中断服务程序负责清除:asclin->txInProgress = FALSE;
4.串口初始化
串口初始化大致可以分为三个部分:
-
声明配置项并赋初值:波特率、FIFO 大小等默认值;
-
用户配置:中断优先级设置、波特率修改、IN/OUT 引脚定义等操作;
-
初始化 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;
}
这里主要关注以下三点:
-
ASCLIN 模块绑定:执行配置项初始化时便会进行 ASCLIN 模块的绑定(由参数直接传入);
-
中断相关:默认中断优先级为 0,服务请求对象为 CPU0;
-
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 时,中断控制器才会响应其中断请求;