ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks使用分析
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 基本上是主控制器公开的一组寄存器。
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_DEBUGdump_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_DEBUGdump_upiu(&utrd);
#endifresp = (resp_upiu_t *)utrd.resp_upiu;return size - resp->res_trans_cnt;
}
4.3 ufs_send_cmd
get_utrd(utrd);
ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length);
ufs_send_request(utrd->task_tag);
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_10
和CDBCMD_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;
}
相关文章:

ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks使用分析
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_blocks2.2 ATF BL1/BL2 ufs_write_blocks 3 UFS System Model4 ufs_read_blocks/ufs_write_blocks详细分析4.1 ufs_re…...

Elasticsearch(十二)搜索---搜索匹配功能③--布尔查询及filter查询原理
一、前言 本节主要学习ES匹配查询中的布尔查询以及布尔查询中比较特殊的filter查询及其原理。 复合搜索,顾名思义是一种在一个搜索语句中包含一种或多种搜索子句的搜索。 布尔查询是常用的复合查询,它把多个子查询组合成一个布尔表达式,这些…...

解决Windows下的docker desktop无法启动问题
以管理员权限运行cmd 报错: docker: error during connect: Post http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/containers/create: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows,…...

LLM生成式 AI 项目生命周期Generative AI project lifecycle
在本课程的其余部分中,您将学习开发和部署LLM驱动应用所需的技巧。在这个视频中,您将了解一个能帮助您完成此工作的生成式AI项目生命周期。此框架列出了从构思到启动项目所需的任务。到课程结束时,您应该对您需要做的重要决策、可能遇到的困难…...
java高并发系列 - 第13天:JUC中的Condition对象
java高并发系列 - 第13天:JUC中的Condition对象 java高并发系列第13篇文章 本文内容 synchronized中实现线程等待和唤醒Condition简介及常用方法介绍及相关示例使用Condition实现生产者消费者使用Condition实现同步阻塞队列Object对象中的wait(),notify()方法,用于线程等待…...
【TTY子系统】printf与printk深入驱动解析
tty子系统解析 tty子系统是一个庞大且复杂,也是内核维护者所头大的子系统。 At a first glance, the TTY layer wouldn’t seem like it should be all that challenging. It is, after all, just a simple char device which is charged with transferring byte-o…...

无涯教程-PHP - 全局变量函数
全局变量 与局部变量相反,可以在程序的任何部分访问全局变量。通过将关键字 GLOBAL 放置在应被识别为全局变量的前面,可以很方便地实现这一目标。 <?php$somevar15;function addit() {GLOBAL $somevar;$somevar;print "Somevar is $somevar";}addit(); ?> …...

shell脚本之循环语句
循环语句 循环含义 将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件 for循环语句 一般知道循环次数使用for循环 第一类 格式1: for名称 in 取值次数;do;done; 格式2: for 名称 in {取值列表} do done# 打印20次 for i i…...

派森 #P122. 峰值查找
描述 给定一个长度为n的列表nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。 (1)峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于; &…...
基础网络详解4--HTTP CookieSession 思考
一、cookie技术思考 一台多用户浏览器发起了三笔请求,将某款产品放入购物车中,A一次,选择了篮球;B两次,第一次选了足球,第二次选了钢笔。如何确认选择篮球、足球、钢笔的请求属于谁呢?如果不确认…...

14. 利用Canvas自制时钟组件
1. 说明 在自定义时钟组件时,使用到的基本控件主要是Canvas,在绘制相关元素时有两种方式:一种时在同一个canvas中绘制所有的部件元素,这样需要不断的对画笔和画布的属性进行保存和恢复,容易混乱;另一种就是…...

微信小程序使用云存储和Markdown开发页面
最近想在一个小程序里加入一个使用指南的页面,考虑到数据存储和减少页面的开发工作量,决定尝试在云存储里上传Markdown文件,微信小程序端负责解析和渲染。小程序端使用到一个库Towxml。 Towxml Towxml是一个可将HTML、Markdown转为微信小程…...

【C++】运算符重载 | 赋值运算符重载
Ⅰ. 运算符重载 引入 ❓什么叫运算符重载? 就是:运用函数,将现有的运算符重新定义,使其能满足各种自定义类型的运算。 回想一下,我们以前运算的对象是不是都是int、char这种内置类型? 那我们自定义的“…...
Python学习 -- 类对象从创建到常用函数
在Python编程中,类是一种强大的工具,用于创建具有共同属性和行为的对象。本篇博客将详细介绍Python中类和对象的创建,类的属性和方法,以及一些常用的类函数,通过丰富的代码例子来帮助读者深入理解。 一、类和对象的创…...

数组分割(2023省蓝桥杯)n种讨论 JAVA
目录 1、题目描述:2、前言:3、动态规划(bug):3、递归 剪枝(超时):4、数学(正解): 1、题目描述: 小蓝有一个长度为 N 的数组 A [A0, A1,…, AN−…...

很好的启用window10专业版系统自带的远程桌面
启用window10专业版系统自带的远程桌面 文章目录 启用window10专业版系统自带的远程桌面前言1.找到远程桌面的开关2. 找到“应用”项目3. 打开需要远程操作的电脑远程桌面功能 总结 前言 Windows操作系统作为应用最广泛的个人电脑操作系统,在我们身边几乎随处可见。…...

TCP定制协议,序列化和反序列化
目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现: 2.4编译测试 总结 前言 在之前的文章中,我们说TCP是面向字节流的,但是可能对于面向字节流这个概念,其实并不理解的,今天我们要介…...

YOLOX在启智AI GPU/CPU平台部署笔记
文章目录 1. 概述2. 部署2.1 拉取YOLOX源码2.2 拉取模型文件yolox_s.pth2.3 安装依赖包2.4 安装yolox2.5 测试运行2.6 运行报错处理2.6.1 ImportError: libGL.so.1: cannot open shared object file: No such file or directory2.6.2 ImportError: libgthread-2.0.so.0: cannot…...

23种设计模式攻关
👍一、创建者模式 🔖1.1、单例模式 单例模式(Singleton Pattern),用于确保一个类只有一个实例,并提供全局访问点。 在某些情况下,我们需要确保一个类只能有一个实例,比如数据库连接…...

【jsthreeJS】入门three,并实现3D汽车展示厅,附带全码
首先放个最终效果图: 三维(3D)概念: 三维(3D)是一个描述物体在三个空间坐标轴上的位置和形态的概念。相比于二维(2D)只有长度和宽度的平面,三维增加了高度或深度这一维度…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果。…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
大数据驱动企业决策智能化的路径与实践
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:数据驱动的企业竞争力重构 在这个瞬息万变的商业时代,“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...

VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...