【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

相关文章

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

基于Redisson实现分布式系统下的接口限流

《基于Redisson实现分布式系统下的接口限流》在高并发场景下,接口限流是保障系统稳定性的重要手段,本文将介绍利用Redisson结合Redis实现分布式环境下的接口限流,具有一定的参考价值,感兴趣... 目录分布式限流的核心挑战基于 Redisson 的分布式限流设计思路实现步骤引入依赖定义限流注解实现

基于Python实现进阶版PDF合并/拆分工具

《基于Python实现进阶版PDF合并/拆分工具》在数字化时代,PDF文件已成为日常工作和学习中不可或缺的一部分,本文将详细介绍一款简单易用的PDF工具,帮助用户轻松完成PDF文件的合并与拆分操作... 目录工具概述环境准备界面说明合并PDF文件拆分PDF文件高级技巧常见问题完整源代码总结在数字化时代,PD

javaSE类和对象进阶用法举例详解

《javaSE类和对象进阶用法举例详解》JavaSE的面向对象编程是软件开发中的基石,它通过类和对象的概念,实现了代码的模块化、可复用性和灵活性,:本文主要介绍javaSE类和对象进阶用法的相关资... 目录前言一、封装1.访问限定符2.包2.1包的概念2.2导入包2.3自定义包2.4常见的包二、stati

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1