【S32K 进阶之旅】 NXP S32K3 以太网 RMII 接口调试(2)

2024-01-09 20:44

本文主要是介绍【S32K 进阶之旅】 NXP S32K3 以太网 RMII 接口调试(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

        前文介绍了 NXP S32K3 以太网 RMII 接口调试的开发环境搭建,下面开始详解软件调试步骤。没看过第一节的小伙伴请移步《【S32K 进阶之旅】 NXP S32K3 以太网 RMII 接口调试(1)》,话不多说我们直接进入正题。


lwip Stack 介绍

       TCP/IP Stack 是 TCP/IP 协议套件的轻量级实现,而实现 lwIP TCP/IP 的重点是减少代码量的同时仍然拥有一个完整的 TCP,lwIP 适用于具有 10Kbytes+ RAM 和 40Kbytes ROM 空间的嵌入式系统。TCP/IP Stack 的代码是开源的,可以参考以下链接:

lwIP - A Lightweight TCP/IP stack

  • 支持的协议:
  • IP(Internet Protocol)
  • ICMP(Internet Control Message Protocol)
  • IGMP(Internet Group Management Protocol)
  • UDP(User Datagram Protocol)
  • TCP(Transmission Control Protocol)
  • DHCP(Dynamic Host Configuration Protocol)
  • ARP(Address Resolution Protocol)
  • 支持的三类 APIs:
    • Raw API: Front/Back-ground structure, best performance, minimal code size.
    • Netconn API: Multi-threaded operations with OS, Increased usability, lower performance, higher memory footprint.
    • BSD Socket API: developed on top of the NetconnAPI, offers more portability.
  • 支持 SSL/TLS (WolfSSL):
    • 轻量级,可移植,基于 C 语言的 SSL/TLS 库
    • 依赖 lwip 堆栈和 FreeRTOS 运行,通过 RTD/HSE 进行加密操作,硬件加速
    • WolfSSL 和 wolfCrypt 可以根据 GPLv2 或标准商业许可使用:wolfSSL – Embedded SSL/TLS Library


图 1  TCP/IP 软件架构


程序修改

1.  重定向 printf,添加串口打印功能(此步骤可以忽略)

       GCC 中没有 Micro,只能使用 newlib 标准库,printf 定义在 <stdio.h> 头文件中:“int printf(const char *_restrct, …”,根据 __restrict 字符串给出的格式打印输出到 stdout(标准输出)中,它调用更底层的函数“int _write(int iFileHandle, char *pcBuffer, int iLength)”来打印。

       新建 <retarget.c>文件,重新定义“_write”函数,并链接到 S32K3 的库函数“Lpuart_Uart_Ip_SyncSend”(见下图),实现 printf 串口打印,现在我们可以将初始化以太网模块的数据直观的打印出来。


图 2  printf 重定向
 


图 3  新建 printf 源文件



2.  以太网 PHY 初始化(JL3101)

       例程中已经有 DP83848/TLK110/TJA1100 等型号以太网模块的初始化配置,初始化操作在 “main() -> device_init() -> Eth_T_InitPhys()”函数中。而本章我们使用国产的景略 JL3101百兆以太网模块实现 S32K3 MAC 与 PHY 之间的 RMII 通信。通过 SMI 总线配置寄存器初始化 JL3101,重新改写 Eth_T_InitPhys() 函数,并通过串口打印实时信息。
 


图 4 读写 JL3101的数据

需要注意的是,JL3101 是通过 Clause45 帧结构方式访问 PHY 的,在 S32K3 SDK 中有可直接调用的函数:

  • 读寄存器:Gmac_Ip_MDIOReadMMD();
  • 写寄存器:Gmac_Ip_MDIOWriteMMD();


初始化 PHY 具体步骤如下:

  • PHY 复位管脚拉低 4ms 以上解除复位,复位管脚拉高 15ms 后开始查找 ID
  • 查找 JL3101 PHY ID:
    • ID0 = 0x937C
    • ID1 = 0x4010
  • 关闭 TC10 车载以太网休眠和唤醒功能
  • 配置 MDI 接口速率为:100Mbs
    • 此时信号转接器档位应调成 100M
  • 配置 MDI 主从模式为:Master Mode
    • 此时信号转接器档位应调成 Slave Mode
  • 配置 MAC 工作模式,我们选择 RMII to copper
  • 软复位:写入命令后,循环读取寄存器直到复位完成
  • 复位后等待 MAC 与 PHY 建立链接:
    • 当读到寄存器“PMA/PMD Status_1[2] = 1”代表链接成功


按照以上步骤编写代码:

static void Eth_T_InitPhys(void){uint16 phy_reg_val0, phy_reg_val1;uint16 phy_addr;Siul2_Dio_Ip_ClearPins(PTE_H_HALF, (1<<5));TestDelay(480000);Siul2_Dio_Ip_SetPins(PTE_H_HALF, (1<<5));TestDelay(4800000);Gmac_Ip_EnableMDIO(CFG_PHY_CTRL_IDX, FALSE, 80000000U);printf("This is a JL3101 Ethernet module demo for S32K3.\n");/* Search for the PHY address */for (phy_addr = 0U; phy_addr < 8U; ++phy_addr){Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 2U, &phy_reg_val0, 1U);Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 3U, &phy_reg_val1, 1U);/* check for PHY ID */if ((phy_reg_val0 == JL3101_PHY_ID0) && (phy_reg_val1 == JL3101_PHY_ID1))
{break; /* found the PHY ID*/}}printf("Search for the PHY address:\n");printf("  Phy_Addr = 0x%X   JL3101_PHY_ID0 = 0x%04X   JL3101_PHY_ID1 = 0x%04X.\n", phy_addr, phy_reg_val0 ,phy_reg_val1);/* TC10 Disable */Gmac_Ip_MDIOWriteMMD(CFG_PHY_CTRL_IDX, phy_addr, 3U, 0x8707U, 0x0000U, 1U);while (Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 3U, 0x8707U, &phy_reg_val0, 1U) & 0x8000U){ /* Busy Wait */}printf("TC10 Disable:\n");printf("  devad = 0x3   reg = 0x8707  reg_value = 0x%04X\n", phy_reg_val0);/* Speed_Select Lsb = 1 100Mbs */Gmac_Ip_MDIOWriteMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0U, 0x2000U, 1U);while (Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0U, &phy_reg_val0, 1U) & 0x8000U){ /* Busy Wait */}printf("Speed_Select 100Mbs:\n");printf("  devad = 0x1   reg = 0x0000  reg_value = 0x%04X\n", phy_reg_val0);/* Master Mode 0xC000, Slave Mode 0x8000 */Gmac_Ip_MDIOWriteMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0x0834U, 0xC000U, 1U);while (Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0x0834U, &phy_reg_val0, 1U) & 0x8000U){ /* Busy Wait */}printf("Master Mode 0xC000, Slave Mode 0x8000:\n");printf("  devad = 0x1   reg = 0x0834  reg_value = 0x%04X\n", phy_reg_val0);/* RMII to copper */Gmac_Ip_MDIOWriteMMD(CFG_PHY_CTRL_IDX, phy_addr, 3U, 0x8000U, 0x0246U, 1U);while (Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 3U, 0x8000U, &phy_reg_val0, 1U) & 0x8000U){ /* Busy Wait */}printf("RMII to copper:\n");printf("  devad = 0x3   reg = 0x8000  reg_value = 0x%04X\n", phy_reg_val0);/* soft Reset */Gmac_Ip_MDIOWriteMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0x0000U, 0xA000, 1U);printf("Soft Reset:\n");do{Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0x0000U, &phy_reg_val0, 1U);printf("  devad = 0x1   reg = 0x0000  reg_value = 0x%04X\n", phy_reg_val0);}while ((0U != (phy_reg_val0 & (1U << 15U))));/* Wait to establish link */printf("Wait to establish link:\n");do{Gmac_Ip_MDIOReadMMD(CFG_PHY_CTRL_IDX, phy_addr, 1U, 0x1, &phy_reg_val0, 1U);}while ((0U == (phy_reg_val0 & (1U << 2U))));printf("  devad = 0x1   reg = 0x0001  reg_value = 0x%04X\n", phy_reg_val0);printf("PMA/PMD receive link up.\n");}


常见问题

1.  调试和运行程序时跳到“DevAssert();”

       这是因为 S32K3 板没有安装 HSE 固件,而 lwip 演示启用了 ssl_echo 应用程序,会调用一些需要 HSE 固件支持的 API。


解决办法:

  • 在 S32K3 MCU 板上安装 HSE 固件,官网有 HSE 安装教程,这里不再展开描述
  • 在不需要测试 SSL service 的情况下,临时注释掉例程中 < test.c> 第 522 行的这个函数“secure_socket_init();”,如下图所示



2.  HardFault_Handler()

       程序正常运行约 20 分钟后突然停止运行,并跳到 HardFault_Handler() 硬件故障处,这是因为代码中限制了测试时间(默认为 1200秒),超时后会停止执行程序。增加 tests_timeout 变量值可以解决问题(在 <test.c> 的第 250 行)



小结

       文中使用的开发板“Cavalry”现已上架大大购,链接如下:DVK2305- CAVALRY S32K344产品详情_大大购 (wpgdadago.com)

       现在 S32K3 车载以太网模块调试的软件部分已经修改并编译通过,最后一节进行以太网 RMII 通信功能验证,敬请关注本章更新。获取更多资讯,或进一步交流关于 S32K3 的技术问题,欢迎联系世平集团上海应用技术处 ATU <atu.sh@wpi-group.com>。


 

参考文档


[1] Automotive TCP/IP Stack User Manual. Rev. 33.0

[2] lwip_s32k344 demo guide.



欢迎在大大通相关博文下方留言评论,我们会及时回复您的问题。如有更多需求,欢迎联系大联大世平集团 ATU 部门:atu.sh@wpi-group.com
作者:Jadyn Li /李瑞洁

登录大大通,了解更多详情,解锁1500+完整应用方案,更有大联大700+FAE在线答疑解惑!

这篇关于【S32K 进阶之旅】 NXP S32K3 以太网 RMII 接口调试(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/588380

相关文章

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC