OpenHarmony-3.HDF框架(2)
- OpenHarmony HDF 平台驱动
1.平台驱动概述
系统平台驱动框架是系统驱动框架的重要组成部分,它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制,为各类平台设备驱动的实现提供标准模型。
系统平台驱动(PlatformDriver),即平台设备驱动,它用于驱动平台设备(PlatformDevice),为系统及外设驱动提供访接口。这里的平台设备,泛指I2C/UART等总线、以及GPIO/RTC等SOC片内硬件资源。
系统平台驱动框架为外设提供了标准的平台设备访问接口,使其不必关注具体硬件及OS平台;同时为平台设备驱动提供统一的适配接口,使其只关注自身硬件的控制。
为实现这个目标,OpenHarmony系统平台驱动框架满足如下特性:
- 统一的平台设备访问接口:对平台设备操作接口进行统一封装,屏蔽不同SOC平台硬件差异以及不同OS形态差异。
- 统一的平台驱动适配接口:为平台设备驱动提供统一的适配接口,使其只关注自身硬件的控制,而不必关注设备管理及公共业务流程。
- 提供设备注册、管理、访问控制等与SOC无关的公共能力。
2.平台驱动框架介绍
OpenHarmony系统平台驱动框架主要由平台接口层、平台核心层以及平台适配层三个部分组成。

-
平台接口层 以API的形式提供标准的平台设备访问接口。
平台接口层以设备句柄加配套API的形式对外提供统一的、标准的访问接口。
设备句柄是DevHandle类型的实例,通过不同设备模块提供的Open/Close方法进行获取、释放。成功获取设备句柄后,即可使用相应的API执行设备操作。例如通过I2cTransfer完成一次I2C数据传输。
这是一种代理模式,即接口层API不直接引用实际设备对象,而是通过DevHandle作为代理,间接访问设备;而所有来自外设驱动的访问,都建议走接口层,以获得最佳的稳定性。
-
平台核心层 提供平台设备模型及公共业务框架。
提供统一适配接口:定义了标准的设备对象模型,驱动程序仅需关注标准对象模型的适配。抽取公共业务框架:将不同设备模块的公共流程、算法加以抽取,使得具体设备驱动更加轻薄。
设备管理:设备注册、注销、设备查找、访问控制。
-
平台适配层 提供特定平台设备的适配驱动,并遵守核心层约束。
驱动具体平台设备硬件,并创建对应的设备模型对象,注册到核心层纳入统一管理。
2.1.平台接口层分析
接口层用DevHandle类型的设备句柄表示一个平台设备对象,然后针对不同类型设备提供一套标准的API方法用于设备访问。那么设备句柄和真实的设备对象如何关联呢?
drivers_hdf_core/framework/include/platform/platform_if.h:39 /**40 * @brief Defines the common device handle of the platform driver.41 *42 * The handle is associated with a specific platform device and is used as the43 * first input parameter for all APIs of the platform driver.44 *45 * @since 1.046 */47 typedef void* DevHandle;
在内核态,这个指针可以直接指向实际设备对象,但是对于某些类型的平台设备,需要在用户态提供同样的DevHandle类型及配套API,而实际设备对象在内核空间,导致无法直接获取和使用内核空间的地址。
解决办法:将平台设备对象实现为一个HDF设备服务,这样借助HDF DeviceManager的设备服务机制,可以在用户态、内核态同时获取到设备服务,而用户态同内核态通信的问题交由HDF DeviceManager处理。此时,DevHandle只需要关联到这个设备服务即可,而void*类型保证了足够的灵活性。
根据DevHandle和设备对象关联方式的不同,接口层的设计有三种模式:
2.1.1.独立服务模式
典型实践是UART模块。

使用范围:在用户态和内核态同时提供API的设备类型,DevHandle同设备对象的关联方式为:
-
用户态:关联到平台设备对应的设备服务;
-
内核态:关联到实际平台设备对象或其设备服务(在内核态两者可互相转换)
每一个设备对象,会独立发布一个设备服务,来处理外部访问,服务收到API的访问请求之后,通过提取请求参数,并调用实际设备对象的相应内部方法。
优点:管理比较简单,因为它借助了HDF DeviceManager的服务管理能力;
缺点:需要为每一个设备对象配置设备节点,以便发布设备服务。
2.1.2.统一服务模式
典型实践是I2C模块。

同一类型的设备对象可能会很多,例如I2C模块,可能同时有十几个控制器。如果采用独立服务的模式,每一个控制器,作为一个平台设备,为其创建一个设备服务,那么将会有十几个服务被创建,不光要配置很多设备节点,而且这些服务还会占用内存资源。
因此为一类设备对象,创建一个平台设备管理器(PlatformManager)对象,并同时对外发布一个管理器服务,由这个管理器服务来统一处理外部访问。当用户需要打开某个设备时,先通过HDF DeviceManager获取到管理器服务,然后管理器服务根据用户指定参数查找到指定设备,并返回一个设备描述符,而这个描述符仍然可以由DevHandle类型表示。
2.1.3.无服务模式
用于不需要在用户态提供API的设备类型或者没有用户态、内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址。而PlatformManager的实现比较自由,它不需要实现设备服务,只需做好某种类型的设备管理即可,甚至在C语言中,由于无法进行OOP编程,很多模块直接将这个功能面向过程化了,使得没有一个具体的结构体与之对应。
2.2.平台核心层
平台核心层的作用是承上启下,其主要内容包括:
-
提供适配接口:为具体的平台设备驱动提供统一的适配接口
平台驱动框架为不同设备类型,定义了标准的设备对象模型,具体设备驱动只需要关注标准设备对象的适配即可
-
提供设备管理:提供设备的注册、注销、查找等功能、访问控制等能力
核心层会提供一系列内部方法,用于设备的注册、注销,设备对象的查找、获取、释放,以及处理多线程访问。例如当向核心层注册一个I2C控制器对象时,使用I2cCntlrAdd;当希望获取一个I2C控制器对象时,通过I2cCntlrGet并指定控制器编号;当不再使用这个对象时,还需要通过I2cCntlrPut释放。这样做的好处是将每一个具体的操作步骤高度抽象化,减小同平台接口层及平台适配层的耦合面,便于业务解耦、演进。由于业务需求需要对I2cCntlr对象进行引用计数,那么只需要修改I2cCntlrGet/Put这对方法的实现即可,并不会影响平台接口层和平台适配层。
-
公共业务实现:抽取公共的业务流程、算法
凡是跟特定硬件无关的业务逻辑,都会被抽取到核心层,例如RTC时钟的时间格式转换算法,GPIO模块的线程中断实现等等。
2.3.平台适配层实现
适配层提供具体平台硬件设备的驱动,按照核心层定义的模型创建设备对象,并完成对象的初始化(包括必要的成员变量初始化以及钩子方法挂接,以及相关的硬件初始化操作),最后使用核心层提供的注册方法将设备对象注册到核心层纳入统一管理。
3.OpenHarmony系统平台驱动适配
3.1.UART模块适配
UART模块适配的核心环节,是UartHost对象的创建、初始化及注册。UART模块采用的是独立服务模式,要求每一个UartHost对象关联一个HDF设备服务。
1).device_info.hcs: 为每一个UART控制器配置一个HDF设备节点
vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs:71 device_uart :: device {72 device0 :: deviceNode {73 policy = 2;74 priority = 40;75 permission = 0644;76 moduleName = "HDF_PLATFORM_UART";77 serviceName = "HDF_PLATFORM_UART_0";78 deviceMatchAttr = "rockchip_rk3568_uart_0";79 }80 device1 :: deviceNode {81 policy = 2;82 permission = 0644;83 priority = 40;84 moduleName = "HDF_PLATFORM_UART";85 serviceName = "HDF_PLATFORM_UART_1";86 deviceMatchAttr = "rockchip_rk3568_uart_1";87 }88 device2 :: deviceNode {89 policy = 2;90 permission = 0644;91 priority = 40;92 moduleName = "HDF_PLATFORM_UART";93 serviceName = "HDF_PLATFORM_UART_3";94 deviceMatchAttr = "rockchip_rk3568_uart_3";95 }96 }
说明:
-
policy大于等于1(如需对用户态可见为2,仅内核态可见为1);
-
moduleName需要与驱动Entry中moduleName 保持一致;
-
serviceName必须要按照HDF_PLATFORM_UART_X的格式,X为UART控制器编号;
-
deviceMatchAttr用于配置控制器私有数据,要与uart_config.hcs中对应控制器保持一致,如不需要则忽略。
2). uart_config.hcs:每一个UART控制器配置私有数据
如果控制器需要配置一些私有数据,例如寄存器基地址,初始化波特率等等,可以在uart_config.hcs中配置,该文件将在产品配置目录的hdf.hcs中导入,具体路径可由产品自由配置。
vendor/hihope/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs:1 root {2 platform {3 uart_config {4 template uart_device {5 serviceName = "";6 match_attr = "";7 driver_name = "ttyS";8 num = 0;9 }1011 device_uart_0x0000 :: uart_device {12 match_attr = "rockchip_rk3568_uart_0";13 }14 device_uart_0x0001 :: uart_device {15 num = 1;16 match_attr = "rockchip_rk3568_uart_1";17 }18 device_uart_0x0003 :: uart_device {19 num = 3;20 match_attr = "rockchip_rk3568_uart_3";21 }22 }23 }24 }hihope/rk3568/hdf_config/khdf/hdf.hcs:1 #include "device_info/device_info.hcs"2 #include "platform/adc_config_linux.hcs"3 #include "platform/pwm_config.hcs"4 #include "platform/rk3568_watchdog_config.hcs"5 #include "platform/rk3568_uart_config.hcs"6 #include "platform/sdio_config.hcs"7 #include "platform/emmc_config.hcs"8 #include "platform/rk3568_spi_config.hcs"9 #include "input/input_config.hcs"10 #include "wifi/wlan_platform.hcs"11 #include "wifi/wlan_chip_ap6275s.hcs"12 #include "camera/camera_config.hcs"13 #include "sensor/sensor_config.hcs"14 #include "audio/audio_config.hcs"15 #include "audio/codec_config.hcs"16 #include "audio/dai_config.hcs"17 #include "audio/dma_config.hcs"18 #include "audio/dsp_config.hcs"19 #include "audio/analog_headset_config.hcs"20 #include "light/light_config.hcs"21 #include "vibrator/vibrator_config.hcs"22 #include "vibrator/linear_vibrator_config.hcs"23 #include "vibrator/drv2605l_linear_vibrator_config.hcs"24 #include "lcd/lcd_config.hcs"
3).驱动的Entry结构
先执行Bind方法绑定服务,后执行Init 初始化。
drivers_hdf_core\framework\sample\platform\uart\src\uart_sample.c
struct HdfDriverEntry g_sampleUartDriverEntry = {.moduleVersion = 1,.moduleName = "UART_SAMPLE",.Bind = SampleUartDriverBind,.Init = SampleUartDriverInit,.Release = SampleUartDriverRelease,
};// Initialize HdfDriverEntry
HDF_INIT(g_sampleUartDriverEntry);
- Bind方法调用UartHostCreate创建 UartHost 控制器对象并完成服务绑定。
drivers_hdf_coreframework\support\platform\include\uart\uart_core.h:
struct UartHost {struct IDeviceIoService service;struct HdfDeviceObject *device;uint32_t num;OsalAtomic atom;void *priv;struct UartHostMethod *method;
};drivers_hdf_core\framework\sample\platform\uart\src\uart_sample.c
static int32_t SampleUartDriverBind(struct HdfDeviceObject *device)
{struct UartHost *uartHost = NULL;HDF_LOGD("%s: Enter", __func__);uartHost = UartHostCreate(device);uartHost->service.Dispatch = SampleDispatch;return HDF_SUCCESS;
}drivers_hdf_core/framework/support/platform/src/uart/uart_core.c79 struct UartHost *UartHostCreate(struct HdfDeviceObject *device)80 {81 struct UartHost *host = NULL;8288 host = (struct UartHost *)OsalMemCalloc(sizeof(*host));9394 host->device = device;95 device->service = &(host->service);96 host->device->service->Dispatch = UartIoDispatch;97 OsalAtomicSet(&host->atom, 0);98 host->priv = NULL;99 host->method = NULL;
100 return host;
101 }
该方法中将UartHost对象同HdfDeviceObject进行关联:
- 为HdfDeviceObject的service成员进行赋值,使其指向UartHost的IDeviceIoService类型的成员对象;
- 同时为service成员的Dispatch方法赋值。
UartHostCreate函数设置host->device->service->Dispatch = UartIoDispatch; 最后SampleUartDriverBind函数使用uartHost->service.Dispatch = SampleDispatch; 进行覆盖UartIoDispatch。
这样做的结果:
-
为HdfDeviceObject对象绑定IDeviceIoService类型的服务对象
-
UartHost和其IDeviceIoService类型的成员对象service可以相互转换
-
通过UartHost对象即可获取HdfDeviceObject对象
-
通过HdfDeviceObject对象即可间接获取UartHost对象(先获取service再转为host)
4). Init方法
完成UartHost对象的初始化。代码调用流程:
SampleUartDriverInit->AttachUartDevice->AddUartDevice->AddRemoveUartDev->register_driver->host->method = &g_sampleUartHostMethod;
代码分析:
drivers_hdf_core\framework\sample\platform\uart\src\uart_sample.c
static int32_t SampleUartDriverInit(struct HdfDeviceObject *device)
{int32_t ret;struct UartHost *host = NULL;HDF_LOGD("%s: Enter", __func__);host = UartHostFromDevice(device);ret = AttachUartDevice(host, device);host->method = &g_sampleUartHostMethod;return ret;
}struct UartHostMethod g_sampleUartHostMethod = {.Init = SampleUartHostInit,.Deinit = SampleUartHostDeinit,.Read = NULL,.Write = SampleUartHostWrite,.SetBaud = SampleUartHostSetBaud,.GetBaud = SampleUartHostGetBaud,.SetAttribute = NULL,.GetAttribute = NULL,.SetTransMode = NULL,
};
通过UartHostFromDevice从HdfDeviceObject对象获取之前关联的UartHost对象,然后调用 AttachUartDevice方法完成host对象的初始化,最后为host对象挂接钩子方法g_sampleUartHostMethod。
小结:
UART适配关键是在驱动Entry的Bind方法中创建UartHost对象,而且是使用UartHostCreate创建。这个创建动作同时也是注册的动作,因为它将UartHost以HDF设备服务的形式同HdfDeviceObject进行绑定,这样就完成了服务的发布,HDF Manager对设备服务的管理也就是对UartHost的管理,核心层可以通过HDF提供的服务获取接口来访问UartHost。
UART适配采用独立服务模式,每一个UartHost对象同时也是一个设备服务,其优点是可以直接利用HDF Manager进行管理;缺点是需要在device_info.hcs为每一个UartHost对象定义设备节点。
3.2.UART模块主要接口
- drivers/hdf_core/framework/include/platform/uart_if.h
DevHandle UartOpen(uint32_t port) UART获取设备句柄
void UartClose(DevHandle handle) UART释放设备句柄
int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size) 从UART设备中读取指定长度的数据
int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size) 向UART设备中写入指定长度的数据
int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate) UART获取波特率
int32_t UartSetBaud(DevHandle handle, uint32_t baudRate) UART设置波特率
int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute) UART获取设备属性
int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute) UART设置设备属性
int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode) UART设置传输模式
本文涉及的UART所有接口,支持内核态及用户态使用。
3.2.1.UartOpen
UartOpen->UartGetObjGetByBusNum(port);-> DevSvcManagerClntGetService(name) -> UartHostRequest((struct UartHost *)handle);
- UartGetObjGetByBusNum 调用DevSvcManagerClntGetService,根据name=“HDF_PLATFORM_UART_port” (framework/sample/config/device_info/device_info.hcs) 获取到handle 即host。
- UartHostRequest 调用host->method->Init,即UartHostDevInit(uart_asr.c)
3.2.2.UartWrite
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size)
{int ret;struct HdfIoService *service = NULL;struct HdfSBuf *sBuf = HdfSbufObtainDefaultSize();if (!HdfSbufWriteBuffer(sBuf, data, size)) {HDF_LOGE("Failed to write sbuf");HdfSbufRecycle(sBuf);return HDF_FAILURE;}service = (struct HdfIoService *)handle->object;ret = service->dispatcher->Dispatch(&service->object, UART_WRITE, sBuf, NULL);HdfSbufRecycle(sBuf);return ret;
}
- 调用Dispatch接口进行写操作,即SampleDispatch,通过传输cmd 为UART_WRITE调用SampleDispatchWrite,然后调用UartPl011Write调用底层代码进行传输数据。
drivers_hdf_core\framework\sample\platform\uart\src\uart_dispatch_sample.c
int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{int32_t result = HDF_FAILURE;(void)reply;struct UartHost *uartHost = (struct UartHost *)client->device->service;struct UartDevice *uartDevice = (struct UartDevice *)uartHost->priv;switch (cmdId) {case UART_WRITE: {result = SampleDispatchWrite(uartDevice, data);break;}default:break;}return result;
}static int32_t SampleDispatchWrite(struct UartDevice *device, struct HdfSBuf *txBuf)
{uint32_t idx;uint32_t dataSize = 0;const uint8_t *data = NULL;struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;if (!HdfSbufReadBuffer(txBuf, (const void **)&data, &dataSize)) {HDF_LOGE("%s: Failed to read sbuf", __func__);return HDF_FAILURE;}regMap = (struct UartRegisterMap *)device->resource.physBase;for (idx = 0; idx < dataSize; idx++) {UartPl011Write(regMap, data[idx]);}return HDF_SUCCESS;
}drivers_hdf_core\framework\sample\platform\uart\include\uart_pl011_sample.h
static inline void UartPl011Write(struct UartRegisterMap *regMap, uint8_t byte)
{while (UartPl011IsBusy(regMap)) {}regMap->dr = byte;
}
3.3.用户层测试代码
- 通过/dev/uartdev-%d 节点访问
drivers_hdf_core\framework\sample\platform\uart\dev\hello_uart_dev.c
int main(void)
{int ret;int fd;const char info[INFO_SIZE] = {" HELLO UART! "};fd = open("/dev/uartdev-5", O_RDWR);if (fd < 0) {HDF_LOGE("uartdev-5 open failed %d", fd);return -1;}ret = write(fd, info, INFO_SIZE);if (ret != 0) {HDF_LOGE("write uartdev-5 ret is %d", ret);}ret = close(fd);if (ret != 0) {HDF_LOGE("uartdev-5 close failed %d", fd);return -1;}return ret;
}
- 使用UartOpen 接口进行方法
drivers_hdf_core\framework\sample\platform\uart\dispatch\hello_uart_dispatch.c
int main(void)
{const char *info = " HELLO UART! ";struct DevHandle *handle = UartOpen(UART_PORT);int ret = UartWrite(handle, (uint8_t *)info, strlen(info));UartClose(handle);return ret;
}
refer to
- git clone https://gitee.com/openharmony/drivers_hdf_core.git
- https://blog.csdn.net/HarmonyOS_666/article/details/140824175
- https://blog.csdn.net/maniuT/article/details/141064333
- https://blog.csdn.net/zxc95279527q/article/details/143062695
相关文章:
OpenHarmony-3.HDF框架(2)
OpenHarmony HDF 平台驱动 1.平台驱动概述 系统平台驱动框架是系统驱动框架的重要组成部分,它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制,为各类平台设备驱动的实现提供标准模型。 系统平台驱动(…...
人大金仓(KingBaseEs)数据库操作手册
人大金仓数据库(KingbaseES)是由北京人大金仓信息技术股份有限公司(简称人大金仓)自主研发的、具有自主知识产权的通用关系型数据库管理系统。 官方下载地址:KingbaseES 人大金仓数据库 KES技术文档在线手册…...
Flink+Paimon实时数据湖仓实践分享
随着 Paimon 近两年的推广普及,使用 FlinkPaimon 构建数据湖仓的实践也越来越多。在 Flink 实时数据开发中,对于依赖大量状态 state 的场景,如长周期的累加指标计算、回撤长历史数据并更新等,使用实时数仓作为中间存储来代替 Flin…...
w~深度学习~合集1
我自己的原文哦~ https://blog.51cto.com/whaosoft/12663254 #Motion Plan 代码 github.com/liangwq/robot_motion_planing 轨迹约束中的软硬约束 前面的几篇文章已经介绍了,轨迹约束的本质就是在做带约束的轨迹拟合。输入就是waypoint点list,约束…...
KVM 虚拟化
KVM(Kernel-based Virtual Machine)是一种基于内核的虚拟机技术,具有以下优势: 开源性:KVM是完全开源的,这意味着它没有许可费用,适合预算有限的用户。性能:KVM利用Linux内…...
MONI后台管理系统-数据库设计
前言:该文档纯属个人总结设计,如果雷同,纯属巧合,其中还有很不合理之处,请大家批评指正。如有应用于项目,请慎重。 注意: 如有需要该文件的sql脚本,请移步:资源下载 1. 表清单 序号…...
Rigol DP711自动控制--SCPI命令
通过串口的SCPI命令来控制通道输入输出 也可以用UltraSigma UI来发送SCPI 物理连接: Pin2_2, Pin3_3, Pin5_5 串口命令控制: 命令:9600, 8bit, None SCPI CMD(Standard Commands for Programmable Instruments) OUTPut CH1, On…...
总结FastDFS的面试题
目录 一:FastDFS的基础知识 1:定义 2:FastDFS的优点 3:tracker server 4:storage server 二:FastDFS的存储原理 1:小文件存储的问题 2:小文件合并存储 3:文件上…...
Fiddler 5.21.0 使用指南:过滤浏览器HTTP(S)流量下(四)
概述 在上一篇文章中,我们介绍了一部分简单的过滤功能,已经可以帮助我们较为准确的定位到感兴趣的请求;提升我们的工作效率,我们可以通过设置更为复杂的过滤规则,精准到定位的我们想要的请求和响应信息。专注于分析对…...
【踩坑】pip安装依赖卡在Installing build dependencies ...
pip安装依赖卡在Installing build dependencies ... 如图,pip安装依赖一直卡着,最后不得不ctrlC强制终止 用–verbose显示详细安装信息,发现卡在安装numpy pip install -r requirements.txt --verbose大概率是网络问题,用镜像单…...
【WRF-Urban】SLUCM新增空间分布城市冠层参数及人为热排放AHF代码详解(下)
目录 详细解释更改文件内容4 运行模块(run):README.namelist5 输出模块(share):share/module_check_a_mundo.Fshare/output_wrf.F参考SLUCM新增空间分布城市冠层参数及人为热排放AHF代码详解的前两部分内容可参见-【WRF-Urban】SLUCM新增空间分布城市冠层参数及人为热排放A…...
云桌面:云计算桌面
目录 云桌面的定义和核心概念 技术架构详解 主流架构详解 管理成本分析 安全性措施 应用场景详解 云桌面的定义和核心概念 云桌面是一种通过云计算技术提供的虚拟桌面服务,它允许用户通过网络访问远程服务器上的虚拟机,这些虚拟机为用户提供了一个…...
WPF+LibVLC开发播放器-音量控制和倍速控制
界面 界面上增加音量的控件和倍速控制控件 音量控制 主要也是一个Slider进度条控件来实现音量调节 我们这里设置默认的最大值为100,默认Value值也为100,默认声音开到最大 这里目前完全由前端控制音量调节,可以直接使用ValueChanged事件实…...
数智运营一体化平台项目经营分享
分离前后台,增强产品管理灵活性 前端成熟的流程平台,支持低代码快速灵活配置流程表单,完美解决流程频繁变化与快速上线、费用控制的矛盾。使产品管理体系,摆脱了流程可移植性差和投入大量人力物力无止境修改流程的困境。同时&…...
记录blender学习过程中遇到的问题
物体发射的方向不对 被发射物体(例如一棵树)n键看旋转归0 切换正视图 将被发射物体的局部坐标的Z轴 指向 全局方向的X轴时 并且把粒子系统设置的物体旋转勾选上 方向就对了 做倒角发现有问题 检查缩放应用、面朝向、有没有重合点(融合点&am…...
(八)腾讯cloudstudio+Stable-Diffusion-webui AI绘画教程-安装插件
一、说明 本文安装8个插件,先安装,后面在慢慢学习,我也是第一次喔 二、中英文双语语言包 (二)Ubuntu22.04Stable-Diffusion-webui AI绘画 中英双语插件安装-CSDN博客https://blog.csdn.net/jiangkp/article/details…...
记一次跑前端老项目的问题
记一次跑前端老项目的问题 一、前言二、过程1、下载依赖2、启动项目3、打包 一、前言 在一次跑前端老项目的时候,遇到了一些坑,这里记录一下。 二、过程 1、下载依赖 使用 npm install下载很久,然后给我报了个错 core-js2.6.12: core-js…...
深度学习:MindSpore自动并行
随着模型规模的逐渐增大,需要的算力逐渐增强,但是算力需求增长速度远高于芯片算力增长速度。现在唯一的解决方案只有通过超大规模集群训练大模型。 大集群训练大模型的挑战 内存墙 200B参数量的模型,参数内存占用745GB内存,训练…...
python拆分Excel文件
按Sheet拆分Excel 或 按照某一列的不同值拆分Excel。文档样式如下: 结果:红色是按照Sheet名拆出的,蓝色和橙色是某个Sheet按照某列的不同值拆分的。 代码: # -*- coding: utf-8 -*- """ 拆分excel文件——按照…...
Python实现Excel中数据条显示
Python中要实现百分比数据条的显示,可以使用pandas库,pandas图表样式的设置与Excel中的条件格式设置比较类似,比如Excel里常用的数据条的用法,在pandas中使用代码进行高亮显示,用来突出重点数据,下面一起来…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
