stmmac ethernet

2023-11-01

学习笔记,网卡驱动
流程图

从这里看起stmmac_register_platform
注册一个平台驱动

const struct stmmac_of_data meson_dwmac_data = {
    .setup = meson_dwmac_setup,
    .fix_mac_speed = meson_dwmac_fix_mac_speed,
};

static const struct of_device_id stmmac_dt_ids[] = {
#ifdef CONFIG_DWMAC_MESON
    {.compatible = "amlogic, meson6-dwmac",},
    {.compatible = "amlogic, meson8-rmii-dwmac",},
    {.compatible = "amlogic, meson8m2-rgmii-dwmac",},
    {.compatible = "amlogic, meson8m2-rmii-dwmac",
     .data = &meson_dwmac_data},
    {.compatible = "amlogic, gxbb-rgmii-dwmac",
     .data = &meson_dwmac_data},
    {.compatible = "amlogic, gxbb-rmii-dwmac",
     .data = &meson_dwmac_data},
    {.compatible = "amlogic, meson8b-rgmii-dwmac",},
    {.compatible = "amlogic, meson8b-rmii-dwmac",
     .data = &meson_dwmac_data},
    {.compatible = "amlogic, meson6-rmii-dwmac",
     .data = &meson_dwmac_data},
#endif
#ifdef CONFIG_DWMAC_SUNXI
    {.compatible = "allwinner,sun7i-a20-gmac",
    .data = &sun7i_gmac_data},
#endif
#ifdef CONFIG_DWMAC_STI
    {.compatible = "st,stih415-dwmac",
    .data = &sti_gmac_data},
    {.compatible = "st,stih416-dwmac",
    .data = &sti_gmac_data},
    {.compatible = "st,stid127-dwmac",
    .data = &sti_gmac_data},
#endif
    /* SoC specific glue layers should come before generic bindings */
    {.compatible = "st,spear600-gmac"},
    {.compatible = "snps,dwmac-3.610"},
    {.compatible = "snps,dwmac-3.70a"},
    {.compatible = "snps,dwmac-3.710"},
    {.compatible = "snps,dwmac"},
    { /* sentinel */ }
}
    err = platform_driver_register(&stmmac_pltfr_driver);
struct platform_driver stmmac_pltfr_driver = {
    .probe = stmmac_pltfr_probe,
    .remove = stmmac_pltfr_remove,
    .driver = {
           .name = STMMAC_RESOURCE_NAME,
           .owner = THIS_MODULE,
#ifdef CONFIG_PM
           .shutdown = stmmac_pltfr_shutdown,
#endif
           .pm = &stmmac_pltfr_pm_ops,
           .of_match_table = of_match_ptr(stmmac_dt_ids),
           },
}
stmmac_pltfr_probe探测函数
首先从dtd中获取资源

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pr_debug(“resource:res:%p”,(struct resource*)res);
addr = devm_ioremap_resource(dev, res);
if (IS_ERR(addr))
return PTR_ERR(addr);
pr_info(“****************ethernet base addr is %p\n”, addr);
plat_dat = dev_get_platdata(&pdev->dev);
if (pdev->dev.of_node) {
if (!plat_dat)
plat_dat = devm_kzalloc(&pdev->dev,
sizeof(struct
plat_stmmacenet_data),
GFP_KERNEL);
if (!plat_dat) {
pr_err(“%s: ERROR: no memory”, func);
return -ENOMEM;
}

    ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
    if (ret) {
        pr_err("%s: main dt probe failed", __func__);
        return ret;
    }
}
/* Custom setup (if needed) */
if (plat_dat->setup) {
    plat_dat->bsp_priv = plat_dat->setup(pdev);

    pr_info("%s,%d\n",__FUNCTION__,__LINE__);
    if (IS_ERR(plat_dat->bsp_priv))
        return PTR_ERR(plat_dat->bsp_priv);
}

/* Custom initialisation (if needed) */
if (plat_dat->init) {
    ret = plat_dat->init(pdev, plat_dat->bsp_priv);

    pr_info("%s,%d\n",__FUNCTION__,__LINE__);
    if (unlikely(ret))
        return ret;
}
priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
中断获取:
    priv->dev->irq = platform_get_irq_byname(pdev, "macirq");

    priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");

    priv->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
保存平台数据:
    platform_set_drvdata(pdev, priv->dev);

接下来看重要的函数,主要用来初化网络数据结构体成员,初始化,注册
    priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
/**
 * stmmac_dvr_probe
 * @device: device pointer
 * @plat_dat: platform data pointer
 * @addr: iobase memory address
 * Description: this is the main probe function used to
 * call the alloc_etherdev, allocate the priv structure.
 */
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
                     struct plat_stmmacenet_data *plat_dat,
                     void __iomem *addr)
{
    int ret = 0;
    struct net_device *ndev = NULL;
    struct stmmac_priv *priv;
    //申请结构体
    ndev = alloc_etherdev(sizeof(struct stmmac_priv));
    if (!ndev)
        return NULL;
       //设置父设备
    SET_NETDEV_DEV(ndev, device);
    //取出私有数据
    priv = netdev_priv(ndev);
    priv->device = device;
    priv->dev = ndev;
     //通用的设置
    ether_setup(ndev);
     //供ethtool使用,它是一个实用工具
    stmmac_set_ethtool_ops(ndev);
    priv->pause = pause;
    priv->plat = plat_dat;
    priv->ioaddr = addr;
    priv->dev->base_addr = (unsigned long)addr;

    /* Verify driver arguments */
    stmmac_verify_args();

    /* Override with kernel parameters if supplied XXX CRS XXX
     * this needs to have multiple instances
     */
    if ((phyaddr >= 0) && (phyaddr <= 31))
        priv->plat->phy_addr = phyaddr;
//时钟
#ifdef CONFIG_DWMAC_MESON
    priv->stmmac_clk = devm_clk_get(priv->device, "ethclk81");
pr_info("%s,%d\n",__FUNCTION__,__LINE__);

#else
    priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
pr_info("%s,%d\n",__FUNCTION__,__LINE__);

#endif
    if (IS_ERR(priv->stmmac_clk)) {
        dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
             __func__);
        ret = PTR_ERR(priv->stmmac_clk);
        goto error_clk_get;
    }
    clk_prepare_enable(priv->stmmac_clk);
#ifdef CONFIG_DWMAC_MESON
    priv->stmmac_rst = devm_reset_control_get(priv->device,
                          "ethpower");
#else
    priv->stmmac_rst = devm_reset_control_get(priv->device,
                          STMMAC_RESOURCE_NAME);

#endif
    if (IS_ERR(priv->stmmac_rst)) {
        if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
            ret = -EPROBE_DEFER;
            goto error_hw_init;
        }
        dev_info(priv->device, "no reset control found\n");
        priv->stmmac_rst = NULL;
    }
    if (priv->stmmac_rst)
        reset_control_deassert(priv->stmmac_rst);

    //硬件初始化,主要是mac
    /* Init MAC and get the capabilities */
    ret = stmmac_hw_init(priv);
    if (ret)
        goto error_hw_init;
//操作函数,.ndo_start_xmit 成员用于上层向底层发送数据时调用
    ndev->netdev_ops = &stmmac_netdev_ops;

    ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_RXCSUM;
    ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
    ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
    /* Both mac100 and gmac support receive VLAN tag detection */
    ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
#endif
    priv->msg_enable = netif_msg_init(debug, default_msg_level);

    if (flow_ctrl)
        priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */

    /* Rx Watchdog is available in the COREs newer than the 3.40.
     * In some case, for example on bugged HW this feature
     * has to be disable and this can be done by passing the
     * riwt_off field from the platform.
     */
    if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
        priv->use_riwt = 1;
        pr_debug(" Enable RX Mitigation via HW Watchdog Timer\n");
    }

    //用NAPI实现,IRQ+POLL(SOFTIRQ)
    netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);

    spin_lock_init(&priv->lock);
    spin_lock_init(&priv->tx_lock);
    //注册核心结构体
    ret = register_netdev(ndev);
    if (ret) {
        pr_err("%s: ERROR %i registering the device\n", __func__, ret);
        goto error_netdev_register;
    }
#ifdef CONFIG_DWMAC_MESON
    priv->stmmac_clk = clk_get(priv->device, "ethclk81");
#else
    priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
#endif
    if (IS_ERR(priv->stmmac_clk)) {
        pr_warn("%s: warning: cannot get CSR clock\n", __func__);
        goto error_clk_get;
    }

    /* If a specific clk_csr value is passed from the platform
     * this means that the CSR Clock Range selection cannot be
     * changed at run-time and it is fixed. Viceversa the driver'll try to
     * set the MDC clock dynamically according to the csr actual
     * clock input.
     */
    if (!priv->plat->clk_csr)
        stmmac_clk_csr_set(priv);
    else
        priv->clk_csr = priv->plat->clk_csr;

    stmmac_check_pcs_mode(priv);

    if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
        priv->pcs != STMMAC_PCS_RTBI) {
        //MII连接MAC与PHY,扫描PHY设备,从寄存器读出PHY_ID,默认寄存器的值为ffffffff,这里模块为20142014
 /*PHY的读写接口
 new_bus->read = &stmmac_mdio_read;
 new_bus->write = &stmmac_mdio_write;
 new_bus->reset = &stmmac_mdio_reset;*/
        /* MDIO bus Registration */
        ret = stmmac_mdio_register(ndev);

        pr_info("%s,%d\n",__FUNCTION__,__LINE__);
        if (ret < 0) {
            pr_debug("%s: MDIO bus (id: %d) registration failed",
                 __func__, priv->plat->bus_id);
            goto error_mdio_register;
        }
    }
#ifdef CONFIG_DWMAC_MESON
    gmac_create_sysfs(priv->mii->phy_map[priv->plat->phy_addr],
        priv->ioaddr);
#endif
    return priv;

error_mdio_register:
    unregister_netdev(ndev);
error_netdev_register:
    netif_napi_del(&priv->napi);
error_hw_init:
    clk_disable_unprepare(priv->stmmac_clk);
error_clk_get:
    free_netdev(ndev);

    return NULL;
}

网卡刚起来时是关闭的,要用命令去打开,ifconfig eth0 up
时调用net_device_ops的.ndo_open,这里为stmmac_open

/**
 *  stmmac_open - open entry point of the driver
 *  @dev : pointer to the device structure.
 *  Description:
 *  This function is the open entry point of the driver.
 *  Return value:
 *  0 on success and an appropriate (-)ve integer as defined in errno.h
 *  file on failure.
 */
static int stmmac_open(struct net_device *dev)
{
//获取私用数据
    struct stmmac_priv *priv = netdev_priv(dev);
    int ret;
//检测mac addr
    stmmac_check_ether_addr(priv);

    if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
        priv->pcs != STMMAC_PCS_RTBI) {
        //初始化PHY设备
        ret = stmmac_init_phy(dev);
        if (ret) {
            pr_err("%s: Cannot attach to PHY (error: %d)\n",
                   __func__, ret);
            goto phy_error;
        }
    } else {
        pr_debug("not call stmmac_init_phy\n");
    }
    /* Extra statistics */
    memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
    priv->xstats.threshold = tc;

    /* Create and initialize the TX/RX descriptors chains. */
    priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
    priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
    priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
    pr_debug("open eth0, alloc desc resource\n");
    ret = alloc_dma_desc_resources(priv);
    if (ret < 0) {
        pr_err("%s: DMA descriptors allocation failed\n", __func__);
        goto dma_desc_error;
    }
   /*设置了TX用的定时器回调函数stmmac_init_tx_coalesce,清理发送流程数据*/
    ret = stmmac_hw_setup(dev);
    if (ret < 0) {
        pr_err("%s: Hw setup failed\n", __func__);
        goto init_error;
    }

    if (priv->phydev)
        phy_start(priv->phydev);
//注册中断请求线IRQ,中断处理函数stmmac_interrupt用于接收DMA数据,配合NAPI处理
    /* Request the IRQ lines */
    ret = request_irq(dev->irq, stmmac_interrupt,
              IRQF_SHARED, dev->name, dev);
    if (unlikely(ret < 0)) {
        pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
               __func__, dev->irq, ret);
        goto init_error;
    }

    /* Request the Wake IRQ in case of another line is used for WoL */
    if (priv->wol_irq != dev->irq) {
        ret = request_irq(priv->wol_irq, stmmac_interrupt,
                  IRQF_SHARED, dev->name, dev);
        if (unlikely(ret < 0)) {
            pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
                   __func__, priv->wol_irq, ret);
            goto wolirq_error;
        }
    }

    /* Request the IRQ lines */
    if (priv->lpi_irq != -ENXIO) {
        ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
                  dev->name, dev);
        if (unlikely(ret < 0)) {
            pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
                   __func__, priv->lpi_irq, ret);
            goto lpiirq_error;
        }
    }

    napi_enable(&priv->napi);
    netif_start_queue(dev);

    return 0;

lpiirq_error:
    if (priv->wol_irq != dev->irq)
        free_irq(priv->wol_irq, dev);
wolirq_error:
    free_irq(dev->irq, dev);

init_error:
    free_dma_desc_resources(priv);
dma_desc_error:
    if (priv->phydev)
        phy_disconnect(priv->phydev);
phy_error:
    clk_disable_unprepare(priv->stmmac_clk);

    return ret;
}

看初始化PHY部分,注册了一个回调函数,用于检测网口连接状态
/**
* stmmac_init_phy - PHY initialization
* @dev: net device structure
* Description: it initializes the driver’s PHY state, and attaches the PHY
* to the mac driver.
* Return value:
* 0 on success
*/
static int stmmac_init_phy(struct net_device *dev)
….

phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);

//显示网络连接状态,刚接上或拨出网线时打印,处理相应环境
phy_print_status(phydev);

中断处理函数
/**
* stmmac_interrupt - main ISR
* @irq: interrupt number.
* @dev_id: to pass the net device pointer.
* Description: this is the main driver interrupt service routine.
* It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
* interrupts.
*/
static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
{
struct net_device dev = (struct net_device )dev_id;
struct stmmac_priv *priv = netdev_priv(dev);

if (priv->irq_wake)
    pm_wakeup_event(priv->device, 0);

if (unlikely(!dev)) {
    pr_err("%s: invalid dev pointer\n", __func__);
    return IRQ_NONE;
}

/* To handle GMAC own interrupts */
if (priv->plat->has_gmac) {
    int status = priv->hw->mac->host_irq_status((void __iomem *)
                            dev->base_addr,
                            &priv->xstats);
    if (unlikely(status)) {
        /* For LPI we need to save the tx status */
        if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
            priv->tx_path_in_lpi_mode = true;
        if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
            priv->tx_path_in_lpi_mode = false;
    }
}

/* To handle DMA interrupts */
stmmac_dma_interrupt(priv);

return IRQ_HANDLED;

}`

/**
 * stmmac_dma_interrupt: DMA ISR
 * @priv: driver private structure
 * Description: this is the DMA ISR. It is called by the main ISR.
 * It calls the dwmac dma routine to understand which type of interrupt
 * happened. In case of there is a Normal interrupt and either TX or RX
 * interrupt happened so the NAPI is scheduled.
 */
static void stmmac_dma_interrupt(struct stmmac_priv *priv)
{
    int status;

    status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
    if (likely((status & handle_rx)) || (status & handle_tx)) {
        if (likely(napi_schedule_prep(&priv->napi))) {
            stmmac_disable_dma_irq(priv);
            //加入poll流程
            __napi_schedule(&priv->napi);
        }
    }
    if (unlikely(status & tx_hard_error_bump_tc)) {
        /* Try to bump up the dma threshold on this failure */
        if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
            tc += 64;
            priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
            priv->xstats.threshold = tc;
        }
    } else if (unlikely(status == tx_hard_error))
        stmmac_tx_err(priv);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stmmac ethernet 的相关文章

  • 一篇就让你了解进程的虚拟地址与物理地址是如何进行映射的

    这篇文章可以让你了解进程的虚拟地址是如何映射物理地址的 在刚开始接触虚拟地址的概念时 真的是一头雾水 不知道它到底是个什么东西 一直有这个疑惑 为什么要用虚拟地址 虚拟地址的作用是什么 经过这么多年做过的项目 积攒经验后 我可以略知一些虚拟
  • Android设备启动时出现pop音

    Android设备启动时出现pop音 Android设备启动时出现pop音 环境介绍 原因定位 Android混音 TEE SINK Android HAL层文件 异常原因 解决方案 解决方案应用 Android设备启动时出现pop音 针对
  • OpenHarmony 标准系统HDF框架之I2C驱动开发

    OpenHarmony 标准系统HDF框架之I2C驱动开发 主要内容 I2C 基础知识 I2C 基础知识 概念和特性 I2C 基础知识 协议 四种信号组合 I2C 调试手段 I2C 调试手段 硬件 I2C 调试手段 软件 HDF 框架下的
  • Linux下开发怎样才算入门了?

    记得大学学单片机的时候 也很想知道自己到底学的怎样了 到了什么水平 到处问人单片机开发怎么才算入门了 最后老师跟我说 能做一个万年历出来就算入门了 于是用单片机控制显示器做一个万年历就成了我的目标 通过按键进行日期设置与时间调整 能区分闰年
  • 使用自旋锁实现驱动设备的互斥访问

    代码来源 Linux设备驱动开发详解 宋宝华 p172 int xxx count 0 定义文件打开次数 static int xxx open struct inode inode struct file filp spinlock xx
  • 【RK3399】I3399烧写Debian系统详解

    00 目录 文章目录 00 目录 01 驱动安装 02 镜像文件烧写 03 问题讨论 04 附录 01 驱动安装 1 1 没有安装驱动的时候 显示感叹号 1 2 解压DriverAssitant v5 1 1 zip 1 3 双击Drive
  • BootLoader简介——linux内核的引导

    1 BootLoader 在CPU上电启动时 一般连内存控制器都没有初始化过 根本无法在主存中运行程序 更不可能处在Linux内核启动环境中 为了初始化CPU及其他外设 使得Linux内核可以在系统主存中运行 并让系统符合Lintix内核启
  • Linux驱动之系统移植----uboot移植(有设备树版本),完整移植.

    uboot版本 uboot2020 04 开发板 100ask imx6ull pro 拿到官方uboot后第一步先编译烧写测试 查看哪些驱动可用 哪些不可用 根据开发板厂商提供的资料 使用mx6ull 14x14 evk defconfi
  • stmmac ethernet

    学习笔记 网卡驱动 从这里看起stmmac register platform 注册一个平台驱动 const struct stmmac of data meson dwmac data setup meson dwmac setup fi
  • 十一、Linux驱动之platform总线设备驱动

    1 基本概念 从Linux2 6开始Linux加入了一套驱动管理和注册机制 platform平台总线驱动模型 platform平台总线是一条虚拟总线 platform device为相应的设备 platform driver为相应的驱动 与
  • Linux驱动

    一 前言 设备树是每一个Linux驱动工程师都必须掌握的一个知识点 有很多之前做单片机的朋友刚接触Linux驱动时 会一脸懵 其实设备树的使用并没有大家想像的那么复杂 对于大部分工程师来说 只要会修改即可 很多粉丝留言说 希望彭老师提供一个
  • Linux input 子系统详解

    1 模块概述 1 1 相关资料和代码研究 drivers input include uapi linux input event codes h 2 模块功能 linux核心的输入框架 3 模块学习 3 1 概述 Linux输入设备种类繁
  • Linux内核中断

    一 相关函数 框架 int request irq unsigned int irq irq handler t handler unsigned long flags const char name void dev gt irq 要申请
  • Linux驱动之input输入子系统

    目录 前言 介绍 input dev结构体 输入子系统的使用流程 实例测试 前言 输入子系统用于实现Linux系统输入设备 鼠标 键盘 触摸屏 游戏杆 驱动的一种框架 Linux内核将其中的固定部分放入内核 驱动开发时只需要实现其中的不固定
  • Linux驱动

    HC SR04超声波模块 工作原理参考 超声波模块 star air的博客 CSDN博客 超声波模块 https blog csdn net qq 41262681 article details 95940707 使用超声波测距的操作步骤
  • 嵌入式Linux驱动笔记(二十三)------使用buidroot构建文件系统

    你好 这里是风筝的博客 欢迎和我一起交流 所有的buidroot使用问题都可以看这个在线使用文档 https buildroot org downloads manual manual html about buildroot Buildr
  • 如何修改dmesg log buffer size

    需要修改 Linux 内核源码中的一个控制 log buffer size 的宏 CONFIG LOG BUF SHIFT buffer size 是 2 shift 加大这个就可以 一 配置 make menuconfig General
  • Linux驱动(一)之最简单的驱动程序

    1 前言 为什么要有驱动 为了防止像我等小菜程序员写应用程序的时候权限过高直接去操作底层设备 给设备造成不可挽回的损失 所以要过度一下 让大牛们将底层封装好 应用开发工程师只需要通过特定的接口来完成特定的功能就可以了 2 应用 通常情况下
  • Linux驱动_多点电容触摸

    一丶Linux下多点电容触摸驱动框架 电容触摸屏IC是FT5426 为IIC协议芯片 因此需要编写IIC驱动 触摸IC会发出中断信号 并在中断服务函数中上报信息 因此需要编写中断框架 触摸屏向Linux内核上报的信息都属于Input子系统
  • 【内核驱动】Linux概述

    00 目录 文章目录 00 目录 01 Unix简介 02 Linux简介 03 Linux发展史 04 单内核与微内核区别 05 Linux内核 06 Linux内核组成 07 Linux官方网站 08 附录 01 Unix简介 UNIX

随机推荐

  • window.open对storage有没有影响?

    首先在浏览器开发者模式打印如下信息 设置storage存值 sessionStorage setItem aaa 111 localStorage setItem bbb 222 新开一个浏览器窗口 在开发者模式打印窗口获取上一个窗口存储的
  • JAVA算法(分糖果)

    题目描述 有n个小朋友围坐成一圈 老师给每个小朋友随机发偶数个糖果 然后进行下面的游戏 每个小朋友都把自己的糖果分一半给左手边的孩子 一轮分糖后 拥有奇数颗糖的孩子由老师补给1个糖果 从而变成偶数 反复进行这个游戏 直到所有小朋友的糖果数都
  • 版本记录总结

    对构建中使用的版本进行记录
  • 【vue】this.$router.replace跳转不起作用 Router push or replace not working

    项目场景 商城APP底部导航切换对应页面 问题描述 提示 这里描述项目中遇到的问题 Just sit there clicking the home btn watching log show me home but never getti
  • Git远程库代码回退

    一 首先认识两个回退过程中很重要的命令 1 git log 显示所有提交过的版本信息 不包括已经被删除的 commit 记录和 reset 的操作 空格向下翻页 b 向上翻页 q 退出 git log pretty oneline git
  • 华为od机试 C++ 【计算最少步数】

    题目 小明计划在周末去爬山 他有一份包含山峰高度的地图 其中 0 代表平地 而 1 到 9 表示不同的山峰高度 小明可以向上 下 左或右移动一步 但是 由于他不想爬得太累 他决定只在高度差不超过 k 的地方移动 现在他站在地图的左上角 你能
  • 做好五年不跳槽的准备

    入职半年了 我觉得这里可以长久发展 其一 工作能胜任 我感觉找回自信了 甚至有些傲娇了 说明osg确实比较对口 做擅长的工作 会越做越有信心 其二 老大靠谱 老大十几年经验 并且很有耐心 工作方式也对 比如 先给你代码 在这个基础上改 并且
  • 超长整数相加

    链接 https www nowcoder com questionTerminal 5821836e0ec140c1aa29510fd05f45fc orderByHotValue 1 mutiTagIds 640 643 page 6
  • Python数据挖掘 数据预处理案例(以航空公司数据为例)

    Python数据预处理 一 内容 1 数据清洗 2 数据集成 3 数据可视化 二 实验数据 根据航空公司系统内的客户基本信息 乘机信息以及积分信息等详细数据 依据末次飞行日期 LAST FLIGHT DATE 以2014年3月31日为结束时
  • go build遇见“module *** found, but does not contain package ***”

    在实际项目中编译版本时遇见以下问题 common middleware sentinel go 4 2 module github com alibaba sentinel golang latest found v1 0 2 but do
  • SSH项目所需jar包下载地址

    struts2下载地址 http pan baidu com s 1c0joXbi hibernate下载地址 http pan baidu com s 1c0ues1a spring下载地址 http pan baidu com s 1b
  • JS学习篇(一)—— 数据类型篇

    JS学习篇 一 数据类型篇 JS的有八种数据类型 七种基本类型 undefined null Boolean number string symbol bigint 一种引用类型 object 七种基本类型 1 undefined 定义 通
  • (新)关于修改window.navigator.webdriver代码失效问题

    文章目录 前文回顾 溯源追根 解决方案 新登陆代码 写在最后 前文回顾 前面写过两篇关于sycm自动化爬取的文章 关于抓取代码的文章链接 出师未捷身先死的sycm数据自动化 关于chrome版本迭代后 代码失效问题解决方案的文章链接 关于修
  • mysql8.0一 服务启动

    声明 本文 禁止转载 本文所有观点和概念都系个人总结 难免存在疏漏之处 为不至于诱导初学者误入歧途 望各位以自己实践为准 特此声明 如有错误请告知 启动 流程 windows 7系统 创建data空目录 创建my ini文本文件 内容如下
  • Mac如何通过Xcode安装GCC编译器 How to install gcc on mac with xcode

    什么是GCC GCC GNU Compiler Collection 是由自由软件基金会 FSF Free Software Foundation Inc 研发的开源编译器集合 用一句话说 GCC就是除Windows以外的平台上使用最广的编
  • Java反射copy对象源到目标

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 使用反射机制 二 使用步骤 1 引入库 2 Copy数据 3 Fields 自定义注解 总结 前言 例如 随着很多流行的框架出现 反射也成了其中必不可少的
  • 【项目实战】Python实现循环神经网络SimpleRNN、LSTM进行淘宝商品评论情感分析(含爬虫程序)

    说明 这是一个机器学习实战项目 附带数据 代码 如需数据 完整代码可以直接到文章最后获取 1 项目背景 随着信息化社会的发展 互联网成为方便 快捷的信息获取渠道之一 在电子商务和社会网站中 大量非结构化的评论文本作为最直观的用户体验数据被保
  • 机器学习之k 均值聚类教程(代码实战,详解核心算法)

    k 均值聚类 1 引入依赖 import numpy as np import matplotlib pyplot as plt 调用sklearn中的方法直接生成数据 from sklearn datasets samples gener
  • vue2 ElementUI 表单标签、表格表头添加问号图标提示

    文章目录 1 问题背景 2 element ui悬浮提示定义 3 基础 4 延申 5 参考 1 问题背景 使用element ui有时候需要对表格的表头 表单的标签进行自定义 添加问号的悬浮提示 要达到的效果 如图所示 2 element
  • stmmac ethernet

    学习笔记 网卡驱动 从这里看起stmmac register platform 注册一个平台驱动 const struct stmmac of data meson dwmac data setup meson dwmac setup fi