本帖最后由 尹小舟 于 2024-5-28 19:24 编辑
大家好,今天我很高兴能与大家分享一个关于以太网的学习和使用经验。GD32H7xxDemoSuitesV1.2.0固件有很多开发板例程,特别是其中的以太网(ENET)部分。这个Demo套件为我们提供了一个宝贵的平台,以便我们深入理解并实践基于GD32H759l评估板的以太网通信功能。
在我学习的过程中,发现“Third_party”文件夹中包含了与这个Demo相关的第三方库和工具(LwiP和FreeRTOS),它们为我们提供了强大的支持,使以太网通信的实现变得更加容易。而在这个Demo的“Projects”目录下,我专注于里面的“FreeRTOS_tcpudp”这个项目,它直接使用Lwip和 FreeRTOS,省去了移植适配代码的苦恼。
在接下来的分享中,我将详细介绍我是如何搭建环境、配置参数,并最终实现以太网通信的。我相信通过这个Demo的学习和实践,我们不仅能够加深对以太网通信原理的理解,还能掌握在实际项目中应用这些原理的技能。希望大家能够从中受益,并一起探讨和学习更多关于嵌入式系统和网络通信的知识。
以太网模块
该以太网模块包含两个10/100Mbps以太网MAC(媒体访问控制器),采用DMA优化数据帧的发送与接收性能,支持MII(媒体独立接口)与RMII(简化的媒体独立
接口)两种与物理层(PHY)通讯的标准接口,实现以太网数据帧的发送与接收。以太网模块遵守IEEE 802.3-2002标准和IEEE 1588-2008标准。
以太网接口和DP83848CVV
DP83848C以太网物理层收发器特性的详细描述:
- 低功耗3.3V、0.18µm CMOS 技术:
- 该收发器采用了低功耗的3.3V供电电压和0.18µm的CMOS工艺技术,这有助于减少整体系统的能耗,同时保持高性能。
- 低功耗典型值低于270mW:
- 在正常工作条件下,该收发器的功耗典型值低于270毫瓦,这使其适用于需要低功耗的嵌入式和网络设备。
- 3.3V MAC 接口:
- 收发器提供了一个3.3V的媒体访问控制(MAC)接口,用于与MAC层设备或处理器进行通信。
- 适用于10/100Mbps 的自动MDIX功能:
- 收发器支持自动MDI/MDIX功能,这意味着它可以自动检测并适应连接的对端设备是直连网线(MDI)还是交叉网线(MDIX),无需手动配置。这使得它能够在10Mbps和100Mbps的速度下灵活工作。
- 能量检测模式:
- 收发器具有能量检测模式,该模式可能用于检测网络链路上是否存在有效的信号或数据传输,以优化电源管理或进行故障检测。
- 25MHz 时钟输出:
- 收发器提供了一个25MHz的时钟输出,这可以用于为其他设备或系统组件提供同步时钟信号。
- SNI 接口(可配置):
- SNI(SerDes Network Interface)接口是一个可配置的接口,它允许收发器以串行方式与其他设备或组件进行通信。
- RMII 版本1.2 接口(可配置):
- RMII(Reduced Media Independent Interface)是一个简化的媒体独立接口,版本1.2提供了更高的灵活性和数据速率。此接口也是可配置的,允许用户根据系统需求选择使用。
- MII 串行管理接口(MDC和MDIO):
- MII(Media Independent Interface)是一个用于PHY和MAC层之间通信的串行管理接口。MDC(Management Data Clock)和MDIO(Management Data Input/Output)是MII接口中的两个关键信号,用于在PHY和MAC之间传输管理数据。
- IEEE 802.3u MI:
- 这指的是收发器符合IEEE 802.3u标准,这是一个定义快速以太网(Fast Ethernet)物理层和数据链路层接口的标准。MI可能是指Management Interface(管理接口),但通常MII更常用来表示Media Independent Interface。所以这里可能是对MII接口或管理接口的引用。l
网路协议
在计算机网络中要做到有条不紊的交换数据就必须遵循一些约定目前国际上应用最广泛的为TCP /IP协议,
TCP/IP协议不仅仅指TCP和IP两个协议,而是一个由多种协议组成的协议簇,如FTP、SMTP、UDP、IP等。其中,TCP和IP协议因其重要性而常被提及,故得名TCP/IP。
标准的TCP IP协议采用四层结构分别为应用层传输层网络层和网络接口层但是在介绍原理时通常把网络接口层区分为物理层和和数据链路层
优点
- 标准化和开放性:TCP/IP协议具有良好的标准化和开放性,可以在不同的设备和系统间进行互联,实现多种应用和服务的互通。
- 可靠性和安全性:TCP/IP协议拥有较好的可靠性和安全性,能够保证数据传输的正确性和机密性。
- 扩展性和灵活性:TCP/IP协议具备较强的扩展性和灵活性,支持网络层次的多种拓扑结构和协议组合。
- 跨平台性:TCP/IP协议能够在不同的操作系统中使用,并且可以通过传输层和应用层进行不同协议的转换。
IP协议
IP协议是整个TCP/IP协议栈的核心协议,也是最重要的互联网协议之一。
IP协议的特性
- 无连接:IP协议是一种无连接的协议,这意味着在发送数据之前,发送方和接收方之间不需要建立连接。每个IP数据包都是独立路由和传输的。
- 不可靠:IP协议本身不保证数据包的传输可靠性。数据包在传输过程中可能会丢失、损坏、重复或乱序。这些错误需要由上层协议(如TCP)来处理。
- 尽力而为:IP协议提供“尽力而为”(best-effort)的服务。它只负责将数据包从源地址发送到目的地址,但不保证数据包的交付或交付的顺序。
为了标识互联网中每台主机的身份每个接入网络中的主机都会分配一个IP地址,IP协议负责将数据包从源主机发送到目标主机通过IP地址作为唯一识别目前IPV四网络使用32位地址以点分十进制表示如192.168.0.1,IPV4的地址已经在2011年被耗尽为解决该问题目前正逐步切换采用128位地址的IPV6。
TCP协议
为了克服IP协议的这些局限性,TCP(Transmission Control Protocol,传输控制协议)被设计为与IP协议一起工作。TCP协议是一种面向连接的、可靠的传输层协议。它使用序列号、确认和重传机制来确保数据的完整性和顺序性。此外,TCP还提供流量控制和拥塞控制机制来防止网络拥塞和数据丢失。
网络端口
面向连接服务TCP协议和无连接服务UDP协议使用16bits端口号来表示和区别网络中的不同应用程序,网络层协议IP使用特定的协议号(TCP 6,UDP 17)来表示和区别传输层协议。端口号的取值范围为0至65536这些端口号标志着上层应用的不同线程一个主机内可能只有一个IP地址但是可能有多个端口号每个端口号表示着不同的应用线程一台拥有IP地址的主机可以提供许多服务我嗯例如web服务FTP服务等等,这些服务通过IP地址加端口号来区分主机不同的线程。
例程代码
打开下FreeRTOS_tcpudp例程我们分析下主函数
int main(void)
{
/* configure 4 bits pre-emption priority */
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
/* init task */
xTaskCreate(init_task, "INIT", configMINIMAL_STACK_SIZE * 2, NULL, INIT_TASK_PRIO, NULL);
/* start scheduler */
vTaskStartScheduler();
while(1) {
}
}
1. nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
这行代码是设置NVIC组,4位表示抢占优先级,0响应优先级
这行代码通常与ARM Cortex-M微控制器的NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)相关。
在ARM Cortex-M微控制器中,每个中断源都有一个优先级。这些优先级由两个字段组成:抢占优先级(Preemption Priority)和子优先级(Subpriority)。
抢占优先级用于确定当一个更高优先级的中断到来时,当前的中断是否应该被抢占。
而子优先级则在两个中断具有相同的抢占优先级时使用,以确 定哪个中断应该先被处理。
2.xTaskCreate(init_task, "INIT", configMINIMAL_STACK_SIZE * 2, NULL, INIT_TASK_PRIO, NULL);
xTaskCreate
是 FreeRTOS 实时操作系统中的一个函数,用于动态地创建和初始化一个新的任务。
函数原型
BaseType_t xTaskCreate(
TaskFunction_t pxTaskCode, /* 任务函数入口指针 */
const char * const pcName, /* 任务描述性名称 */
const uint16_t usStackDepth, /* 任务堆栈大小(以字为单位) */
void * const pvParameters, /* 传递给任务函数的参数 */
UBaseType_t uxPriority, /* 任务优先级 */
TaskHandle_t * const pxCreatedTask /* 任务句柄 */
);
参数详解
- pxTaskCode:
- 类型:TaskFunction_t
- 描述:指向任务函数的指针。任务函数必须是一个死循环,或者至少应该设计为不返回,除非它被 vTaskDelete 显式地删除。
- pcName:
- 类型:const char * const
- 描述:任务的描述性名称。这主要是为了调试方便。FreeRTOS 配置文件(如 FreeRTOSConfig.h)中通常定义了一个宏 configMAX_TASK_NAME_LEN 来指定任务名称的最大长度(默认通常是16个字符)。
- usStackDepth:
- 类型:const uint16_t
- 描述:任务堆栈的大小,以字(word)为单位,而不是字节。
- pvParameters:
- 类型:void * const
- 描述:传递给任务函数的参数。这可以是一个指向任何数据类型的指针,或者如果任务不需要参数,可以是 NULL。
- uxPriority:
- 类型:UBaseType_t
- 描述:任务的优先级。数字越大,优先级越高。注意,某些 FreeRTOS 端口可能限制了优先级的最大和最小值。
- pxCreatedTask:
- 类型:TaskHandle_t * const
- 描述:用于存储新创建任务的句柄的指针。如果不需要句柄,可以将其设置为 NULL。但通常建议保留句柄,以便后续可以引用或删除任务。
返回值
函数返回一个 BaseType_t 类型的值,用于指示任务是否成功创建。如果任务成功创建并添加到就绪列表中,则返回 pdPASS(通常定义为 1)。否则,它将返回在 projdefs.h 文件中定义的一个错误代码。
参数的两个宏
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define INIT_TASK_PRIO ( tskIDLE_PRIORITY + 1 )
这个函数的意思就是,新建个init_task任务,别名叫INIT,堆栈大小260,优先级1
3. vTaskStartScheduler();
vTaskStartScheduler()
是 FreeRTOS 实时操作系统中,用于启动任务调度器。