在RT-Thread下为MPU手搓以太网MAC驱动-1

2024-05-25 09:36

本文主要是介绍在RT-Thread下为MPU手搓以太网MAC驱动-1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 动手写驱动之前的思考
    • MAC驱动兼容不同的MPU平台
      • 解决不同MPU平台头文件包含的问题
      • 对MAC操作接口的抽象
      • 对MAC设备的抽象
      • MAC设备的注册

这是个人驱动开发过程中做的一些记录,仅代表个人意见和理解,不喜勿喷

动手写驱动之前的思考

  • MAC驱动需要兼容不同的MPU平台
  • MAC驱动需要支持不同的PHY芯片
  • MAC驱动需要支持多个以太网接口
  • MAC驱动需要是否借鉴某个平台代码

在动手写驱动之前,脑海里就会在不停地思考这几个问题,等脑子里有个大概的可行框架就开始动手码代码。

MAC驱动兼容不同的MPU平台

Microchip 也有着丰富的MPU产品线(通过收购Atmel而获取),覆盖传统的ARM9、Cortex-A5和Cortex-A7内核。有的MPU它的以太网叫做GMAC,而有的又叫做EMAC,那编写驱动的时候就要留意对GMAC

解决不同MPU平台头文件包含的问题

选择在libraries/Kconfig文件下添加以下内容:

config SOC_SAM9X60_EKboolselect RT_USING_COMPONENTS_INITselect RT_USING_CACHEconfig SOC_SAM9X75_EKboolselect RT_USING_COMPONENTS_INITselect RT_USING_CACHEconfig SOC_SAMA5D2_XULTboolselect ARCH_ARM_CORTEX_Aselect ARCH_ARM_CORTEX_FPUconfig SOC_SAMA5D2_SOM1_EKboolselect ARCH_ARM_CORTEX_Aselect ARCH_ARM_CORTEX_FPUconfig SOC_SAMA7G54_EKboolselect ARCH_ARM_CORTEX_Aselect ARCH_ARM_CORTEX_FPU

那在sam9x75-ek/board/Kconfig文件下这么做:

menu "Microchip Harmony Plib Configuration"config SOC_SAM9X75boolselect ARCH_ARM_ARM9select SOC_SAM9X75_EKselect RT_USING_USER_MAINdefault y

通过这样的方式,在选择sam9x75-ek平台做开发的时候,就会自动选择上SOC_SAM9X75_EK这个宏定义,后面会用到这个定义。

接下来在gmac/hpl_mac_async.h头文件中添加以下代码实现了对不同平台头文件的包含:

#ifdef SOC_SAMA5D2
#include <sama5d27.h>
#endif#ifdef SOC_SAM9X75
#include <sam9x75.h>
#endif#ifdef SOC_SAMA7G54
#include <sama7g54.h>
#endif

有的MPU平台只有一个GMAC,那它给的MAC相关ID定义是ID_GMAC,如果包含2个GMAC的MPU平台,则会给出ID_GMAC0和ID_GMAC1,那我选择在hpl_mac_async.h头文件添加这样的定义(后面会讲解到这样定义的作用):

#define ID_GMAC_NONE               0xFF#ifdef ID_GMAC
#  define MAC0_ID                  ID_GMAC
#  define MAC1_ID                  ID_GMAC_NONE
#  define MAC0_IRQn                GMAC_IRQn
#  define MAC1_IRQn                ID_GMAC_NONE
#  define MAC0_REGS                GMAC_REGS
#  define MAC1_REGS                (void *)0
#else
#  define MAC0_ID                  ID_GMAC0
#  define MAC1_ID                  ID_GMAC1
#  define MAC0_IRQn                GMAC0_IRQn
#  define MAC1_IRQn                GMAC1_IRQn
#  define MAC0_REGS                GMAC0_REGS
#  define MAC1_REGS                GMAC1_REGS
#endif

对MAC操作接口的抽象

MAC操作接口的抽象,包括中断处理函数、初始化、使能和禁止、网络数据包的收发、获取接收数据包长度、过滤的设置、MAC地址的设置和非常重要的PHY读写访问接口:

struct h3_macplib_ops
{void     (*macdev_interrupt)(mac_dev *const dev);int32_t  (*macdev_init)(mac_dev *const dev, void *const hw);int32_t  (*macdev_deinit)(mac_dev *const dev);int32_t  (*macdev_enable)(mac_dev *const dev);int32_t  (*macdev_disable)(mac_dev *const dev);int32_t  (*macdev_send)(mac_dev *const dev, uint8_t *buf, uint32_t len);uint32_t (*macdev_recv)(mac_dev *const dev, uint8_t *buf, uint32_t len);uint32_t (*macdev_rxbyte)(mac_dev *const dev);int32_t  (*macdev_register)(mac_dev *const dev, mac_cb_type type, mac_async_cb fn);int32_t  (*macdev_filter)(mac_dev *const dev, uint8_t index, mac_filter *filter);int32_t  (*macdev_setmac)(mac_dev *const dev, uint8_t mac[6]);int32_t  (*macdev_writephy)(mac_dev *const dev, uint16_t addr, uint16_t reg, uint16_t data);int32_t  (*macdev_readphy) (mac_dev *const dev, uint16_t addr, uint16_t reg, uint16_t *val);
};

对MAC设备的抽象

对MAC设备也做出了抽象,MPU中如果存在多个MAC接口,那就会有对应数量的MAC设备实例:

struct h3_macplib_dev
{const char   *name;IRQn_Type     irqnum;H3_MAC_REGS   regs;uint8_t       mac_addr[6];uint8_t       dev_id;uint8_t       reserved;mac_async_dev mac_dev;phy_async_dev phy_dev;const struct rt_mdio_bus_ops *mdio_ops;const struct h3_macplib_ops  *mac_ops;struct rt_mdio_bus rt_mdiobus;struct eth_device  rt_ethdev;
};

MAC设备的注册

对MAC设备对应的实例,其部分成员都会在h3_macplib.c文件里面做静态的初始化:

#if defined(BSP_USING_GMAC0) || defined(BSP_USING_EMAC0)
struct h3_macplib_dev h3_macdev0 = {.name       = "e0",.irqnum     = MAC0_IRQn,.regs       = MAC0_REGS,.dev_id     = MAC0_ID,.mac_ops    = &h3_macdev_ops,
};
#endif#if defined(BSP_USING_GMAC1) || defined(BSP_USING_EMAC1)
struct h3_macplib_dev h3_macdev1 = {.name       = "e1",.irqnum     = MAC1_IRQn,.regs       = MAC1_REGS,.dev_id     = MAC1_ID,.mac_ops    = &h3_macdev_ops,
};
#endif

实现对多个MAC设备的注册是这样来实现的:

static struct h3_macplib_dev *h3_macplib_devtable[] =
{0
#if defined(BSP_USING_GMAC0) || defined(BSP_USING_EMAC0), &h3_macdev0
#endif
#if defined(BSP_USING_GMAC1) || defined(BSP_USING_EMAC1), &h3_macdev1
#endif
};
int h3_macplib_init(void)
{rt_err_t state;uint8_t  macaddr = 0xAA;uint32_t table_sz = sizeof(h3_macplib_devtable)/sizeof(uint32_t);struct h3_macplib_dev *macplib_dev;for (uint32_t i = 1; i < table_sz; i++){macplib_dev = h3_macplib_devtable[i];macplib_dev->mac_dev.devid     = macplib_dev->dev_id;macplib_dev->rt_mdiobus.hw_obj = (void *)macplib_dev;macplib_dev->rt_mdiobus.ops    = &h3_mdiobus_ops;/* GMAC MAC Address */macplib_dev->mac_addr[0] = 0x54;macplib_dev->mac_addr[1] = 0x27;macplib_dev->mac_addr[2] = 0x8d;macplib_dev->mac_addr[3] = 0x33;macplib_dev->mac_addr[4] = 0x55;macplib_dev->mac_addr[5] = macaddr++;macplib_dev->rt_ethdev.parent.init      = h3_macplib_initial;macplib_dev->rt_ethdev.parent.open      = h3_macplib_open;macplib_dev->rt_ethdev.parent.close     = h3_macplib_close;macplib_dev->rt_ethdev.parent.read      = h3_macplib_read;macplib_dev->rt_ethdev.parent.write     = h3_macplib_write;macplib_dev->rt_ethdev.parent.control   = h3_macplib_control;macplib_dev->rt_ethdev.parent.user_data = (void *)macplib_dev;macplib_dev->rt_ethdev.eth_rx = h3_macplib_rx;macplib_dev->rt_ethdev.eth_tx = h3_macplib_tx;/* register eth device */state = eth_device_init(&macplib_dev->rt_ethdev, macplib_dev->name);if (RT_EOK != state) {break;}eth_device_linkchange(&macplib_dev->rt_ethdev, RT_FALSE);}return state;
}

这篇关于在RT-Thread下为MPU手搓以太网MAC驱动-1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

Mac备忘录怎么导出/备份和云同步? Mac备忘录使用技巧

《Mac备忘录怎么导出/备份和云同步?Mac备忘录使用技巧》备忘录作为iOS里简单而又不可或缺的一个系统应用,上手容易,可以满足我们日常生活中各种记录的需求,今天我们就来看看Mac备忘录的导出、... 「备忘录」是 MAC 上的一款常用应用,它可以帮助我们捕捉灵感、记录待办事项或保存重要信息。为了便于在不同

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

如何关闭Mac的Safari通知? 3招教你关闭Safari浏览器网站通知的技巧

《如何关闭Mac的Safari通知?3招教你关闭Safari浏览器网站通知的技巧》当我们在使用Mac电脑专注做一件事情的时候,总是会被一些消息推送通知所打扰,这时候,我们就希望关闭这些烦人的Mac通... Safari 浏览器的「通知」功能本意是为了方便用户及时获取最新资讯,但很容易被一些网站滥用,导致我们

如何在Ubuntu上安装NVIDIA显卡驱动? Ubuntu安装英伟达显卡驱动教程

《如何在Ubuntu上安装NVIDIA显卡驱动?Ubuntu安装英伟达显卡驱动教程》Windows系统不同,Linux系统通常不会自动安装专有显卡驱动,今天我们就来看看Ubuntu系统安装英伟达显卡... 对于使用NVIDIA显卡的Ubuntu用户来说,正确安装显卡驱动是获得最佳图形性能的关键。与Windo

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决