当前位置: 首页 > news >正文

STM32的以太网外设+PHY(LAN8720)使用详解(5):MAC及DMA配置

0 工具准备

1.野火 stm32f407霸天虎开发板
2.LAN8720数据手册
3.STM32F4xx中文参考手册

1 MAC及DMA配置

1.1 使能ETH时钟

stm32的ETH外设挂载在AHB1总线上,位于RCC_AHB1ENR的bit25-bit27:
在这里插入图片描述
相关语句如下:

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |RCC_AHB1Periph_ETH_MAC_Rx,ENABLE);

1.2 复位MAC寄存器

直接调用ETH_DeInit函数来复位ETH外设

void ETH_DeInit(void)
{RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, ENABLE);RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, DISABLE);
}

上述语句操作的寄存器如下:
首先使能
首先设置位25为1复位以太网MAC(复位MAC寄存器到默认值),然后设置为0取消复位。

1.3 复位MAC DMA控制器

首先调用ETH_SoftwareReset函数复位MAC的DMA

void ETH_SoftwareReset(void)
{/* Set the SWR bit: resets all MAC subsystem internal registers and logic *//* After reset all the registers holds their respective reset values */ETH->DMABMR |= ETH_DMABMR_SR;
}

上述语句操作的寄存器如下:
在这里插入图片描述
等待MAC DMA控制器软件复位完成:

while (ETH_GetSoftwareResetStatus() == SET);

ETH_GetSoftwareResetStatus函数定义如下:

FlagStatus ETH_GetSoftwareResetStatus(void)
{FlagStatus bitstatus = RESET;if((ETH->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET){bitstatus = SET;}else{bitstatus = RESET;}return bitstatus;
}

这里轮询位0的状态,当为0值为0时表示复位完成,方可以进行接下来的操作。

1.4 配置ETH

由于需要配置的ETH参数非常多,大部分参数保持默认即可,为了省事首先调用ETH_StructInit函数将ETH参数设置为默认值。语句如下:

ETH_StructInit(&ETH_InitStructure);

ETH_StructInit这个函数实际上就是将ETH_InitStructure这个变量的成员的值全部设置为默认值。
然后我们根据需要修改其中一些参数,比较常见的就是开启混杂模式,也就是将ETH_InitStructure.ETH_ReceiveAll设置为ETH_ReceiveAll_Enable。
本文使用的配置如下:

/* 开启网络自适应功能 */
ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
/* 关闭反馈 */
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
/* 关闭重传功能 */
ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
/* 关闭自动去除PDA/CRC功能  */
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
/* 关闭接收所有的帧 */
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
/* 允许接收所有广播帧 */
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
/* 关闭混合模式的地址过滤  */
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
/* 对于组播地址使用完美地址过滤    */
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
/* 对单播地址使用完美地址过滤  */
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
/* 开启ipv4和TCP/UDP/ICMP的帧校验和卸载   */
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
/* 开启丢弃TCP/IP错误帧 */
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
/* 开启接收数据的存储转发模式  */
ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
/* 开启发送数据的存储转发模式   */
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
/* 禁止转发错误帧 */
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
/* 不转发过小的好帧 */
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
/* 打开处理第二帧功能 */
ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
/* 开启DMA传输的地址对齐功能 */
ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
/* 开启固定突发功能 */
ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
/* DMA发送的最大突发长度为32个节拍 */
ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
/*DMA接收的最大突发长度为32个节拍 */
ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;

最后调用ETH_Init函数初始化ETH即可:

EthStatus = ETH_Init(&ETH_InitStructure, ETHERNET_PHY_ADDRESS);

注意,参数2是PHY的地址,我们使用的PHY地址为0x00。
ETH_Init主要工作就是根据我们设置的ETH参数去配置相应的寄存器。

1.5 配置MAC地址

直接使用ETH_MACAddressConfig函数设置MAC地址即可:

uint8_t macAddr[6] = {0x00, 0x00, 0x00, 0x14, 0x99, 0x30};
ETH_MACAddressConfig(ETH_MAC_Address0, macAddr);

这里要注意,参数1的值为0,会操作如下寄存器:
在这里插入图片描述
在这里插入图片描述

1.6 配置DMA

1.6.1 DMA描述符介绍

在介绍DMA配置之前,需要了解一下STM32的ETH DMA结构:
在这里插入图片描述
一般来说我们都选择链接结构,操作起来更方便一些。提到了ETH DMA就绕不开DMA描述符,DMA描述符分为Tx DMA描述符和Rx DMA描述符,DMA描述符是纯软件的概念,STM32的ETH DMA通过DMA描述符来管理接收、发送的以太网数据。STM32默认使用的是增强型的DMA描述符。
增强型Tx DMA描述符如下:
在这里插入图片描述
可以看到描述符的大小为48bit,这和STM32定义的DMA结构体是一模一样的:

typedef struct  {__IO uint32_t   Status;                /*!< Status */uint32_t   ControlBufferSize;     /*!< Control and Buffer1, Buffer2 lengths */uint32_t   Buffer1Addr;           /*!< Buffer1 address pointer */uint32_t   Buffer2NextDescAddr;   /*!< Buffer2 or next descriptor address pointer */
/* Enhanced ETHERNET DMA PTP Descriptors */
#ifdef USE_ENHANCED_DMA_DESCRIPTORSuint32_t   ExtendedStatus;        /* Extended status for PTP receive descriptor */uint32_t   Reserved1;             /* Reserved */uint32_t   TimeStampLow;          /* Time Stamp Low value for transmit and receive */uint32_t   TimeStampHigh;         /* Time Stamp High value for transmit and receive */
#endif /* USE_ENHANCED_DMA_DESCRIPTORS */
} ETH_DMADESCTypeDef;

增强型Rx DMA描述符如下:
在这里插入图片描述
增强型Rx DMA描述符和增强型Tx DMA描述符在组成上是一致的,唯一的区别是bit的含义不同。
有人会好奇,既然DMA描述符是纯软件的概念,那么硬件DMA又是如何找到DMA描述符并使用它完成数据接收、发送操作的呢?这里就要提到DMATDLAR、DMARDLAR这两个寄存器,这两个寄存器会保存DMA描述符首地址到寄存器,这便是联系硬件DMA和软件DMA描述符的桥梁:
在这里插入图片描述

1.6.2 DMA配置过程

(1)定义发送、接收DMA描述符及buffer等变量

__align(4) 
ETH_DMADESCTypeDef  DMARxDscrTab[ETH_RXBUFNB];/* Ethernet Rx DMA Descriptor 以太网接收DMA描述符 */
__align(4) 
ETH_DMADESCTypeDef  DMATxDscrTab[ETH_TXBUFNB];/* Ethernet Tx DMA Descriptor  以太网发送DMA描述符 */
__align(4) 
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; /* Ethernet Receive Buffer 以太网接收Buffer */
__align(4) 
uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; /* Ethernet Transmit Buffer 以太网发送Buffer */

以上是STM32默认配置的DMA描述符和buffer,DMA描述符的数量为4,buffer的大小为1524Byte。需要4字节对齐,方便DMA的搬运。
之所以定义buffer大小为1524Byte,是因为以太网报文最大帧大小为1524Byte,计算方法如下:

ETH_HEADER + ETH_EXTRA + VLAN_TAG + MAX_ETH_PAYLOAD + ETH_CRC

其中,
ETH_HEADER表示以太网帧头,大小为14字节,包括6字节目的地址、6字节源地址、2字节帧类型
ETH_EXTRA表示某些情况下的额外字节,大小为2字节
VLAN_TAG表示VLAN字段,大小为4字节
MAX_ETH_PAYLOA表示以太网帧有效载荷,大小为1500字节(范围为46-1500字节)
ETH_CRC表示CRC校验,大小为4字节
我们还需要定义2个DMA描述符指针,这个DMA描述符指针主要是给CPU使用的,用来指示当前操作到了哪个DMA描述符,有点类似于环形buffer的头指针,而ETH DMA则是尾指针。定义内容如下:

__IO ETH_DMADESCTypeDef  *DMATxDescToSet;
__IO ETH_DMADESCTypeDef  *DMARxDescToGet;

(2)初始化Tx DMA和Rx DMA描述符

/* Initialize Tx Descriptors list: Chain Mode */ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);/* Initialize Rx Descriptors list: Chain Mode  */ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);

ETH_DMATxDescChainInit和ETH_DMARxDescChainInit这两个函数实际上就是初始化Tx和RxDMA描述符,具体工作如下:
①设置每个DMA描述符的状态
②设置每个DMA描述符的buffer地址
③设置每个DMA描述符的下一个DMA描述符地址(构成链形)
④设置DMA描述符列表地址寄存器的值为首个DMA描述符地址
这里我们开启硬件发送报文校验和功能,当我们发送TCP/UDP/ICMP报文时无需使用CPU计算校验和,直接让DMA完成即可。语句如下:

  for(i = 0; i < ETH_TXBUFNB; i++){ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);}

(3)使能ETH
到此为止,MAC和DMA的配置基本完成,接下来只需要使能所有相关的外设即可。直接调用ETH_Start函数即可:

ETH_Start();

这个函数的主要工作就是将相关的寄存器位使能:

void ETH_Start(void)
{/* Enable transmit state machine of the MAC for transmission on the MII */ETH_MACTransmissionCmd(ENABLE);/* Enable receive state machine of the MAC for reception from the MII */ETH_MACReceptionCmd(ENABLE);/* Flush Transmit FIFO */ETH_FlushTransmitFIFO();/* Start DMA transmission */ETH_DMATransmissionCmd(ENABLE);/* Start DMA reception */ETH_DMAReceptionCmd(ENABLE);
}

这里有个非常有用的函数ETH_FlushTransmitFIFO,可以用来清空FIFO。当我们的网口之前残余了一些无用的报文,在我们初始化之前将FIFO清空可以避免这些无用报文的干扰。

2 总结

(1)DMA描述符是个纯软件的概念,通过设置DMA描述符地址寄存器来建立DMA和DMA描述符的联系。DMA描述符使用起来和环形buffer类似,且一个报文可能存在多个DMA描述符内,但一个DMA描述符最多只有一个报文。
(2)最好将接收、发送buffer大小设置到1524字节,这样可以避免拆包,便于我们对数据的处理。
(3)可以使能ETH_InitStructure.ETH_ReceiveAll开启混杂模式,这在开发Ethernet层的协议时非常有用。

相关文章:

STM32的以太网外设+PHY(LAN8720)使用详解(5):MAC及DMA配置

0 工具准备 1.野火 stm32f407霸天虎开发板 2.LAN8720数据手册 3.STM32F4xx中文参考手册1 MAC及DMA配置 1.1 使能ETH时钟 stm32的ETH外设挂载在AHB1总线上&#xff0c;位于RCC_AHB1ENR的bit25-bit27&#xff1a; 相关语句如下&#xff1a; RCC_AHB1PeriphClockCmd(RCC_AHB1…...

GitHub、Gitee、Gitlab共用一个SSH密钥配置

目录 1. 说明2. 生成ssh2-1. 设置全局邮箱和用户名2-2. 生成全局ssh 3. Github、Gitee配置ssh3-1. Github配置3-2. Gitee配置 1. 说明 由于我的Github、Gitee、Gitlab用的邮箱不同&#xff0c;向不同的平台提交代码时都需要验证密码&#xff0c;非常麻烦所以配置了一个共用的S…...

ClickHouse(19)ClickHouse集成Hive表引擎详细解析

文章目录 Hive集成表引擎创建表使用示例如何使用HDFS文件系统的本地缓存查询 ORC 输入格式的Hive 表在 Hive 中建表在 ClickHouse 中建表 查询 Parquest 输入格式的Hive 表在 Hive 中建表在 ClickHouse 中建表 查询文本输入格式的Hive表在Hive 中建表在 ClickHouse 中建表 资料…...

用C求斐波那契数列-----(C每日一编程)

斐波那契数列: 斐波那契数列是指这样一个数列&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#xff0c;89……这个数列从第3项开始 &#xff0c;每一项都等于前两项之和。 递推…...

在Jetpack Compose中使用ExoPlayer实现直播流和音频均衡器

在Jetpack Compose中使用ExoPlayer实现直播流和音频均衡器 背景 ExoPlayer与Media3的能力结合&#xff0c;为Android应用程序播放多媒体内容提供了强大的解决方案。在本教程中&#xff0c;我们将介绍如何设置带有Media3的ExoPlayer来支持使用M3U8 URL进行直播流。此外&#x…...

持续集成交付CICD:Jira 远程触发 Jenkins 实现更新 GitLab 分支

目录 一、实验 1.环境 2.GitLab 查看项目 3.Jira新建模块 4. Jira 通过Webhook 触发Jenkins流水线 3.Jira 远程触发 Jenkins 实现更新 GitLab 分支 二、问题 1.Jira 配置网络钩子失败 2. Jira 远程触发Jenkins 报错 一、实验 1.环境 &#xff08;1&#xff09;主机 …...

基于SSM的面向TCP_IP的网络互联实验平台

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SSM的面向TCP和IP的网络互联实验平台…...

【IDEA】try-catch自动生成中修改catch的内容

编辑器 --> 文件和代码模板 --> 代码 --> Catch Statement Body...

2024 十大AI预测

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

【Linux基础开发工具】gcc/g++使用make/Makefile

目录 前言 gcc/g的使用 1. 语言的发展 1.1 语言和编译器自举的过程 1.2 程序翻译的过程&#xff1a; 2. 动静态库的理解 Linux项目自动化构建工具-make/makefile 1. 快速上手使用 2. makefile/make执行顺序的理解 前言 了解完vim编辑器的使用&#xff0c;接下来就可以尝…...

Windows Nginx版本升级

记录windows系统上nginx版本从1.22.1直接升级到1.25.3&#xff0c;全程一步到位&#xff01; nginx官网: https://nginx.org/ C:\Windows\system32>cd C:\nginx# 查看当前nginx版本C:\nginx>nginx -v nginx version: nginx/1.22.1# 停止nginx服务C:\nginx>net stop ng…...

kubernetes集群 应用实践 kafka部署

kubernetes集群 应用实践 kafka部署 零.1、环境说明 零.2、kafka架构说明 zookeeper在kafka集群中的作用 一、Broker注册 二、Topic注册 三、Topic Partition选主 四、生产者负载均衡 五、消费者负载均衡 一、持久化存储资源准备 1.1 创建共享目录 [rootnfsserver ~]# mkdir -…...

Featured Based知识蒸馏及代码(3): Focal and Global Knowledge (FGD)

文章目录 1. 摘要2. Focal and Global 蒸馏的原理2.1 常规的feature based蒸馏算法2.2 Focal Distillation2.3 Global Distillation2.4 total loss3. 实验完整代码论文: htt...

CentOs 安装MySQL

1、拉取安装包 wget --no-check-certificate dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm 成功拉取 2、安装 yum install mysql-community-release-el6-5.noarch.rpm 过程中可能需要你同意一些东西&#xff0c;y 即可 然后稍微检查一下 yum repolist enabled…...

基于Java (spring-boot)的在线考试管理系统

一、项目介绍 系统功能说明 1、系统共有管理员、老师、学生三个角色&#xff0c;管理员拥有系统最高权限。 2、老师拥有考试管理、题库管理、成绩管理、学生管理四个模块。 3、学生可以参与考试、查看成绩、试题练习、留言等功能 二、作品包含 三、项目技术 后端语言&…...

5. 结构型模式 - 外观模式

亦称&#xff1a; Facade 意图 外观模式是一种结构型设计模式&#xff0c; 能为程序库、 框架或其他复杂类提供一个简单的接口 问题 假设你必须在代码中使用某个复杂的库或框架中的众多对象。 正常情况下&#xff0c; 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确…...

微服务之配置中心与服务跟踪

zookeeper 配置中心 实现的架构图如下所示&#xff0c;采取数据加载到内存方式解决高效获取的问题&#xff0c;借助 zookeeper 的节点监听机制来实现实时感知。 配置中心数据分类 事件调度&#xff08;kafka&#xff09; 消息服务和事件的统一调度&#xff0c;常用用 kafka …...

链表 典型习题

160 相交链表&#xff1a;遍历&#xff0c;统计是否出现过 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:ListNode *getIntersectionNode(L…...

面试题:JVM 对锁都进行了哪些优化?

文章目录 锁优化自旋锁和自适应自旋锁消除锁粗化逃逸分析方法逃逸线程逃逸通过逃逸分析&#xff0c;编译器对代码的优化 锁优化 jvm 在加锁的过程中&#xff0c;会采用自旋、自适应、锁消除、锁粗化等优化手段来提升代码执行效率。 自旋锁和自适应自旋 现在大多的处理器都是…...

SSM整合实战(Spring、SpringMVC、MyBatis)

五、SSM整合实战 目录 一、SSM整合理解 1. 什么是SSM整合&#xff1f;2. SSM整合核心理解五连问&#xff01; 2.1 SSM整合涉及几个IoC容器&#xff1f;2.2 每个IoC容器盛放哪些组件&#xff1f;2.3 IoC容器之间是什么关系&#xff1f;2.4 需要几个配置文件和对应IoC容器关系&…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...