I.MX6 PHY fixup 调用流程 hacking
/*********************************************************************************** I.MX6 PHY fixup 调用流程 hacking* 说明:* 跟一下i.MX6中对PHY进行fixup的代码是如何被调用的。* * 2017-4-14 深圳 龙华民治樟坑村 曾剑锋*********************************************************************************/ static struct platform_driver fec_driver = { <-----+.driver = { |.name = DRIVER_NAME, |.owner = THIS_MODULE, |.pm = &fec_pm_ops, |.of_match_table = fec_dt_ids, |}, |.id_table = fec_devtype, ---------*-+.probe = fec_probe, | |.remove = fec_drv_remove, | | }; | || | module_platform_driver(fec_driver); ---------+ || MODULE_ALIAS("platform:"DRIVER_NAME); | MODULE_LICENSE("GPL"); || static int | fec_probe(struct platform_device *pdev) <----------+ {struct fec_enet_private *fep;struct fec_platform_data *pdata;struct net_device *ndev;int i, irq, ret = 0;struct resource *r;const struct of_device_id *of_id;static int dev_id;struct device_node *np = pdev->dev.of_node, *phy_node;int num_tx_qs;int num_rx_qs;fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);/* Init network device */ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private),num_tx_qs, num_rx_qs);if (!ndev)return -ENOMEM;SET_NETDEV_DEV(ndev, &pdev->dev);/* setup board info structure */fep = netdev_priv(ndev);of_id = of_match_device(fec_dt_ids, &pdev->dev);if (of_id)pdev->id_entry = of_id->data;fep->quirks = pdev->id_entry->driver_data;fep->netdev = ndev;fep->num_rx_queues = num_rx_qs;fep->num_tx_queues = num_tx_qs;#if !defined(CONFIG_M5272)/* default enable pause frame auto negotiation */if (fep->quirks & FEC_QUIRK_HAS_GBIT)fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; #endif/* Select default pin state */pinctrl_pm_select_default_state(&pdev->dev);r = platform_get_resource(pdev, IORESOURCE_MEM, 0);fep->hwp = devm_ioremap_resource(&pdev->dev, r);if (IS_ERR(fep->hwp)) {ret = PTR_ERR(fep->hwp);goto failed_ioremap;}fep->pdev = pdev;fep->dev_id = dev_id++;platform_set_drvdata(pdev, ndev);fec_enet_of_parse_stop_mode(pdev);if (of_get_property(np, "fsl,magic-packet", NULL))fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;phy_node = of_parse_phandle(np, "phy-handle", 0);if (!phy_node && of_phy_is_fixed_link(np)) {ret = of_phy_register_fixed_link(np);if (ret < 0) {dev_err(&pdev->dev,"broken fixed-link specification\n");goto failed_phy;}phy_node = of_node_get(np);}fep->phy_node = phy_node;ret = of_get_phy_mode(pdev->dev.of_node);if (ret < 0) {pdata = dev_get_platdata(&pdev->dev);if (pdata)fep->phy_interface = pdata->phy;elsefep->phy_interface = PHY_INTERFACE_MODE_MII;} else {fep->phy_interface = ret;}fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");if (IS_ERR(fep->clk_ipg)) {ret = PTR_ERR(fep->clk_ipg);goto failed_clk;}fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb");if (IS_ERR(fep->clk_ahb)) {ret = PTR_ERR(fep->clk_ahb);goto failed_clk;}fep->itr_clk_rate = clk_get_rate(fep->clk_ahb);/* enet_out is optional, depends on board */fep->clk_enet_out = devm_clk_get(&pdev->dev, "enet_out");if (IS_ERR(fep->clk_enet_out))fep->clk_enet_out = NULL;fep->ptp_clk_on = false;mutex_init(&fep->ptp_clk_mutex);/* clk_ref is optional, depends on board */fep->clk_ref = devm_clk_get(&pdev->dev, "enet_clk_ref");if (IS_ERR(fep->clk_ref))fep->clk_ref = NULL;fep->bufdesc_ex = fep->quirks & FEC_QUIRK_HAS_BUFDESC_EX;fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");if (IS_ERR(fep->clk_ptp)) {fep->clk_ptp = NULL;fep->bufdesc_ex = false;}pm_runtime_enable(&pdev->dev);ret = fec_enet_clk_enable(ndev, true);if (ret)goto failed_clk;fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");if (!IS_ERR(fep->reg_phy)) {ret = regulator_enable(fep->reg_phy);if (ret) {dev_err(&pdev->dev,"Failed to enable phy regulator: %d\n", ret);goto failed_regulator;}} else {fep->reg_phy = NULL;}fec_reset_phy(pdev);if (fep->bufdesc_ex)fec_ptp_init(pdev);ret = fec_enet_init(ndev); ----------------------------+if (ret) |goto failed_init; ||for (i = 0; i < FEC_IRQ_NUM; i++) { |irq = platform_get_irq(pdev, i); |if (irq < 0) { |if (i) |break; |ret = irq; |goto failed_irq; |} |ret = devm_request_irq(&pdev->dev, irq, fec_enet_interrupt, |0, pdev->name, ndev); |if (ret) |goto failed_irq; ||fep->irq[i] = irq; |} ||ret = of_property_read_u32(np, "fsl,wakeup_irq", &irq); |if (!ret && irq < FEC_IRQ_NUM) |fep->wake_irq = fep->irq[irq]; |else |fep->wake_irq = fep->irq[0]; ||init_completion(&fep->mdio_done); |ret = fec_enet_mii_init(pdev); |if (ret) |goto failed_mii_init; ||/* Carrier starts down, phylib will bring it up */ |netif_carrier_off(ndev); |fec_enet_clk_enable(ndev, false); |pinctrl_pm_select_sleep_state(&pdev->dev); ||ret = register_netdev(ndev); |if (ret) |goto failed_register; ||device_init_wakeup(&ndev->dev, fep->wol_flag & |FEC_WOL_HAS_MAGIC_PACKET); ||if (fep->bufdesc_ex && fep->ptp_clock) |netdev_info(ndev, "registered PHC device %d\n", fep->dev_id); ||fep->rx_copybreak = COPYBREAK_DEFAULT; |INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); |return 0; || failed_register: |fec_enet_mii_remove(fep); | failed_mii_init: | failed_irq: | failed_init: |if (fep->reg_phy) |regulator_disable(fep->reg_phy); | failed_regulator: |fec_enet_clk_enable(ndev, false); | failed_clk: | failed_phy: |of_node_put(phy_node); | failed_ioremap: |free_netdev(ndev); ||return ret; | } ||/* |* XXX: We need to clean up on failure exits here. |* |*/ | static int fec_enet_init(struct net_device *ndev) <-----------------+ {struct fec_enet_private *fep = netdev_priv(ndev);struct fec_enet_priv_tx_q *txq;struct fec_enet_priv_rx_q *rxq;struct bufdesc *cbd_base;dma_addr_t bd_dma;int bd_size;unsigned int i;#if defined(CONFIG_ARM)fep->rx_align = 0xf;fep->tx_align = 0xf; #elsefep->rx_align = 0x3;fep->tx_align = 0x3; #endiffec_enet_alloc_queue(ndev);if (fep->bufdesc_ex)fep->bufdesc_size = sizeof(struct bufdesc_ex);elsefep->bufdesc_size = sizeof(struct bufdesc);bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) *fep->bufdesc_size;/* Allocate memory for buffer descriptors. */cbd_base = dma_alloc_coherent(NULL, bd_size, &bd_dma,GFP_KERNEL);if (!cbd_base) {return -ENOMEM;}memset(cbd_base, 0, bd_size);/* Get the Ethernet address */fec_get_mac(ndev);/* make sure MAC we just acquired is programmed into the hw */fec_set_mac_address(ndev, NULL);/* Set receive and transmit descriptor base. */for (i = 0; i < fep->num_rx_queues; i++) {rxq = fep->rx_queue[i];rxq->index = i;rxq->rx_bd_base = (struct bufdesc *)cbd_base;rxq->bd_dma = bd_dma;if (fep->bufdesc_ex) {bd_dma += sizeof(struct bufdesc_ex) * rxq->rx_ring_size;cbd_base = (struct bufdesc *)(((struct bufdesc_ex *)cbd_base) + rxq->rx_ring_size);} else {bd_dma += sizeof(struct bufdesc) * rxq->rx_ring_size;cbd_base += rxq->rx_ring_size;}}for (i = 0; i < fep->num_tx_queues; i++) {txq = fep->tx_queue[i];txq->index = i;txq->tx_bd_base = (struct bufdesc *)cbd_base;txq->bd_dma = bd_dma;if (fep->bufdesc_ex) {bd_dma += sizeof(struct bufdesc_ex) * txq->tx_ring_size;cbd_base = (struct bufdesc *)(((struct bufdesc_ex *)cbd_base) + txq->tx_ring_size);} else {bd_dma += sizeof(struct bufdesc) * txq->tx_ring_size;cbd_base += txq->tx_ring_size;}}/* The FEC Ethernet specific entries in the device structure */ndev->watchdog_timeo = TX_TIMEOUT;ndev->netdev_ops = &fec_netdev_ops; --------------------+ndev->ethtool_ops = &fec_enet_ethtool_ops; ||writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK); |netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT); ||if (fep->quirks & FEC_QUIRK_HAS_VLAN) |/* enable hw VLAN support */ |ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; ||if (fep->quirks & FEC_QUIRK_HAS_CSUM) { |ndev->gso_max_segs = FEC_MAX_TSO_SEGS; ||/* enable hw accelerator */ |ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM || NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO); |fep->csum_flags |= FLAG_RX_CSUM_ENABLED; |} ||if (fep->quirks & FEC_QUIRK_HAS_AVB) { |fep->tx_align = 0; |fep->rx_align = 0x3f; |} ||ndev->hw_features = ndev->features; ||fec_restart(ndev); ||return 0; | } || static const struct net_device_ops fec_netdev_ops = { <-----------+.ndo_open = fec_enet_open, ---------+.ndo_stop = fec_enet_close, |.ndo_start_xmit = fec_enet_start_xmit, |.ndo_select_queue = fec_enet_select_queue, |.ndo_set_rx_mode = set_multicast_list, |.ndo_change_mtu = eth_change_mtu, |.ndo_validate_addr = eth_validate_addr, |.ndo_tx_timeout = fec_timeout, |.ndo_set_mac_address = fec_set_mac_address, |.ndo_do_ioctl = fec_enet_ioctl, | #ifdef CONFIG_NET_POLL_CONTROLLER |.ndo_poll_controller = fec_poll_controller, | #endif |.ndo_set_features = fec_set_features, | }; || static int | fec_enet_open(struct net_device *ndev) <--------+ {struct fec_enet_private *fep = netdev_priv(ndev);const struct platform_device_id *id_entry =platform_get_device_id(fep->pdev);int ret;pinctrl_pm_select_default_state(&fep->pdev->dev);ret = fec_enet_clk_enable(ndev, true);if (ret)return ret;/* I should reset the ring buffers here, but I don't yet know* a simple way to do that.*/ret = fec_enet_alloc_buffers(ndev);if (ret)goto err_enet_alloc;/* Init MAC firstly for suspend/resume with megafix off case */fec_restart(ndev);/* Probe and connect to PHY when open the interface */ret = fec_enet_mii_probe(ndev); -----+if (ret) |goto err_enet_mii_probe; ||napi_enable(&fep->napi); |phy_start(fep->phy_dev); |netif_tx_start_all_queues(ndev); ||pm_runtime_get_sync(ndev->dev.parent); |if ((id_entry->driver_data & FEC_QUIRK_BUG_WAITMODE) && |!fec_enet_irq_workaround(fep)) |pm_qos_add_request(&ndev->pm_qos_req, |PM_QOS_CPU_DMA_LATENCY, |0); |else |pm_qos_add_request(&ndev->pm_qos_req, |PM_QOS_CPU_DMA_LATENCY, |PM_QOS_DEFAULT_VALUE); ||device_set_wakeup_enable(&ndev->dev, fep->wol_flag & |FEC_WOL_FLAG_ENABLE); |fep->miibus_up_failed = false; ||return 0; || err_enet_mii_probe: |fec_enet_free_buffers(ndev); | err_enet_alloc: |fep->miibus_up_failed = true; |if (!fep->mii_bus_share) |pinctrl_pm_select_sleep_state(&fep->pdev->dev); |return ret; | } || static int fec_enet_mii_probe(struct net_device *ndev) <----+ {struct fec_enet_private *fep = netdev_priv(ndev);struct phy_device *phy_dev = NULL;char mdio_bus_id[MII_BUS_ID_SIZE];char phy_name[MII_BUS_ID_SIZE + 3];int phy_id;int dev_id = fep->dev_id;fep->phy_dev = NULL;if (fep->phy_node) {phy_dev = of_phy_connect(ndev, fep->phy_node,&fec_enet_adjust_link, 0,fep->phy_interface);if (!phy_dev)return -ENODEV;} else {/* check for attached phy */for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {if ((fep->mii_bus->phy_mask & (1 << phy_id)))continue;if (fep->mii_bus->phy_map[phy_id] == NULL)continue;if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)continue;if (dev_id--)continue;strlcpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);break;}if (phy_id >= PHY_MAX_ADDR) {netdev_info(ndev, "no PHY, assuming direct connection to switch\n");strlcpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);phy_id = 0;}snprintf(phy_name, sizeof(phy_name),PHY_ID_FMT, mdio_bus_id, phy_id);phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, ---------------+fep->phy_interface); |} ||if (IS_ERR(phy_dev)) { |netdev_err(ndev, "could not attach to PHY\n"); |return PTR_ERR(phy_dev); |} ||/* mask with MAC supported features */ |if (fep->quirks & FEC_QUIRK_HAS_GBIT) { |phy_dev->supported &= PHY_GBIT_FEATURES; |// phy_dev->supported &= ~SUPPORTED_1000baseT_Half; |phy_dev->supported |= SUPPORTED_Pause; |// phy_dev->supported |= SUPPORTED_1000baseT_Half; |printk("FEC_QUIRK_HAS_GBIT\n"); | #if !defined(CONFIG_M5272) |phy_dev->supported |= SUPPORTED_Pause; | #endif |phy_dev->advertising = phy_dev->supported; |} |else |{ |printk("PHY_BASIC_FEATURES\n"); |// phy_dev->supported &= PHY_BASIC_FEATURES; |phy_dev->advertising = phy_dev->supported & PHY_BASIC_FEATURES; |} |// phy_dev->advertising = phy_dev->supported; ||fep->phy_dev = phy_dev; |fep->link = 0; |fep->full_duplex = 0; ||netdev_info(ndev, "Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", |fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), |fep->phy_dev->irq); ||return 0; | } || struct phy_device *phy_connect(struct net_device *dev, const char *bus_id, <--------+void (*handler)(struct net_device *),phy_interface_t interface) {struct phy_device *phydev;struct device *d;int rc;/* Search the list of PHY devices on the mdio bus for the* PHY with the requested name*/d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id);if (!d) {pr_err("PHY %s not found\n", bus_id);return ERR_PTR(-ENODEV);}phydev = to_phy_device(d);rc = phy_connect_direct(dev, phydev, handler, interface); --------------+if (rc) |return ERR_PTR(rc); ||return phydev; | } | EXPORT_SYMBOL(phy_connect); || int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, <----+void (*handler)(struct net_device *),phy_interface_t interface) {int rc;rc = phy_attach_direct(dev, phydev, phydev->dev_flags, interface); --------+if (rc) |return rc; ||phy_prepare_link(phydev, handler); |phy_start_machine(phydev); |if (phydev->irq > 0) |phy_start_interrupts(phydev); ||return 0; | } | EXPORT_SYMBOL(phy_connect_direct); || int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, <-------+u32 flags, phy_interface_t interface) {struct device *d = &phydev->dev;int err;/* Assume that if there is no driver, that it doesn't* exist, and we should use the genphy driver.*/if (NULL == d->driver) {if (phydev->is_c45)d->driver = &genphy_driver[GENPHY_DRV_10G].driver;elsed->driver = &genphy_driver[GENPHY_DRV_1G].driver;err = d->driver->probe(d);if (err >= 0)err = device_bind_driver(d);if (err)return err;}if (phydev->attached_dev) {dev_err(&dev->dev, "PHY already attached\n");return -EBUSY;}phydev->attached_dev = dev;dev->phydev = phydev;phydev->dev_flags = flags;phydev->interface = interface;phydev->state = PHY_READY;/* Do initial configuration here, now that* we have certain key parameters* (dev_flags and interface)*/err = phy_init_hw(phydev); --------------------+if (err) |phy_detach(phydev); |else |phy_resume(phydev); ||return err; | } | EXPORT_SYMBOL(phy_attach_direct); || int phy_init_hw(struct phy_device *phydev) <------------+ {int ret;if (!phydev->drv || !phydev->drv->config_init)return 0;ret = phy_write(phydev, MII_BMCR, BMCR_RESET);if (ret < 0)return ret;ret = phy_poll_reset(phydev);if (ret < 0)return ret;ret = phy_scan_fixups(phydev); -------------+if (ret < 0) |return ret; ||return phydev->drv->config_init(phydev); | } | EXPORT_SYMBOL(phy_init_hw); || /* Runs any matching fixups for this phydev */ | int phy_scan_fixups(struct phy_device *phydev) <--------+ {struct phy_fixup *fixup;mutex_lock(&phy_fixup_lock);list_for_each_entry(fixup, &phy_fixup_list, list) { ------------------+if (phy_needs_fixup(phydev, fixup)) { --------+ |int err = fixup->run(phydev); | || |if (err < 0) { | |mutex_unlock(&phy_fixup_lock); | |return err; | |} | |} | |} | |mutex_unlock(&phy_fixup_lock); | || |return 0; | | } | | EXPORT_SYMBOL(phy_scan_fixups); | |v--------------------------------------+ | static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) | { |if (strcmp(fixup->bus_id, dev_name(&phydev->dev)) != 0) |if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) |return 0; ||if ((fixup->phy_uid & fixup->phy_uid_mask) != |(phydev->phy_id & fixup->phy_uid_mask)) |if (fixup->phy_uid != PHY_ANY_UID) |return 0; ||return 1; | } || static LIST_HEAD(phy_fixup_list); <-----------------+| int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, ----*-+int (*run)(struct phy_device *)) | | { | |struct phy_fixup *fixup = kzalloc(sizeof(*fixup), GFP_KERNEL); | || |if (!fixup) | |return -ENOMEM; | || |strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id)); | |fixup->phy_uid = phy_uid; | |fixup->phy_uid_mask = phy_uid_mask; | |fixup->run = run; | || |mutex_lock(&phy_fixup_lock); | |list_add_tail(&fixup->list, &phy_fixup_list); <-----------------+ |mutex_unlock(&phy_fixup_lock); ||return 0; | } | EXPORT_SYMBOL(phy_register_fixup); || static void __init imx6q_enet_phy_init(void) -------------------*-+ { | |if (IS_BUILTIN(CONFIG_PHYLIB)) { | |phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, | |ksz9021rn_phy_fixup); | |phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK, | |ksz9031rn_phy_fixup); | |phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff, <-------------+ |ar8031_phy_fixup); --------------+ |phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef, | |ar8035_phy_fixup); | |} | | } | || | static int ar8031_phy_fixup(struct phy_device *dev) <-------------+ | { |u16 val; ||/* Set RGMII IO voltage to 1.8V */ |phy_write(dev, 0x1d, 0x1f); |phy_write(dev, 0x1e, 0x8); ||/* disable phy AR8031 SmartEEE function. */ |phy_write(dev, 0xd, 0x3); |phy_write(dev, 0xe, 0x805d); |phy_write(dev, 0xd, 0x4003); |val = phy_read(dev, 0xe); |val &= ~(0x1 << 8); |phy_write(dev, 0xe, val); ||/* To enable AR8031 output a 125MHz clk from CLK_25M */ |phy_write(dev, 0xd, 0x7); |phy_write(dev, 0xe, 0x8016); |phy_write(dev, 0xd, 0x4007); ||val = phy_read(dev, 0xe); |val &= 0xffe3; |val |= 0x18; |phy_write(dev, 0xe, val); ||/* introduce tx clock delay */ |phy_write(dev, 0x1d, 0x5); |val = phy_read(dev, 0x1e); |val |= 0x0100; |phy_write(dev, 0x1e, val); ||return 0; | } || static inline void imx6q_enet_init(void) -----------------------------------*-+ { | |imx6_enet_mac_init("fsl,imx6q-fec"); | |imx6q_enet_phy_init(); <-----------------------------------+ |imx6q_1588_init(); |if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_2_0) |imx6q_enet_clk_sel(); |imx6q_enet_plt_init(); | } || static void __init imx6q_init_machine(void) | { |struct device *parent; ||if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_2_0) |imx_print_silicon_rev("i.MX6QP", IMX_CHIP_REVISION_1_0); |else |imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q", |imx_get_soc_revision()); ||mxc_arch_reset_init_dt(); ||parent = imx_soc_device_init(); |if (parent == NULL) |pr_warn("failed to initialize soc device\n"); ||of_platform_populate(NULL, of_default_bus_match_table, |imx6q_auxdata_lookup, parent); ||imx6q_enet_init(); <---------------------------+imx_anatop_init();imx6q_csi_mux_init();cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();imx6q_mini_pcie_init(); }
I.MX6 PHY fixup 调用流程 hacking相关推荐
- I.MX6 ar1020 SPI device driver hacking
/************************************************************************************* I.MX6 ar1020 ...
- I.MX6 Linux Qt 启动流程跟踪
/*************************************************************************** I.MX6 Linux Qt 启动流程跟踪* ...
- I.MX6 Linux Serial Baud Rate hacking
/********************************************************************************* I.MX6 Linux Seria ...
- RPC 笔记(01)— RPC概念、调用流程、RPC 与 Restful API 区别
1. 基本概念 PRC 远程过程调用 Remote Procedure Call,其就是一个节点请求另外一个节点提供的服务.当两个物理分离的子系统需要建立逻辑上的关联时,RPC 是牵线搭桥的常见技术手 ...
- novaclient的api调用流程与开发
novaclient的api调用流程与开发 2015年07月05日 19:27:17 qiushanjushi 阅读数:3915 http://blog.csdn.net/tpiperatgod/ar ...
- java 操作uart串口_【tty】应用程序调用write写串口调用流程
这几天在跟进串口使能流控后收发异常问题,特简单梳理了下应用程序执行write操作的调用流程,在这简单记录下,平台为全志方案 tty_io.c tty_io.c ...
- go语言基础之递归函数的调用流程
一.递归函数的调用流程 package main //必须import "fmt"func test(a int) {if a == 1 { //函数终止调用的条件,非常重要fmt ...
- 【Android 逆向】Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )
文章目录 一.进程注入原理 二.远程调用流程 ( 获取 so 动态库地址 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 ) 一.进程注入原理 调试进程 At ...
- Retrofit2源码解析——网络调用流程(下)
Retrofit2源码解析系列 Retrofit2源码解析(一) Retrofit2源码解析--网络调用流程(上) 本文基于Retrofit2的2.4.0版本 implementation 'com. ...
最新文章
- SQLite.swift的简单使用
- Golang协程goroutine和管道channel结合案例
- Java死锁、活锁,悲观锁、乐观锁
- 图形工具包 linux,GTK 4.0图形工具包正式发布:时隔四年的重大版本!
- multism中ui和uo应该怎么表示_王者荣耀:梦泪直播时谈到体验服大改动,表示装备的改动很关键...
- sae 微信 java web_[1] 微信公众号与sae的web应用之间的配置
- Linux命令解释之mkfs.ext3
- Codeforces Round #511 (Div. 1) 题解
- SQL入门教程(一):基础知识
- 测试人员必会用例设计方法--正交表
- 计算机中存储单位的换算
- 跟我学c++中级篇——decay
- sina股票接口更新:Kinsoku jikou desu
- win7系统如何映射服务器,教你win7系统映射网络驱动器的操作方法
- JavaSE学习笔记之网络编程
- 要学就学透彻!Spring Security 中 CSRF 防御源码解析
- 机器学习中的ground truth
- 我要搬家到51CTO了
- INE深圳硅谷双线发布演讲实录 | CEOCTO羽睿-去中心化的最后一块版图
- c语言为什么运行不出数据,程序运行后可以输入数据,但是之后为什么没有显示?...
热门文章
- Selenium自动化之最大化浏览器操作
- linux shell 编辑文件内容,Shell编辑与文本处理(Bash sed文本编辑)
- numpy numpy.concatenate()函数
- Web 应用性能和压力测试工具 Gor
- 你的团队是王者还是青铜(下)
- 【论文精读】Smoothly Varying Affine Stitching
- 读人工智能发展报告学习心得(大纲)
- java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
- 【玩转嵌入式屏幕显示】(七)LCD中文字符显示机制
- 联科教育【免费公开课】每周一和周三晚19:30分:C#程序设计--基础篇,赶快围观啦~~~