mmc频率配置

代码路径及功能

 以zync的 sd mmc来解读

涉及到的设备驱动文件:

文件说明
\drivers\mmc\host\dw_mmc-pltfm.c 作为mmc的驱动的入口
\drivers\mmc\host\dw_mmc.c       dw mmc的通用驱动。虽然各个芯片厂家都有自己的外设接口,但是这些接口通常用的同一个IP,例如此处的dw即为Synopsys DesignWare 的mmc ip 
drivers\mmc\core\host.cmmc控制器通用接口
\drivers\mmc\core\core.c控制器与mmc设备的结合处。mmc扫描设备的入口
\drivers\mmc\core\mmc.c

DTS配置

配置

mmc0: dwmmc@e0043000 {
			compatible = "fmsh,psoc-dw-mshc";
			reg = <0xe0043000 0x1000>;
			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clkc NCLK_AHB_SDIO0>, <&clkc NCLK_SDIO0>;
			clock-names = "biu", "ciu";
			#address-cells = <1>;
			#size-cells = <0>;
			data-addr = <0x100>;
			max-frequency = <50000000>;

解析

在 host.c中的函数实现对DTS中 host控制器(SD SDIO EMMC等)的配置解析。这里可以看到

host->caps 包含了DTS的属性。此处解析出的最大频率max-frequency放到了host->f_max

int mmc_of_parse(struct mmc_host *host)
{
	struct device *dev = host->parent;
	u32 bus_width;
	int ret;
	bool cd_cap_invert, cd_gpio_invert = false;
	bool ro_cap_invert, ro_gpio_invert = false;

	if (!dev || !dev_fwnode(dev))
		return 0;

	/* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
	if (device_property_read_u32(dev, "bus-width", &bus_width) < 0) {
		dev_dbg(host->parent,
			"\"bus-width\" property is missing, assuming 1 bit.\n");
		bus_width = 1;
	}

	switch (bus_width) {
	case 8:
		host->caps |= MMC_CAP_8_BIT_DATA;
		/* Hosts capable of 8-bit transfers can also do 4 bits */
	case 4:
		host->caps |= MMC_CAP_4_BIT_DATA;
		break;
	case 1:
		break;
	default:
		dev_err(host->parent,
			"Invalid \"bus-width\" value %u!\n", bus_width);
		return -EINVAL;
	}
    //此处解析设备树中的最大的频率
	/* f_max is obtained from the optional "max-frequency" property */
	device_property_read_u32(dev, "max-frequency", &host->f_max);

mmc控制器初始化

    针对dw mmc控制器,此控制器的初始化函数中针对每个通道调用接口 dw_mci_init_slot完成初始化,主要包括如下三个部分: 

  host分配

       这里我们主要关注一个个delay work,即mmc rescan      

mmc_alloc_host


INIT_DELAYED_WORK(&host->detect, mmc_rescan);
	INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work);
	setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);

   解析dts

       参考1.2 节

  host添加

     将 mmc host控制器添加到系统中

      mmc_add_host

     

void mmc_start_host(struct mmc_host *host)
{
	host->f_init = max(freqs[0], host->f_min);
	host->rescan_disable = 0;
	host->ios.power_mode = MMC_POWER_UNDEFINED;

	if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) {
		mmc_claim_host(host);
		mmc_power_up(host, host->ocr_avail);
		mmc_release_host(host);
	}

	mmc_gpiod_request_cd_irq(host);
	_mmc_detect_change(host, 0, false);
}
//此处开始mmc设备的探测,也就是说将host控制器添加到系统后,再探测host下挂的mmc
static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
				bool cd_irq)
{
	/*
	 * If the device is configured as wakeup, we prevent a new sleep for
	 * 5 s to give provision for user space to consume the event.
	 */
	if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&
		device_can_wakeup(mmc_dev(host)))
		pm_wakeup_event(mmc_dev(host), 5000);

	host->detect_change = 1;
	mmc_schedule_delayed_work(&host->detect, delay);
}

 powerup(第一次配置速率)

      此处第一次配置mmc的速率。此处 配置的速率为f_init


/*
 * Apply power to the MMC stack.  This is a two-stage process.
 * First, we enable power to the card without the clock running.
 * We then wait a bit for the power to stabilise.  Finally,
 * enable the bus drivers and clock to the card.
 *
 * We must _NOT_ enable the clock prior to power stablising.
 *
 * If a host does all the power sequencing itself, ignore the
 * initial MMC_POWER_UP stage.
 */
void mmc_power_up(struct mmc_host *host, u32 ocr)
{
	if (host->ios.power_mode == MMC_POWER_ON)
		return;

	
	host->ios.clock = host->f_init;

	host->ios.power_mode = MMC_POWER_ON;
	mmc_set_ios(host);

	/*
	 * This delay must be at least 74 clock sizes, or 1 ms, or the
	 * time required to reach a stable voltage.
	 */
	mmc_delay(10);
}

 上电打印

   可以看到第一行 控制器请求的速率为400K,这个为默认初始化的值。

  2.521074] mmc_host mmc0: Bus speed (slot 0) = 99999999Hz (slot req 400000Hz, actual 399999HZ div = 125)
[    2.530608] CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.14.55-fmsh20220223 #27ware name: FMSH PSOC Platform
[    2.542168] [<8010e648>] (unwind_backtrace) from [<8010a970>] (show_stack+0x10/0x14)
[    2.549890] [<8010a970>] (show_stack) from [<806483c4>] (dump_stack+0x7c/0x9c)
[    2.557094] [<806483c4>] (dump_stack) from [<8051f840>] (dw_mci_setup_bus+0x18c/0x1c4)
[    2.564987] [<8051f840>] (dw_mci_setup_bus) from [<8051f9a0>] (dw_mci_set_ios+0x128/0x164)
[    2.573227] [<8051f9a0>] (dw_mci_set_ios) from [<80509158>] (mmc_power_up+0xa4/0xb0)
[    2.580947] [<80509158>] (mmc_power_up) from [<80509cf4>] (mmc_start_host+0x48/0x74)
[    2.588665] [<80509cf4>] (mmc_start_host) from [<8050acb4>] (mmc_add_host+0x3c/0x4c)
[    2.596384] [<8050acb4>] (mmc_add_host) from [<8051f378>] (dw_mci_probe+0x924/0xb88)
[    2.604105] [<8051f378>] (dw_mci_probe) from [<804179fc>] (platform_drv_probe+0x50/0x9c)
[    2.612169] [<804179fc>] (platform_drv_probe) from [<8041654c>] (driver_probe_device+0x1dc/0x298)
[    2.621009] [<8041654c>] (driver_probe_device) from [<80416684>] (__driver_attach+0x7c/0xa8)
[    2.629417] [<80416684>] (__driver_attach) from [<80414dac>] (bus_for_each_dev+0x7c/0x8c)
[    2.637566] [<80414dac>] (bus_for_each_dev) from [<80415bd4>] (bus_add_driver+0x16c/0x1d4)
[    2.645801] [<80415bd4>] (bus_add_driver) from [<80416e08>] (driver_register+0xa0/0xe0)
[    2.653778] [<80416e08>] (driver_register) from [<801019ac>] (do_one_initcall+0xf8/0x118)
[    2.661929] [<801019ac>] (do_one_initcall) from [<80900da8>] (kernel_init_freeable+0x188/0x1c8)
[    2.670601] [<80900da8>] (kernel_init_freeable) from [<806583e4>] (kernel_init+0x8/0x10c)
[    2.678753] [<806583e4>] (kernel_init) from [<80106f88>] (ret_from_fork+0x14/0x2c)
[    2.711293] sdhci-pltfm: SDHCI platform and OF driver helper

sys 系统设备信息

     

mmc设备初始化

    mmc设备的扫描

     书接上回,在host初始化完毕开始时,启动了delay work  开始扫描mmc设备,以下的接口

   

mmc_rescan

static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
//400k -100k中的最大值
	for (i = 0; i < ARRAY_SIZE(freqs); i++) {
		if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
			break;
		if (freqs[i] <= host->f_min)
			break;
	}

mmc的初始化

       这里根据设备猜测支持的速率。

mmc_attach_sd

/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err;
	u32 cid[4];
	u32 rocr = 0;

	WARN_ON(!host->claimed);

	
   //以下部分代码是初始化时钟相关参数

	/* Initialization sequence for UHS-I cards */
	if (rocr & SD_ROCR_S18A) {
		err = mmc_sd_init_uhs_card(card);
		if (err)
			goto free_card;
	} else {
		/*
		 * Attempt to change to high-speed (if supported)
		 */
		err = mmc_sd_switch_hs(card);
		if (err > 0)
			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
		else if (err)
			goto free_card;

		/*
		 * Set bus speed.
		 */
		mmc_set_clock(host, mmc_sd_get_max_clock(card));

		/*
		 * Switch to wider bus (if supported).
		 */
		if ((host->caps & MMC_CAP_4_BIT_DATA) &&
			(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
			err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
			if (err)
				goto free_card;

			mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
		}
	}

	host->card = card;
	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);

	return err;
}

   SD_ROCR_S18A

  high-speed mode(第二次速率设定)

    mmc工作模式

mmc_set_timing(card->host, MMC_TIMING_SD_HS);

host->ios.timing = timing;
	mmc_set_ios(host);

bus speed

 根据mmc的信息,确定最大的bus speed

unsigned mmc_sd_get_max_clock(struct mmc_card *card)
{
	unsigned max_dtr = (unsigned int)-1;

	if (mmc_card_hs(card)) {
		if (max_dtr > card->sw_caps.hs_max_dtr)
			max_dtr = card->sw_caps.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	return max_dtr;
}
void mmc_set_clock(struct mmc_host *host, unsigned int hz)
{
	WARN_ON(hz && hz < host->f_min);

	if (hz > host->f_max)
		hz = host->f_max;

	host->ios.clock = hz;
	mmc_set_ios(host);
}

上电打印

       此时,速率已经变为52MHZ,而打印出的栈正如我们分析的一样,在扫描具体的mmc存储设备后,再次更新控制器的速率配置。

[    2.846320] mmc_host mmc0: Bus speed (slot 0) = 99999999Hz (slot req 52000000Hz, actual 49999999HZ div = 1)
[    2.856119] CPU: 3 PID: 32 Comm: kworker/3:1 Not tainted 4.14.55-fmsh20220223 #27
[    2.863586] Hardware name: FMSH PSOC Platform
[    2.867959] Workqueue: events_freezable mmc_rescan
[    2.872808] [<8010e648>] (unwind_backtrace) from [<8010a970>] (show_stack+0x10/0x14)
[    2.880568] [<8010a970>] (show_stack) from [<806483c4>] (dump_stack+0x7c/0x9c)
[    2.887807] [<806483c4>] (dump_stack) from [<8051f840>] (dw_mci_setup_bus+0x18c/0x1c4)
[    2.895732] [<8051f840>] (dw_mci_setup_bus) from [<8051f9a0>] (dw_mci_set_ios+0x128/0x164)
[    2.904006] [<8051f9a0>] (dw_mci_set_ios) from [<8050bf8c>] (mmc_init_card+0x578/0x1774)
[    2.912102] [<8050bf8c>] (mmc_init_card) from [<8050d524>] (mmc_attach_mmc+0xbc/0x11c)
Starting logging: [    2.920002] [<8050d524>] (mmc_attach_mmc) from [<80509c9c>] (mmc_rescan+0x300/0x310)
[    2.929302] [<80509c9c>] (mmc_rescan) from [<8012dc14>] (process_one_work+0x13c/0x240)
[    2.937220] [<8012dc14>] (process_one_work) from [<8012ec8c>] (worker_thread+0x1b0/0x2b4)
[    2.945378] [<8012ec8c>] (worker_thread) from [<80132e7c>] (kthread+0x130/0x148)
OK[    2.952758] [<80132e7c>] (kthread) from [<80106f88>] (ret_from_fork+0x14/0x2c)

[    2.961578] mmc0: new high speed MMC card at address 0001

如果没有设置dts中的参数,那么频率是根据什么来的?

mmc控制器的频率设定

   经过控制器的初始化,mmc的扫描,得知了mmc支持的最大频率,进而调用host的控制接口设置host的频率。如下代码回调了host的接口set_ios.    

static inline void mmc_set_ios(struct mmc_host *host)
{
	struct mmc_ios *ios = &host->ios;

	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
		"width %u timing %u\n",
		 mmc_hostname(host), ios->clock, ios->bus_mode,
		 ios->power_mode, ios->chip_select, ios->vdd,
		 1 << ios->bus_width, ios->timing);

	host->ops->set_ios(host, ios);
}

 如下代码中slot->clock 即为上述mmc初始时得到的clock值。


static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
	struct dw_mci_slot *slot = mmc_priv(mmc);
	const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
	u32 regs;
	int ret;

	switch (ios->bus_width) {
	case MMC_BUS_WIDTH_4:
		slot->ctype = SDMMC_CTYPE_4BIT;
		break;
	case MMC_BUS_WIDTH_8:
		slot->ctype = SDMMC_CTYPE_8BIT;
		break;
	default:
		/* set default 1 bit mode */
		slot->ctype = SDMMC_CTYPE_1BIT;
	}

	regs = mci_readl(slot->host, UHS_REG);

	/* DDR mode set */
	if (ios->timing == MMC_TIMING_MMC_DDR52 ||
	    ios->timing == MMC_TIMING_UHS_DDR50 ||
	    ios->timing == MMC_TIMING_MMC_HS400)
		regs |= ((0x1 << slot->id) << 16);
	else
		regs &= ~((0x1 << slot->id) << 16);

	mci_writel(slot->host, UHS_REG, regs);
	slot->host->timing = ios->timing;

	/*
	 * Use mirror of ios->clock to prevent race with mmc
	 * core ios update when finding the minimum.
	 */
	slot->clock = ios->clock;

	if (drv_data && drv_data->set_ios)
		drv_data->set_ios(slot->host, ios);

	switch (ios->power_mode) {
	case MMC_POWER_UP:
		if (!IS_ERR(mmc->supply.vmmc)) {
			ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
					ios->vdd);
			if (ret) {
				dev_err(slot->host->dev,
					"failed to enable vmmc regulator\n");
				/*return, if failed turn on vmmc*/
				return;
			}
		}
		set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
		regs = mci_readl(slot->host, PWREN);
		regs |= (1 << slot->id);
		mci_writel(slot->host, PWREN, regs);
		break;
	case MMC_POWER_ON:
		if (!slot->host->vqmmc_enabled) {
			if (!IS_ERR(mmc->supply.vqmmc)) {
				ret = regulator_enable(mmc->supply.vqmmc);
				if (ret < 0)
					dev_err(slot->host->dev,
						"failed to enable vqmmc\n");
				else
					slot->host->vqmmc_enabled = true;

			} else {
				/* Keep track so we don't reset again */
				slot->host->vqmmc_enabled = true;
			}

			/* Reset our state machine after powering on */
			dw_mci_ctrl_reset(slot->host,
					  SDMMC_CTRL_ALL_RESET_FLAGS);
		}

		/* Adjust clock / bus width after power is up */
		dw_mci_setup_bus(slot, false);

		break;
	case MMC_POWER_OFF:
		/* Turn clock off before power goes down */
		dw_mci_setup_bus(slot, false);

		if (!IS_ERR(mmc->supply.vmmc))
			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);

		if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled)
			regulator_disable(mmc->supply.vqmmc);
		slot->host->vqmmc_enabled = false;

		regs = mci_readl(slot->host, PWREN);
		regs &= ~(1 << slot->id);
		mci_writel(slot->host, PWREN, regs);
		break;
	default:
		break;
	}

	if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0)
		slot->host->state = STATE_IDLE;
}

设备与控制器速率支持

   设备的速率为上表,而控制器只支持前两种速率,同时,对于EMIO扩展的,频率仅仅支持25M,这就需要在DTS中限制,而不能仅仅依赖于MMC设备支持的速率。

dw_mci_setup_bus

dw ip设置 频率的代码接口

    


static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
{
	struct dw_mci *host = slot->host;
	unsigned int clock = slot->clock;
	u32 div;
	u32 clk_en_a;
	u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT;

	/* We must continue to set bit 28 in CMD until the change is complete */
	if (host->state == STATE_WAITING_CMD11_DONE)
		sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH;

	if (!clock) {
		mci_writel(host, CLKENA, 0);
		mci_send_cmd(slot, sdmmc_cmd_bits, 0);
	} else if (clock != host->current_speed || force_clkinit) {
		div = host->bus_hz / clock;
		if (host->bus_hz % clock && host->bus_hz > clock)
			/*
			 * move the + 1 after the divide to prevent
			 * over-clocking the card.
			 */
			div += 1;

		div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0;

		if ((clock != slot->__clk_old &&
			!test_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags)) ||
			force_clkinit) {
			/* Silent the verbose log if calling from PM context */
			if (!force_clkinit)
				dev_info(&slot->mmc->class_dev,
					 "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n",
					 slot->id, host->bus_hz, clock,
					 div ? ((host->bus_hz / div) >> 1) :
					 host->bus_hz, div);

			/*
			 * If card is polling, display the message only
			 * one time at boot time.
			 */
			if (slot->mmc->caps & MMC_CAP_NEEDS_POLL &&
					slot->mmc->f_min == clock)
				set_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags);
		}

		/* disable clock */
		mci_writel(host, CLKENA, 0);
		mci_writel(host, CLKSRC, 0);

		/* inform CIU */
		mci_send_cmd(slot, sdmmc_cmd_bits, 0);

		/* set clock to desired speed */
		mci_writel(host, CLKDIV, div);

		/* inform CIU */
		mci_send_cmd(slot, sdmmc_cmd_bits, 0);

		/* enable clock; only low power if no SDIO */
		clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
		if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags))
			clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
		mci_writel(host, CLKENA, clk_en_a);

		/* inform CIU */
		mci_send_cmd(slot, sdmmc_cmd_bits, 0);

		/* keep the last clock value that was requested from core */
		slot->__clk_old = clock;
	}

	host->current_speed = clock;

	/* Set the current slot bus width */
	mci_writel(host, CTYPE, (slot->ctype << slot->id));
}

总结

   速率的配置,首先采用默认值。

   而后根据具体的mmc存储设备进行调整。但是本身控制器的实现也会对速率有要求,导致在配置时要多方考虑才能得出一个较好的速率值。

  进一步的走读: 对mmc设备的识别。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/223742.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1.2 C语言简介

一、为什么要讲C语言 C语言是编程界的长青藤&#xff0c;可以查看语言排名发现&#xff0c;虽然现在语言很多&#xff0c;但是C语言一直占有一定地址 来源网站&#xff1a;https://www.tiobe.com/tiobe-index/ 在系统、嵌入式、底层驱动等领域存在一定的唯一性&#xff08;C语…

GNSEC 2022年第8届全球下一代软件工程线上峰会-核心PPT资料下载

一、峰会简介 新一代软件工程是指利用新的理论、方法和技术&#xff0c;在软件开发、部署、运维等过程中&#xff0c;实现软件的可控、可预测、可维护的软件生产方式。它涵盖了多个领域&#xff0c;如软件开发、测试、部署、运维等&#xff0c;旨在提高软件生产效率和质量。 …

Qt-Q_OBJECT宏使用与“无法解析的外部符号qt_metacall/metaObject/qt_metacast“

有时候我们编写Qt类的时候&#xff0c;修改代码时直接加上Q_OBJECT宏&#xff0c;然后直接构建&#xff0c;会报如下错误&#xff1a; 这里的几个函数的声明是由Q_OBJECT宏引入的&#xff0c;而其对应的实现是由moc实现的&#xff0c;如果我们更新了代码但是没有执行qmake&…

【Qt开发流程】之对象模型3:对象树及其所有权

描述 Qt对象树是一种基于父子关系的对象管理机制&#xff0c;用于管理Qt应用程序中的所有对象。在Qt中&#xff0c;每个对象都可以拥有一个或多个子对象&#xff0c;并且每个子对象只能属于一个父对象。每个对象的所有权&#xff08;也称为生存期&#xff09;由其父对象控制。…

Linux常用指令详解

目录 前言&#xff1a; Linux的目录结构 Linux常用指令简介 whoami指令 ls指令 pwd指令 cd指令 tree指令 touch指令 mkdir指令 rmdir指令与rm指令 man指令 cp&#xff08;copy&#xff09;指令 mv&#xff08;move&#xff09;指令 cat指令 重定向及重定向的类型…

SE考研真题总结(一)

本帖开始分享考研真题中设计【软件工程】的部分&#xff0c;预计会出5期左右&#xff0c;敬请期待~ 一.单选题 1.程序编写不是软件质量保障过程~ 静态代码扫描是今年来多数被人提及的软件应用安全解决方案之一&#xff0c;指程序员在编写好代码后无需进行编译&#xff0c;直接…

【网络】抓包工具Wireshark下载安装和基本使用教程

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1…

电商运营基础(一、新手起店完整的运营流程)

任何东西的学习都要现有广度再有深度 一、学习流程大纲 二、新店运营的完整步骤 1.品类选择&#xff08;最重要的一步&#xff09; 切记&#xff0c;电商&#xff0c;选择大于努力 类——类目——做一件代发的——选类目很重要 品——货源——有自己的货源——选品——你做…

行业研究:2023年中国游戏陪玩行业市场现状分析

近年来随着我国游戏行业的不断发展&#xff0c;我国游戏用户规模也是随着稳步上升&#xff0c;给游戏陪玩行业带来了稳定的用户基础。在用户规模增长的同时&#xff0c;随着经济、文化的快速发展&#xff0c;我国娱乐技能社交也随之逐渐兴起。而作为我国娱乐技能社交比重较大的…

HarmonyOS 修改App的默认加载的界面(ArkTS版本)(十七)

根据鸿蒙系统APP的应用生命周期结构&#xff08;鸿蒙4.0开发笔记之ArkTS语法基础之应用生命周期&#xff09;来看。 1、首先在roject/entry/src/main/ets/entryability/EntryAbility.ts文件中找到UI加载函数&#xff1a;onWindowStageCreate(…){…}&#xff0c;然后找到windo…

【i.MX6ULL】linux驱动bh1750模块

I2C-BH1750 1、设备地址 引脚说明 VCC5VGNDGNDSCLPB6SDAPB7ADDRVCC/GND bh1750设备的地址由引脚 ADDR 来决定 ADDR接GND 当ADDR引脚接地时设备bh1750的地址为&#xff1a;0x23(7bit) ADDR接VCC 当ADDR引脚接地时设备bh1750的地址为&#xff1a;0x5c(7bit) 2、工作模式 …

【S32K3环境搭建】-0.3-S32DS安装实时驱动RTD(Real-Time Driver)

目录 1 什么是“实时驱动RTD(Real-Time Driver)” 2 安装“实时驱动RTD(Real-Time Driver)” 2.1 方法一&#xff1a;通过S32DS Extensions and Updates安装“实时驱动RTD(Real-Time Driver)” 2.2 方法二&#xff1a;通过Install New Software…安装“实时驱动RTD(Real-Ti…

基于KSZ9897VLAN 虚拟WAN网络接口

目录 1:先看看高通的8327是如何虚拟网络接口 2: Linux 内核中选上802.1Q 3: 实际效果展示 4&#xff1a;配置使用 1:先看看高通的8327是如何虚拟网络接口 rootOpenWrt:~# cat /etc/config/wirelessconfig wifi-device wifi0option type qcawifioption macaddr 68:89:75:04:…

一篇文章带你详细了解C++智能指针

一篇文章带你详细了解C智能指针 为什么要有智能指针内存泄漏1.什么是内存泄漏&#xff0c;它的危害是什么2.内存泄漏的分类3.如何避免内存泄漏 智能指针的使用及原理1.RAII2.智能指针的原理3.auto_ptr4.unique_ptr5.shared_ptr6.weak_ptr 为什么要有智能指针 C引入智能指针的主…

flink源码分析之功能组件(四)-slot管理组件I

简介 本系列是flink源码分析的第二个系列&#xff0c;上一个《flink源码分析之集群与资源》分析集群与资源&#xff0c;本系列分析功能组件&#xff0c;kubeclient&#xff0c;rpc&#xff0c;心跳&#xff0c;高可用&#xff0c;slotpool&#xff0c;rest&#xff0c;metrics&…

从零开发短视频电商 Jmeter压测示例模板详解(无认证场景)

文章目录 添加线程组添加定时器添加HTTP请求默认值添加HTTP头管理添加HTTP请求添加结果断言响应断言 Response AssertionJSON断言 JSON Assertion持续时间断言 Duration Assertion 添加察看结果树添加聚合报告添加表格察看结果参考 以压测百度搜索为例 https://www.baidu.com/s…

[NAND Flash 2.2] NAND闪存及控制器的市场趋势 [2023]

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 一、NAND闪存市场分析 据欧洲知名半导体分析机构Yole发布的报告显示&#xff0c;2020年起&#xff0c;NAND闪存市场发展趋势保持稳定…

【Angular开发】Angular中的高级组件

在这个博客中&#xff0c;我将解释Angular中的几个高级组件和机制&#xff0c;它们增强了灵活性、可重用性和性能。 通过熟悉这些高级组件和机制&#xff0c;您可以提高您的Angular开发技能&#xff0c;并在应用程序中利用灵活性、可重用性和性能优化的能力。让我们开始吧&…

使用dockerfile 构建自己的nacos-mysql

前言 在部署nacos的时候触发的脑袋灵光一闪&#xff0c;每次部署nacos都要部署下mysql服务器&#xff0c;然后导入sql语句&#xff0c;配置nacos配置文件&#xff0c;那有没有简单的方法实现一键部署nacos和nacos-mysql 呢? 答案是肯定&#xff01;如下目录图&#xff1a; …

ctfhub技能树_web_信息泄露

目录 二、信息泄露 2.1、目录遍历 2.2、Phpinfo 2.3、备份文件下载 2.3.1、网站源码 2.3.2、bak文件 2.3.3、vim缓存 2.3.4、.DS_Store 2.4、Git泄露 2.4.1、log 2.4.2、stash 2.4.3、index 2.5、SVN泄露 2.6、HG泄露 二、信息泄露 2.1、目录遍历 注&#xff1…
最新文章