ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks使用分析

news2024/9/22 9:49:54

ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks使用分析

  • 1 ATF的下载链接
  • 2 ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks处理流程
    • 2.1 ATF BL1/BL2 ufs_read_blocks
    • 2.2 ATF BL1/BL2 ufs_write_blocks
  • 3 UFS System Model
  • 4 ufs_read_blocks/ufs_write_blocks详细分析
    • 4.1 ufs_read_blocks
    • 4.2 ufs_write_blocks
    • 4.3 ufs_send_cmd
    • 4.4 get_utrd
    • 4.5 ufs_prepare_cmd
      • 4.5.1 COMMAND UPIU
      • 4.5.2 READ (10) Command
      • 4.5.3RESPONSE UPIU
      • 4.5.4 WRITE (10) Command
      • 4.5.5 ufs_prepare_cmd
    • 4.6 ufs_send_request
    • 4.7 ufs_check_resp

ATF BL1 UFS初始化简单分析
ATF bl1 ufshc_dme_get/set处理流程分析

1 ATF的下载链接

https://github.com/ARM-software/arm-trusted-firmware

可以通过下面的命令来下载ATF的代码,或者通过打包下载的方式也可以。

git clone git@github.com:ARM-software/arm-trusted-firmware.git

2 ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks处理流程

ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks的处理流程是类似的,只ufs_send_cmd下传的命令是有区别的,在ufs_prepare_cmd的时候需要依据ufs_send_cmd传递的命令参数去组织cmd UPIU。

2.1 ATF BL1/BL2 ufs_read_blocks

在这里插入图片描述

2.2 ATF BL1/BL2 ufs_write_blocks

在这里插入图片描述

3 UFS System Model

It shows how a UFS host is connected to a UFS device, the position of UFS host controller and its related UFS HCI interface.
它显示了 UFS 主机与 UFS 设备的连接方式、UFS 主机控制器的位置及其相关的 UFS HCI 接口。
The UFS host consists of the application which wishes to communicate with the UFS device. It communicates with the device using the UFS driver. The UFS driver is meant for managing the UFS host controller through the UFS HCI (UFS Host Controller Interface). The UFS HCI is basically a set of registers exposed by the host controller.
UFS 主机由希望与 UFS 设备通信的应用程序组成。它使用 UFS 驱动程序与设备通信。UFS 驱动程序用于通过 UFS 主控制器接口(UFS HCI)管理 UFS 主控制器。UFS HCI 基本上是主控制器公开的一组寄存器。
## 3.2

4 ufs_read_blocks/ufs_write_blocks详细分析

4.1 ufs_read_blocks

  • ufs_send_cmd(&utrd, CDBCMD_READ_10, lun, lba, buf, size);
size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size)
{
	utp_utrd_t utrd;
	resp_upiu_t *resp;

	assert((ufs_params.reg_base != 0) &&
	       (ufs_params.desc_base != 0) &&
	       (ufs_params.desc_size >= UFS_DESC_SIZE));

	ufs_send_cmd(&utrd, CDBCMD_READ_10, lun, lba, buf, size);
#ifdef UFS_RESP_DEBUG
	dump_upiu(&utrd);
#endif
	/*
	 * Invalidate prefetched cache contents before cpu
	 * accesses the buf.
	 */
	inv_dcache_range(buf, size);
	resp = (resp_upiu_t *)utrd.resp_upiu;
	return size - resp->res_trans_cnt;
}

4.2 ufs_write_blocks

  • ufs_send_cmd(&utrd, CDBCMD_WRITE_10, lun, lba, buf, size);
size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size)
{
	utp_utrd_t utrd;
	resp_upiu_t *resp;

	assert((ufs_params.reg_base != 0) &&
	       (ufs_params.desc_base != 0) &&
	       (ufs_params.desc_size >= UFS_DESC_SIZE));

	ufs_send_cmd(&utrd, CDBCMD_WRITE_10, lun, lba, buf, size);
#ifdef UFS_RESP_DEBUG
	dump_upiu(&utrd);
#endif
	resp = (resp_upiu_t *)utrd.resp_upiu;
	return size - resp->res_trans_cnt;
}

4.3 ufs_send_cmd

  1. get_utrd(utrd);
  2. ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length);
  3. ufs_send_request(utrd->task_tag);
  4. ufs_check_resp(utrd, RESPONSE_UPIU, CMD_TIMEOUT_MS);
static void ufs_send_cmd(utp_utrd_t *utrd, uint8_t cmd_op, uint8_t lun, int lba, uintptr_t buf,
			 size_t length)
{
	int result, i;

	for (i = 0; i < UFS_CMD_RETRIES; ++i) {
		get_utrd(utrd);
		result = ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length);
		assert(result == 0);
		ufs_send_request(utrd->task_tag);
		result = ufs_check_resp(utrd, RESPONSE_UPIU, CMD_TIMEOUT_MS);
		if (result == 0 || result == -EIO) {
			break;
		}
	}
	assert(result == 0);
	(void)result;
}

4.4 get_utrd

  • get_utrd函数用于获取一个公共的utrd结构
  • hd->ucdba = utrd->upiu & UINT32_MAX; hd->ucdbau = (utrd->upiu >> 32) & UINT32_MAX;用于UTP传输请求列表基地址的配置。
    在这里插入图片描述
/* UTP Transfer Request Descriptor */
typedef struct utrd_header {
        uint32_t        reserved0 : 24;
        uint32_t        i : 1;          /* interrupt */
        uint32_t        dd : 2;         /* data direction */
        uint32_t        reserved1 : 1;
        uint32_t        ct : 4;         /* command type */                                                                                                                                                         
        uint32_t        reserved2;
        uint32_t        ocs : 8;        /* Overall Command Status */
        uint32_t        reserved3 : 24;
        uint32_t        reserved4;
        uint32_t        ucdba;          /* aligned to 128-byte */
        uint32_t        ucdbau;         /* Upper 32-bits */
        uint32_t        rul : 16;       /* Response UPIU Length */
        uint32_t        ruo : 16;       /* Response UPIU Offset */
        uint32_t        prdtl : 16;     /* PRDT Length */
        uint32_t        prdto : 16;     /* PRDT Offset */
} utrd_header_t;        /* 8 words with little endian */

typedef struct utp_utrd {
        uintptr_t       header;         /* utrd_header_t */
        uintptr_t       upiu;
        uintptr_t       resp_upiu;                                                                                                                                                                                 
        uintptr_t       prdt;
        size_t          size_upiu;
        size_t          size_resp_upiu;
        size_t          prdt_length;
        int             task_tag;
} utp_utrd_t;

static void get_utrd(utp_utrd_t *utrd)
{
	uintptr_t base;
	int result;
	utrd_header_t *hd;

	assert(utrd != NULL);
	result = is_slot_available();
	assert(result == 0);

	/* clear utrd */
	memset((void *)utrd, 0, sizeof(utp_utrd_t));
	base = ufs_params.desc_base;
	/* clear the descriptor */
	memset((void *)base, 0, UFS_DESC_SIZE);

	utrd->header = base;
	utrd->task_tag = 1; /* We always use the first slot */
	/* CDB address should be aligned with 128 bytes */
	utrd->upiu = ALIGN_CDB(utrd->header + sizeof(utrd_header_t));
	utrd->resp_upiu = ALIGN_8(utrd->upiu + sizeof(cmd_upiu_t));
	utrd->size_upiu = utrd->resp_upiu - utrd->upiu;
	utrd->size_resp_upiu = ALIGN_8(sizeof(resp_upiu_t));
	utrd->prdt = utrd->resp_upiu + utrd->size_resp_upiu;

	hd = (utrd_header_t *)utrd->header;
	hd->ucdba = utrd->upiu & UINT32_MAX;
	hd->ucdbau = (utrd->upiu >> 32) & UINT32_MAX;
	/* Both RUL and RUO is based on DWORD */
	hd->rul = utrd->size_resp_upiu >> 2;
	hd->ruo = utrd->size_upiu >> 2;
	(void)result;
}

4.5 ufs_prepare_cmd

4.5.1 COMMAND UPIU

The COMMAND UPIU contains the basic UPIU header plus additional information needed to specify a command. The Initiator device will generate this UPIU and send it to a Target device to request a SCSI command service to be performed by the Target.
COMMAND UPIU 包含基本 UPIU 标头以及指定命令所需的附加信息。启动程序设备将生成此 UPIU 并将其发送至目标设备,以请求目标设备执行 SCSI 命令服务。
在这里插入图片描述

4.5.2 READ (10) Command

The READ (10) command requests that the Device Server read from the medium the specified number of logical block(s) and transfer them to the Application Client.
READ (10) 命令要求设备服务器从介质读取指定数量的逻辑块,并将其传输到应用程序客户端。
The Command CDB shall be sent in a single COMMAND UPIU.
命令 CDB 应在单个 COMMAND UPIU 中发送。
The RDPROTECT field is set to zero for UFS.
对于 UFS,RDPROTECT 字段设置为零。
在这里插入图片描述

4.5.3RESPONSE UPIU

The RESPONSE UPIU contains the basic UPIU header plus additional information indicating the command and device level status resulting from the successful or failed execution of a command. The Target will generate this UPIU and send it to the Initiator device after it has completed the requested task.
RESPONSE UPIU 包含基本的 UPIU 标头和附加信息,表明命令和设备级状态,这些状态来自命令的成功或失败执行。目标设备将生成此 UPIU,并在完成请求任务后将其发送给启动设备。
Before terminating a command which requires Data-Out data transfer and before sending the RESPONSE UPIU, the Target device shall wait until it receives all DATA OUT UPIUs related to any outstanding READY TO TRANSFER UPIUs. Also, the Target device should stop sending READY TO TRANSFER UPIUs for the command which requires Data-Out data transfer and to be terminated.
在终止需要数据输出数据传输的命令和发送 RESPONSE UPIU 之前,目标设备应等待收到与任何未完成的 "准备传输 "UPIU 相关的所有 "数据输出 "UPIU。此外,目标设备应停止为需要数据输出数据传输和终止的命令发送 READY TO TRANSFER UPIU。
在这里插入图片描述

4.5.4 WRITE (10) Command

The WRITE (10) UFS command requests that the Device Server transfer the specified number of logical blocks(s) from the Application Client and write them to the medium.
WRITE (10) UFS 命令要求设备服务器从应用程序客户端传输指定数量的逻辑块并将其写入介质。
The Command CDB shall be sent in a single COMMAND UPIU.
命令 CDB 应在单个命令 UPIU 中发送。
The RDPROTECT field is set to zero for UFS.
对于 UFS,RDPROTECT 字段设置为零。
在这里插入图片描述

4.5.5 ufs_prepare_cmd

  • 按照ufs_send_cmd的cmd_op去组command upiu。
  • 对于ufs的读写操作,其cmd_op分别为CDBCMD_READ_10CDBCMD_WRITE_10
  • upiu->cdb[0] = op;
  • CDBCMD_READ_10对于读来说,其upiu以及command的组织形式
	case CDBCMD_READ_10:
		hd->dd = DD_OUT;
		upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S;
		upiu->lun = lun;
		upiu->cdb[1] = RW_WITHOUT_CACHE;
		/* set logical block address */
		upiu->cdb[2] = (ulba >> 24) & 0xff;
		upiu->cdb[3] = (ulba >> 16) & 0xff;
		upiu->cdb[4] = (ulba >> 8) & 0xff;
		upiu->cdb[5] = ulba & 0xff;
		/* set transfer length */
		upiu->cdb[7] = (lba_cnt >> 8) & 0xff;
		upiu->cdb[8] = lba_cnt & 0xff;
		break;
  • CDBCMD_WRITE_10对于写来说,其upiu以及command的组织形式
	case CDBCMD_WRITE_10:
		hd->dd = DD_IN;
		upiu->flags = UPIU_FLAGS_W | UPIU_FLAGS_ATTR_S;
		upiu->lun = lun;
		upiu->cdb[1] = RW_WITHOUT_CACHE;
		/* set logical block address */
		upiu->cdb[2] = (ulba >> 24) & 0xff;
		upiu->cdb[3] = (ulba >> 16) & 0xff;
		upiu->cdb[4] = (ulba >> 8) & 0xff;
		upiu->cdb[5] = ulba & 0xff;
		/* set transfer length */
		upiu->cdb[7] = (lba_cnt >> 8) & 0xff;
		upiu->cdb[8] = lba_cnt & 0xff;
		break;

函数实现

/*
 - Prepare UTRD, Command UPIU, Response UPIU.
 */
static int ufs_prepare_cmd(utp_utrd_t *utrd, uint8_t op, uint8_t lun,
			   int lba, uintptr_t buf, size_t length)
{
	utrd_header_t *hd;
	cmd_upiu_t *upiu;
	prdt_t *prdt;
	unsigned int ulba;
	unsigned int lba_cnt;
	uintptr_t desc_limit;
	uintptr_t prdt_end;

	hd = (utrd_header_t *)utrd->header;
	upiu = (cmd_upiu_t *)utrd->upiu;

	hd->i = 1;
	hd->ct = CT_UFS_STORAGE;
	hd->ocs = OCS_MASK;

	upiu->trans_type = CMD_UPIU;
	upiu->task_tag = utrd->task_tag;
	upiu->cdb[0] = op;
	ulba = (unsigned int)lba;
	lba_cnt = (unsigned int)(length >> UFS_BLOCK_SHIFT);
	switch (op) {
	case CDBCMD_TEST_UNIT_READY:
		break;
	case CDBCMD_READ_CAPACITY_10:
		hd->dd = DD_OUT;
		upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S;
		upiu->lun = lun;
		break;
	case CDBCMD_READ_10:
		hd->dd = DD_OUT;
		upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S;
		upiu->lun = lun;
		upiu->cdb[1] = RW_WITHOUT_CACHE;
		/* set logical block address */
		upiu->cdb[2] = (ulba >> 24) & 0xff;
		upiu->cdb[3] = (ulba >> 16) & 0xff;
		upiu->cdb[4] = (ulba >> 8) & 0xff;
		upiu->cdb[5] = ulba & 0xff;
		/* set transfer length */
		upiu->cdb[7] = (lba_cnt >> 8) & 0xff;
		upiu->cdb[8] = lba_cnt & 0xff;
		break;
	case CDBCMD_WRITE_10:
		hd->dd = DD_IN;
		upiu->flags = UPIU_FLAGS_W | UPIU_FLAGS_ATTR_S;
		upiu->lun = lun;
		upiu->cdb[1] = RW_WITHOUT_CACHE;
		/* set logical block address */
		upiu->cdb[2] = (ulba >> 24) & 0xff;
		upiu->cdb[3] = (ulba >> 16) & 0xff;
		upiu->cdb[4] = (ulba >> 8) & 0xff;
		upiu->cdb[5] = ulba & 0xff;
		/* set transfer length */
		upiu->cdb[7] = (lba_cnt >> 8) & 0xff;
		upiu->cdb[8] = lba_cnt & 0xff;
		break;
	default:
		assert(0);
		break;
	}
	if (hd->dd == DD_IN) {
		flush_dcache_range(buf, length);
	} else if (hd->dd == DD_OUT) {
		inv_dcache_range(buf, length);
	}

	utrd->prdt_length = 0;
	if (length) {
		upiu->exp_data_trans_len = htobe32(length);
		assert(lba_cnt <= UINT16_MAX);
		prdt = (prdt_t *)utrd->prdt;

		desc_limit = ufs_params.desc_base + ufs_params.desc_size;
		while (length > 0) {
			if ((uintptr_t)prdt + sizeof(prdt_t) > desc_limit) {
				ERROR("UFS: Exceeded descriptor limit. Image is too large\n");
				panic();
			}
			prdt->dba = (unsigned int)(buf & UINT32_MAX);
			prdt->dbau = (unsigned int)((buf >> 32) & UINT32_MAX);
			/* prdt->dbc counts from 0 */
			if (length > MAX_PRDT_SIZE) {
				prdt->dbc = MAX_PRDT_SIZE - 1;
				length = length - MAX_PRDT_SIZE;
			} else {
				prdt->dbc = length - 1;
				length = 0;
			}
			buf += MAX_PRDT_SIZE;
			prdt++;
			utrd->prdt_length++;
		}
		hd->prdtl = utrd->prdt_length;
		hd->prdto = (utrd->size_upiu + utrd->size_resp_upiu) >> 2;
	}

	prdt_end = utrd->prdt + utrd->prdt_length * sizeof(prdt_t);
	flush_dcache_range(utrd->header, prdt_end - utrd->header);
	return 0;
}

4.6 ufs_send_request

  • mmio_setbits_32(ufs_params.reg_base + UTRLDBR, 1 << slot); UFS HCI 向设备端发送一个doorbell,告诉设备端对应的slot去处理由host 发送给设备端的命令。
    UTP Task Management Request List DoorBell Register(UTMRLDBR): This field is bit significant. Each bit corresponds to a slot in the task management request List, where bit 0 corresponds to slot 0. A bit in this field is set by host software to indicate to the host controller that a task management request has been built in system memory for the associated task management request slot, and may be ready for execution. The host software indicates no change to request slots by setting the associated bits in this field to ‘0’. Bits in this field shall only be set to ‘1’ by host software when UTMRLRSR is set to ‘1’.
    UTP任务管理请求列表门铃寄存器(UTMRLDBR):该字段是位有效的。每个位对应任务管理请求列表中的一个槽,其中位 0 对应槽 0。该字段中的位由主机软件设置,以向主机控制器指示系统内存中已为该任务建立了一个任务管理请求。关联的任务管理请求槽,并且可以准备好执行。主机软件通过将该字段中的相关位设置为“0”来指示请求时隙没有变化。当 UTMRLRSR 设置为“1”时,该字段中的位只能由主机软件设置为“1”。
    When a task management request is completed (with success or error), the corresponding bit is cleared to ‘0’ by the host controller.
    当任务管理请求完成(成功或错误)时,相应位被主机控制器清除为“0”。
    The host controller always process task management request in-order according to the order submitted to the list. In case of multiple requests with single doorbell register ringing (batch mode), The dispatch order for these requests by host controller will base on their index in the List. A task management with lower index value will be executed before a task management request with higher index value.
    主机控制器总是按照提交到列表的顺序按顺序处理任务管理请求。如果单个门铃寄存器响铃有多个请求(批处理模式),主机控制器对这些请求的调度顺序将基于它们在列表中的索引。具有较低索引值的任务管理将在具有较高索引值的任务管理请求之前执行。
    This field is also cleared when UTMRLRSR is written from a ‘1’ to a ‘0’ by host software.
    当主机软件将 UTMRLRSR 从“1”写入“0”时,该字段也会被清除。
    在这里插入图片描述
static void ufs_send_request(int task_tag)
{
	unsigned int data;
	int slot;

	slot = task_tag - 1;
	/* clear all interrupts */
	mmio_write_32(ufs_params.reg_base + IS, ~0);

	mmio_write_32(ufs_params.reg_base + UTRLRSR, 1);
	assert(mmio_read_32(ufs_params.reg_base + UTRLRSR) == 1);

	data = UTRIACR_IAEN | UTRIACR_CTR | UTRIACR_IACTH(0x1F) |
	       UTRIACR_IATOVAL(0xFF);
	mmio_write_32(ufs_params.reg_base + UTRIACR, data);
	/* send request */
	mmio_setbits_32(ufs_params.reg_base + UTRLDBR, 1 << slot);
}

4.7 ufs_check_resp

  • data = mmio_read_32(ufs_params.reg_base + UTRLDBR);在ufs_check_resp函数中检查UTRLDBR状态,检查对应slot位的状态值。
static int ufs_check_resp(utp_utrd_t *utrd, int trans_type, unsigned int timeout_ms)
{
	utrd_header_t *hd;
	resp_upiu_t *resp;
	sense_data_t *sense;
	unsigned int data;
	int slot, result;

	hd = (utrd_header_t *)utrd->header;
	resp = (resp_upiu_t *)utrd->resp_upiu;

	result = ufs_wait_for_int_status(UFS_INT_UTRCS, timeout_ms, false);
	if (result != 0) {
		return result;
	}

	slot = utrd->task_tag - 1;

	data = mmio_read_32(ufs_params.reg_base + UTRLDBR);
	assert((data & (1 << slot)) == 0);
	/*
	 * Invalidate the header after DMA read operation has
	 * completed to avoid cpu referring to the prefetched
	 * data brought in before DMA completion.
	 */
	inv_dcache_range((uintptr_t)hd, UFS_DESC_SIZE);
	assert(hd->ocs == OCS_SUCCESS);
	assert((resp->trans_type & TRANS_TYPE_CODE_MASK) == trans_type);

	sense = &resp->sd.sense;
	if (sense->resp_code == SENSE_DATA_VALID &&
	    sense->sense_key == SENSE_KEY_UNIT_ATTENTION && sense->asc == 0x29 &&
	    sense->ascq == 0) {
		WARN("Unit Attention Condition\n");
		return -EAGAIN;
	}

	(void)resp;
	(void)slot;
	(void)data;
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

layui框架学习(37:学习laytpl基本语法)

layui中的模板引擎模块laytpl属于轻量的 JavaScript 模板引擎&#xff0c;支持在页面中将指定的数据按指定的模板进行展示或处理&#xff0c;此处的模板是指一段包含html和脚本的文本&#xff08;感觉类似asp.net core中的razor标记语言&#xff0c;在网页中嵌入基于服务器的代…

深入理解CyclicBarrier

CyclicBarrier翻译过来是回环栅栏&#xff0c;它可以实现让一组线程等待至某个状态之后再全部同步执行&#xff0c;这个状态叫屏障点。当所有等待线程都被释放后&#xff0c;CyclicBarrier可以重置再次使用。 CyclicBarrier的功能是由ReentrantLock和Condition共同实现的&…

java: 无法访问org.springframework.boot.SpringApplication 错误的类文件

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; java: 无法访问org.springframework.boot.SpringApplication 错误的类文件: /D:/Software/env-java/apache-maven-3.6.1/repository/org/springframework/boot/spring-boot/3.1.2/spring-boot-3.1.2.ja…

Docker基础操作入门

1 初识 Docker 1.1 简介 我们写的代码会接触到好几个环境&#xff1a;开发环境、测试环境以及生产环境 Docker概念 Docker 是一个开源的应用容器引擎&#xff0c;诞生于 2013 年初&#xff0c;基于 Go 语言实现&#xff0c; dotCloud 公司出品&#xff08;后改名为Docker In…

钝感力:项目经理的隐形盾牌

钝感力的定义 钝感力的起源和意义 钝感力&#xff0c;或者说对外部刺激的不敏感性&#xff0c;起源于我们的生存本能。在古代&#xff0c;人们面对各种危险和挑战&#xff0c;需要有一定的抗压能力&#xff0c;才能在恶劣环境中生存下来。这种能力使得我们的祖先能够在面对猛兽…

R package org.Hs.eg.db to convert gene id

文章目录 install使用org.Hs.egENSEMBL将Ensembl id convert to gene idorg.Hs.egGENENAME 将Ensembl id convert to gene nameorg.Hs.egSYMBOL 将 gene symbol convert to gene id我现在有一些ensembl id 如何转为 gene name注意你会遇到一些record不全的情况&#xff0c;gtf文…

Certify The Web (IIS)

一、简介 Certify The Web 适用于 Windows的SSL 证书管理器用户界面&#xff0c;与所有 ACME v2 CA 兼容&#xff0c;为您的 IIS/Windows 服务器轻松地安装和自动更新来自 Letencrypt.org 和其他 ACME 证书授权机构的免费 SSL/TLS 证书&#xff0c;设置 https 从未如此简单。 …

T599聚合物电容器:在汽车应用中提供更长的使用寿命的解决方案

自从电子技术被引入汽车工业以来&#xff0c;汽车的技术含量一直在提升。诸多技术被应用在汽车上&#xff0c;使汽车的形象更接近于轮子上的超级计算机。更多传感器、更强大的计算能力和电力被装载到汽车上&#xff0c;汽车应用中的电子产品数量正在迅速增长。随着电动汽车和自…

jeecg如何创建报表并配置到菜单中

当使用jeecg创建单表之后,需要进行报表显示,并把报表配置到菜单中,该如何操作呢?下面进行详细讲解。这里以课程表这张表为例进行讲解。 一.表单创建完成,并配置好菜单栏。具体步骤略,如下图: 二.创建积木报表 1.左侧边栏展开低代码开发菜单,进入报表设计器栏目 2.进…

数据库中字段不给值或给““,默认存什么

准备 在mysql数据库中有一张stu表,下面是表的结构和数据和Student类 开始测试一(不给值) 情况一:添加一条数据,但是跳过math列 可以看到,表的int类型的默认为null. 查id2的这条数据,用student类去接 结果math是0,因为实体类的int元素不会是null,会默认给个0 用hashMap<st…

Vue教程(五):样式绑定——class和style

1、样式代码准备 样式提前准备 <style>.basic{width: 400px;height: 100px;border: 1px solid black;}.happy{border: 4px solid red;background-color: rgba(255, 255, 0, 0.644);background: linear-gradient(30deg, yellow, pink, orange, yellow);}.sad{border: 4px …

【Java 高阶】一文精通 Spring MVC - 基础概念(一)

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

微信小程序使用npm引入三方包详解

目录 1 前言2 微信小程序npm环境搭建2.1 创建package.json文件2.2 修改 project.config.json2.3 修改project.private.config.json配置2.4 构建 npm 包2.5 typescript 支持2.6 安装组件2.7 引入使用组件 1 前言 从小程序基础库版本 2.2.1 或以上、及开发者工具 1.02.1808300 或…

课程项目设计--spring security--用户管理功能--宿舍管理系统--springboot后端

写在前面&#xff1a; 还要实习&#xff0c;每次时间好少呀&#xff0c;进度会比较慢一点 本文主要实现是用户管理相关功能。 前文项目建立 文章目录 验证码功能验证码配置验证码生成工具类添加依赖功能测试编写controller接口启动项目 security配置拦截器配置验证码拦截器 …

一、pikachu之SQL注入

文章目录 一、SQL注入步骤二、数字型注入(post注入)三、字符型注入(get)四、搜索型注入五、XX型注入六、“insert/updata”注入 一、SQL注入步骤 寻找传参页面&#xff1b;判断是否存在注入点&#xff1b; 字符型注入&#xff1f;数字型注入&#xff1f; 判断字段的数量&#…

二、4.makefile、断言和位图内存池

在 Linux 中&#xff0c;文件分为属性和数据两部分&#xff0c;每个文件有三种时间&#xff0c;分别用于记录与文件属性和文件数据相关的时间&#xff0c;这三个时间分别是 atime、 mtime 、 ctime 。 atime&#xff0c;即 access time&#xff0c;和示访问文件数据部分时间&a…

SprintBoot Bean管理

SpringBoot中获取Bean对象 下面这段代码在测试类中进行&#xff0c;下面通过三种方式获取bean对象。 import org.springframework.context.ApplicationContext;// 注意一定要引入上面的依赖SpringBootTest class TliasWebManagementApplicationTests {Testvoid getBeanTest(){…

AI夏令营第三期 - 基于论文摘要的文本分类与关键词抽取挑战赛笔记

赛题&#xff1a;基于论文摘要的文本分类与关键词抽取 背景&#xff1a;高效的从海量医学文献中提取疾病诊断和治疗关键信息 任务&#xff1a;通过论文摘要判断论文是否为医学文献 样例 数据集&#xff1a;csv文件&#xff0c;字段&#xff1a;标题、作者、摘要、关键词 评价指…

uniapp 引入海康H5player实现视频监控的播放

uniapp直接调用海康H5player方法&#xff0c;只能在web浏览器页面正常播放&#xff0c;实机运行会因为找不到文件的相对路径而报错无法播放。因此需要通过web-view或iframe引入html的方式来实现实时视频监控的播放。具体步骤如下&#xff1a; 1、首先将海康h5player的相关文件…

服装定制小程序的秘诀

随着互联网的快速发展&#xff0c;越来越多的企业开始关注互联网商业模式的创新。其中&#xff0c;定制化服务成为了各行各业的关注焦点之一。尤其是在服装行业&#xff0c;定制化服装已经成为许多消费者的追求。而面对这一市场需求&#xff0c;如何创造成功的互联网新商业模式…