文章目录
- 1.前言
- 2.TJA1101简介
- 3.TJA1101调试
- 3.1 硬件
- 3.1.1 整体框图
- 3.1.2 评估板
- 3.1.2.1 参考原理图
- 3.1.2.2 引脚说明
- 3.1.3 转接板
- 3.1.3.1 参考原理图
- 3.1.3.2 模式配置
- 3.1.3.3 原理介绍
- 3.2 软件
- 3.2.1 物理层(TJA1101):
- 3.2.2 数据链路层(S32K148):
- 3.2.3 主要代码
- 3.3 测试
- 3.3.1 测试normal mode
- 3.3.2 测试link up 和 link down
- 3.3.3 测试wake up
- 4.参考资料
1.前言
如上图所示,为了适应车身越来越多的ECU节点,汽车电子架构正在从传统的分布式往集中式(Domain、Zonal)转变。在这转变的过程中,除了传统的CAN,LIN节点变多之外,汽车以太网也开始被广泛的使用。
以下图(传统的分布式架构)为例,汽车以太网主要用于大数据传输的场合,如摄像头,雷达,显示,网关等。
在CAN、LIN收发器占据大部分市场份额的NXP也早在2017年推出了百兆车载以太网PHY芯片-TJA1100,随后又推出了TJA1101,TJA1102等产品,roadmap如下所示,下文将介绍如何快速调试TJA1101。
2.TJA1101简介
TJA1101为单端口IEEE 802.3bw(100BASE-T1) PHY,符合功能安全ASIL-A。可通过非屏蔽双绞线(UTP)电缆提供100Mbit/s的发送和接收能力,同时针对耦合到UTP线路的容性信号耦合进行了优化,支持至少15米的电流长度。TJA1101与介质访问控制单元(MAC)的通信接口为MII或者RMII。
TJA1101支持符合OPEN联盟TC10标准的睡眠和唤醒转发解决方案,具体如下,同时拥有和唤醒线路相关的本地唤醒引脚。
- 全局系统唤醒
- 通过总线进行可靠的远程唤醒检测
- PHY层级唤醒转发
- 进入睡眠时的握手确认
- 节省一个额外的唤醒线路
3.TJA1101调试
目前TJA1101系列主推的是TJA1101BHN,但是笔者手上只有S32K148+TJA1101AHN的板子,TJA1101AHN和TJA1101BHN是软硬件兼容的,这里就以TJA1101AHN为例,介绍调试相关的内容。
3.1 硬件
测试环境主要由两块板子组成,一块S32K148评估板,用于驱动TJA1101,并发送数据;一块以太网转接板,将车载以太网信号转为工业以太网信号,方便在电脑上查看。
3.1.1 整体框图
整个测试环境的框图如下所示:
3.1.2 评估板
对于TJA1101的调试工作在S32K148评估板完成,如下是S32K148评估板有关以太网部份的介绍。
3.1.2.1 参考原理图
TJA1101的推荐电路图如下所示,
其中使用本地25MHz晶振的MII和RMII连接方式如下图所示,
3.1.2.2 引脚说明
TJA1101和S32K148的接口主要是®MII和SMI,S32K148用到的引脚以及功能定义如下:
同时,TJA1101有一些引脚具有pin strapping的功能,如下所示:(红框中是S32K148板子的实际配置)
3.1.3 转接板
以太网转接板主要元器件为一颗工业以太网PHY+以太网PHY,然后都配置成Reverse MII模式,用来实现车载以太网的信号转换成传统的工业以太网的信号
3.1.3.1 参考原理图
Reverse MII模式下的TJA1101推荐原理图如下:
3.1.3.2 模式配置
参考上一章节有关pin strapping的描述,转接板上TJA1101的配置为:Master,自主模式,Reverse MII。
3.1.3.3 原理介绍
如果需要深入了解转接板的原理图,可以查看胡工的公众号文章,链接如下:
- 汽车以太网(100BASE-T1)转工业以太网(100BASE-TX)转换器工作原理介绍 (qq.com)
3.2 软件
接下来是软件的配置介绍,本次对于TJA1101的调试基于S32DS 2.2自带的如下例程进行修改。
打开例程后,图形化界面相关的组件有三个,其中GPIO口的配置参考3.1.2.2章节进行设置,phy和mac的设置介绍如下。
3.2.1 物理层(TJA1101):
打开phy组件的图形化界面,如下所示:
其中,有四项配置说明下:
- Address设置需要和pin strapping的设置匹配,或者使用广播地址0x00
- PHY Role,设置为自动,跟随pin strapping,为从机模式
- link Up Event Callback,填充link up事件发生时调用的回调函数名称
- link Down Event Callback,填充link down事件发生时调用的回调函数名称
3.2.2 数据链路层(S32K148):
打开ethernet组件的图形化界面,如下所示:
其中,有两项配置说明下:
- MAC Address,测试时随便填充即可,实际使用时车厂统一分配
- MII configuration,选择模式,速度以及全双工/半双工
3.2.3 主要代码
#define GPIO_PORT PTE
#define PCC_CLOCK PCC_PORTE_CLOCK
#define LED1_RED (1 << 21U)
#define LED2_YELLOW (1 << 22U)
#define LED3_BLUE (1 << 23U)
#define PTB_PHY_INT (1 << 20U)
#define PTC_BTN0 (1 << 12U)
#define PTC_BTN1 (1 << 13U)
#define PHY_CONFIG1 18U
#define PHY_CONFIG1_FWDREM 0x0004U
#define PHY_EXTENDED_CTRL_ADDR 17U
#define PHY_EXTENDED_CTRL_CONFIG_EN 0x0004U
#define PHY_COM_CONFIG 27U
#define PHY_COM_CONFIG_WAKE 0x0040U
static uint8_t srcMacaddress[]={0x11,0x22,0x33,0x44,0x55,0x99};
typedef struct {
uint8_t destAddr[6];
uint8_t srcAddr[6];
uint16_t length;
uint8_t payload[1500];
} mac_frame_t;
void copyBuff(uint8_t *dest, uint8_t *src, uint32_t len)
{
uint32_t i;
for (i = 0; i < len; i++)
{
dest[i] = src[i];
}
}
void rx_callback(uint8_t instance, enet_event_t event, uint8_t ring)
{
(void)instance;
if (event == ENET_RX_EVENT)
{
enet_buffer_t buff;
status_t status;
status = ENET_DRV_ReadFrame(INST_ETHERNET1, ring, &buff, NULL);
if (status == STATUS_SUCCESS)
{
mac_frame_t *frame;
frame = (mac_frame_t *) buff.data;
/* You can process the payload here */
(void)frame->payload;
// /*turn off Blue led*/
// PINS_DRV_SetPins(GPIO_PORT, LED3_BLUE);
ENET_DRV_ProvideRxBuff(INST_ETHERNET1, ring, &buff);
}
}
}
/* Port C IRQ handler */
void portc_Handler(void)
{
uint32_t flags;
static bool loopback;
static phy_role_t phyRole = PHY_ROLE_MASTER;
uint32_t delay = 1000000U;
do
{
/* wait some time to allow capturing pushing multiple buttons at once */
delay--;
}
while(delay != 0);
flags = PINS_DRV_GetPortIntFlag(PORTC);
if ((flags & (PTC_BTN1 | PTC_BTN0)) == (PTC_BTN1 | PTC_BTN0))
{
/* both buttons pressed - change master/slave settings */
PHY_SetRole(0, phyRole);
phyRole = (phyRole == PHY_ROLE_MASTER) ? (PHY_ROLE_SLAVE) : (PHY_ROLE_MASTER);
}
else
{
if ((flags & PTC_BTN1) != 0U)
{
PHY_Sleep(0);
}
if ((flags & PTC_BTN0) != 0U)
{
if (loopback)
{
PHY_SetLoopback(0, PHY_LOOPBACK_NONE);
}
else
{
PHY_SetLoopback(0, PHY_LOOPBACK_INTERNAL);
}
loopback = !loopback;
}
}
/* Clear interrupt flag */
PINS_DRV_ClearPortIntFlagCmd(PORTC);
}
/* Link up callback */
void link_up(uint8_t phy)
{
if (phy == 0U)
{
/* if link up,turn off red led and turn on yellow led*/
PINS_DRV_ClearPins(GPIO_PORT, LED2_YELLOW);
PINS_DRV_SetPins(GPIO_PORT, LED1_RED);
PINS_DRV_SetPins(GPIO_PORT, LED3_BLUE);
}
}
/* Link down callback */
void link_down(uint8_t phy)
{
if (phy == 0U)
{
/* set PTE21 to low for turning on Red led*/
PINS_DRV_ClearPins(GPIO_PORT, LED1_RED);
PINS_DRV_SetPins(GPIO_PORT, LED2_YELLOW);
PINS_DRV_SetPins(GPIO_PORT, LED3_BLUE);
}
}
/*!
\brief The main function for the project.
\details The startup initialization sequence is the following:
* - startup asm routine
* - main()
*/
int main(void)
{
/* Write your local variable definition here */
enet_buffer_t buff;
mac_frame_t frame;
uint8_t i;
status_t ENET_status;
static uint16_t extCtrl = 0;
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
#ifdef PEX_RTOS_INIT
PEX_RTOS_INIT(); /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
#endif
/*** End of Processor Expert internal initialization. ***/
/* Initialize and configure clocks
* - see clock manager component for details
*/
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
/* Initialize pins
* - See PinSettings component for more info
*/
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);
/* Initialize ENET instance */
ENET_DRV_Init(INST_ETHERNET1, ðernet1_State, ðernet1_InitConfig0, ethernet1_buffConfigArr0, ethernet1_MacAddr);
ENET_DRV_EnableMDIO(INST_ETHERNET1, false);
/* turn on Red led for init */
PINS_DRV_ClearPins(GPIO_PORT, LED1_RED);
PHY_FrameworkInit(phyConfig, phyDrivers);
PHY_Init(0);
/* make custom settings */
PHY_RMR(0, PHY_EXTENDED_CTRL_ADDR, PHY_EXTENDED_CTRL_CONFIG_EN, PHY_EXTENDED_CTRL_CONFIG_EN);
PHY_RMR(0, PHY_CONFIG1, PHY_CONFIG1_FWDREM, PHY_CONFIG1_FWDREM);
PHY_RMR(0, PHY_COM_CONFIG, PHY_COM_CONFIG_WAKE, PHY_COM_CONFIG_WAKE); /* ratio metric threshold on wake pin */
PHY_RMR(0, PHY_EXTENDED_CTRL_ADDR, 0, PHY_EXTENDED_CTRL_CONFIG_EN);
INT_SYS_InstallHandler(PORTC_IRQn, portc_Handler, (isr_t *)0);
INT_SYS_EnableIRQ(PORTC_IRQn);
// /* set tja1101 into internal loopback mode */
// PHY_SetLoopback(0, PHY_LOOPBACK_INTERNAL);
/* prepare for sending data */
for (i = 0; i < 50U; i++)
{
frame.payload[i] = i;
}
copyBuff(frame.destAddr, ethernet1_MacAddr, 6U);
copyBuff(frame.srcAddr, srcMacaddress, 6U);
frame.length = 50U;
buff.data = (uint8_t *)&frame;
/* Length == 12 bytes MAC addresses + 2 bytes length + 50 bytes payload */
buff.length = 64U;
ENET_DRV_SendFrame(INST_ETHERNET1, 0U, &buff, NULL);
OSIF_TimeDelay(500);
while (1)
{
/* Provides polling support, by handling specific events */
PHY_MainFunction(0);
ENET_status = ENET_DRV_GetTransmitStatus(INST_ETHERNET1,0,&buff, NULL);
if (ENET_status == STATUS_SUCCESS)
{
ENET_DRV_SendFrame(INST_ETHERNET1, 0U, &buff, NULL);
/* if send ok, toggle yellow led*/
PINS_DRV_TogglePins(GPIO_PORT, LED2_YELLOW);
}
PHY_Read(0, PHY_EXTENDED_CTRL_ADDR, &extCtrl);
if (extCtrl == 0xD000U)
{
/* when tja1101 go to sleep mode, toggle on blue led*/
PINS_DRV_TogglePins(GPIO_PORT, LED3_BLUE);
PINS_DRV_SetPins(GPIO_PORT, LED1_RED);
PINS_DRV_SetPins(GPIO_PORT, LED2_YELLOW);
}
OSIF_TimeDelay(500);
}
3.3 测试
3.3.1 测试normal mode
连上S32K148开发板、以太网转接板以及电脑,然后上电,红色LED短暂亮一下,然后黄色LED闪烁,在电脑的抓包软件wireshark上能看到S32K148循环发送的以太网数据。
wireshark抓取的部分数据如下图:
3.3.2 测试link up 和 link down
两种中断状态进入的条件如下:
测试情况为:
-
上电之后,先打开红色LED,然后进入link_up回调函数,关闭红色LED,打开黄色LED。wireshark显示数据正常发送的同时,黄色LED闪烁。
-
接着断开双绞线(TRX_P和TRX_N),进入link_down回调函数,关闭黄色LED,打开红色LED。wireshark面板上没有数据显示。
-
最后接上双绞线(TRX_P和TRX_N),进入link_up回调函数,关闭红色LED,打开黄色LED。wireshark显示数据正常发送的同时,黄色LED闪烁。
3.3.3 测试wake up
通过在WAKE_IN_OUT引脚产生上升沿去产生唤醒事件,从而唤醒TJA1101。
测试情况为:
-
上电之后红色LED短暂亮一下,然后黄色LED闪烁。按下开发板的按钮,配置TJA1101进入sleep模式,黄色LED熄灭,蓝色LED点亮,wireshark面板上没有数据显示。
-
在WAKE_IN_OUT引脚短接一下VDD,产生一个上升沿,唤醒TJA1101,进入normal模式,关闭蓝色LED,黄色LED闪烁,wireshark显示数据正常发送。
4.参考资料
- TJA1101B, 100BASE-T1 PHY for automotive Ethernet – Data Sheet (nxp.com)
- Automotive Ethernet Switches & PHY Transceivers Brochure (nxp.com)
本文主要介绍了如何快速调试TJA1101,对于很多细节的东西没有展开。后面有时间会专门写几篇文章分别介绍TJA1101的硬件设计,软件驱动以及测试注意事项。
如果觉得本文对你有用,不妨给个一键三连!!!