【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在线答疑解惑!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/334734.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双指针(简化哈希)力扣15.三数之和

题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 …

Linux Capabilities 进阶实战

目录 1. 快速回顾 2. 为可执行文件分配 capabilities 3. 构建半特权环境 4. 容器与 capabilities Linux Capabilities 基础概念与基本使用 上一篇学习了LinuxCapabilities的基础知识和基本使用&#xff0c;因为后面需要学习Docker的逃逸&#xff0c;理解Linux Capabilitie…

网工内推 | 运维工程师,国企、上市公司,RHCE认证优先

01 广东机场白云信息科技股份有限公司 招聘岗位&#xff1a;基础架构运维工程师&#xff08;中级&#xff09; 职责描述&#xff1a; 1、参与公司业务系统的监控、巡检、维护、故障定位、原因分析&#xff1b; 2、负责业务系统的上线、升级割接工作&#xff1b; 3、负责服务器…

作业--day43

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数&#xff0c;将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c…

python 基础笔记

基本数据类型 函数 lamda 匿名函数 成员方法 类 类与对象 构造方法 魔术方法 私有成员 私有方法 继承 注解 变量注解 函数注解 Union类型 多态 参考链接&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了_哔哩哔哩_bilib…

Java中的网络编程

文章目录 网络基础知识IP 地址端口协议 Java 中网络编程InetAddress&#xff08;静态类&#xff09;UDP 通信原理UDP 发送数据步骤UDP 接收数据步骤UDP 发送接收案例 TCP 通信原理TCP 发送数据步骤TCP 接收数据步骤TCP 发送接收案例 网络基础知识 概述&#xff1a;在网络通信协…

vue3 +TS 安装使用router路由模块

一.安装 1.下载安装依赖 npm install vue-routernextnpm install types/vue-router2.router目录创建 在src 目录下 创建 /src/router文件夹 包含两个文件 route.ts import { RouteRecordRaw } from vue-routerconst routes: Array<RouteRecordRaw> [{path: /,name:…

尚硅谷大数据技术-数据湖Hudi视频教程-笔记01【概述、编译安装】

大数据新风口&#xff1a;Hudi数据湖&#xff08;尚硅谷&Apache Hudi联合出品&#xff09; B站直达&#xff1a;https://www.bilibili.com/video/BV1ue4y1i7na 尚硅谷数据湖Hudi视频教程百度网盘&#xff1a;https://pan.baidu.com/s/1NkPku5Pp-l0gfgoo63hR-Q?pwdyyds阿里…

Kubernetes复习总结(二):Kubernetes容器网络

2、Kubernetes容器网络 1&#xff09;、Docker网络原理 Docker默认使用的网络模型是bridge&#xff0c;这里只讲bridge网络模型 1&#xff09;容器之间通信原理 当安装完docker之后&#xff0c;docker会在宿主机上创建一个名叫docker0的网桥&#xff0c;默认IP是172.17.0.1…

Tensorflow2.0笔记 - 创建tensor

tensor创建可以基于numpy&#xff0c;list或者tensorflow本身的API。 笔记直接上代码&#xff1a; import tensorflow as tf import numpy as np import matplotlib.pyplot as plttf.__version__#通过numpy创建tensor tensor0 tf.convert_to_tensor(np.ones([2,3])) print(te…

Java程序员面试-场景篇

前言 裁员增效潮滚滚而来&#xff0c;特总结一些实际场景方案的面试题&#xff0c;希望对大家找工作有一些帮助。 注册中心 题目&#xff1a; 有三台机器&#xff0c;分别部署了微服务A、微服务B、注册中心&#xff0c;其中A和B都有服务接口提供并正常注册到了注册中心&…

H264/AVC的句法和语义

概述 码流的基本单位&#xff1a; 在编码器输出的码流中&#xff0c;数据的基本单位是句法元素&#xff0c;每个句法元素由若干比特组成&#xff0c;它表示某个特定的物理意义 &#xff0c;比如宏块类型、量化参数等。 句法&#xff1a;句法表征句法元素的组织结构。 语义&a…