sdio架构初解

linux device driver之sdio驱动编程 先谈谈如何写linux驱动: - 在驱动模块初始化函数中调用register_chrdev(),将驱动向系统注册为一个字符设备,伪装成一个文件,上层的应用可以通过访问这个文件(字符设备),来操作驱动模块。 - 驱动模块注册为字符设备后,还需要用户在命令行中敲mknod命令来创建一个对应的字符文件,上层应用就是用open, close, read, write该文件这样的方式来访问驱动模块。 阅读详情

原文地址:http://blog.youkuaiyun.com/zoe6553/article/details/6588306

一.前言

SD卡的大名是耳熟能详,但是SDIO总线确是不为人解,不过说起他的近亲SPI就知道了。我们这里主要是理解SDIO总线,并不去理解SPI总线。也许大家会畏惧其庞大的代码,其实我们并不需要详细理解其具体的实现,我们需要理解其架构。

二.主机(host)

在linux2.6.28中,在sdhci-s3c.c实现对主机的sdhci的驱动,而其设备的添加则在smdk6410_devices中。

在sdhci-s3c.c的sdhci_s3c_probe实现对主机端的驱,对于里面具体的一些实现我们就不看了,主要是看其中通用的code。

static int __devinit sdhci_s3c_probe(structplatform_device *pdev)

{

         structsdhci_host*host;

         structsdhci_s3c *sc;

         host= sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));

         sc= sdhci_priv(host);

         sdhci_add_host(host);

}

对于上面的函数,主要就是关心上面的几段代码。首先,来看sdhci_host这个结构体,这个是个很重要的东西,这个将会贯穿整个驱动。

struct sdhci_host {

         /*Data set by hardware interface driver */

         constchar                  *hw_name;      /* Hardware bus name */

         unsignedint              quirks;               /* Deviations from spec. */

         int                       irq;            /* Device IRQ */

         void__iomem *                 ioaddr;               /* Mapped address */

         conststruct sdhci_ops    *ops;                  /* Low level hw interface */

         structmmc_host              *mmc;               /* MMC structure */

         u64                     dma_mask;      /* custom DMA mask */

         spinlock_t                  lock;          /* Mutex */

         int                       flags;                  /* Host attributes */

         unsignedint              version;    /* SDHCI spec. version */

         unsignedint              max_clk;  /* Max possible freq (MHz) */

         unsignedint              timeout_clk;    /* Timeout freq (KHz) */

         unsignedint              clock;                 /* Current clock (MHz) */

         unsignedshort                   power;               /* Current voltage */

         structmmc_request        *mrq;                 /* Current request */

         structmmc_command    *cmd;                /* Current command */

         structmmc_data              *data;                /* Current data request */

         unsignedint              data_early:1;   /* Data finished before cmd */

         structsg_mapping_iter  sg_miter;          /* SG state for PIO */

         unsignedint              blocks;               /* remaining PIO blocks */

         int                       sg_count;         /* Mapped sg entries */

         u8                       *adma_desc;   /* ADMA descriptor table */

         u8                       *align_buffer;  /* Bounce buffer */

         dma_addr_t              adma_addr;     /* Mapped ADMA descr. table */

         dma_addr_t              align_addr;       /* Mapped bounce buffer */

         structtasklet_struct        card_tasklet;   /* Tasklet structures */

         structtasklet_struct        finish_tasklet;

         structtimer_list       timer;                /* Timer for timeouts */

         unsignedlong           private[0]____cacheline_aligned;

};

上面的结构体主要需要关注mmc_host和两个tasklet_struct。

struct mmc_host {

         structdevice             *parent;

         structdevice             class_dev;

         int                       index;

         conststruct mmc_host_ops *ops;

         unsignedint              f_min;

         unsignedint              f_max;

         u32                     ocr_avail;

         unsignedlong           caps;                  /* Host capabilities */

         /*host specific block data */

         unsignedint              max_seg_size;         /* see blk_queue_max_segment_size */

         unsignedshort                   max_hw_segs;         /* see blk_queue_max_hw_segments */

         unsignedshort                   max_phys_segs;      /* see blk_queue_max_phys_segments */

         unsignedshort                   unused;

         unsignedint              max_req_size;          /* maximum number of bytes in one req*/

         unsignedint              max_blk_size; /* maximum size of one mmc block */

         unsignedint              max_blk_count;       /* maximum number of blocks in one req */

         /*private data */

         spinlock_t                  lock;          /* lock for claim and bus ops */

         structmmc_ios                 ios;            /* current io bus settings */

         u32                     ocr;           /* the current OCR setting */

         /*group bitfields together to minimize padding */

         unsignedint              use_spi_crc:1;

         unsignedint              claimed:1;        /* host exclusively claimed */

         unsignedint              bus_dead:1;     /* bus has been released */

         structmmc_card              *card;                /* device attached to this host*/

         wait_queue_head_t         wq;

         structdelayed_work        detect;

         conststruct mmc_bus_ops *bus_ops;   /* currentbus driver */

         unsignedint              bus_refs; /* reference counter */

         unsignedint              sdio_irqs;

         structtask_struct   *sdio_irq_thread;

         atomic_t           sdio_irq_thread_abort;

         structdentry             *debugfs_root;

         unsignedlong           private[0]____cacheline_aligned;

};

Mmc_host可以认为是总线设备的一种封装。

继续上面的源码在sdhci_alloc_host->mmc_alloc_host中,会发现我们的申请的mmc_host设备指向一个特殊的类mmc_host_class,在该类中并没有什么特殊的function只有一个mmc_host_classdev_release,从下面的code可知主要是释放在mmc_alloc_host中开辟的空间。为什么需要这样来设计就不知道???

static void mmc_host_classdev_release(structdevice *dev)

{

         structmmc_host *host = cls_dev_to_mmc_host(dev);

         kfree(host);

}

下面来看sdhci_add_host这个函数。

int sdhci_add_host(struct sdhci_host *host)

{

         structmmc_host *mmc;

         mmc= host->mmc;

         tasklet_init(&host->card_tasklet,sdhci_tasklet_card,(unsigned long)host);

         tasklet_init(&host->finish_tasklet,sdhci_tasklet_finish,(unsigned long)host);

         setup_timer(&host->timer,sdhci_timeout_timer, (unsigned long)host);

         request_irq(host->irq,sdhci_irq, IRQF_SHARED,mmc_hostname(mmc), host);

         mmc_add_host(mmc);

         return0;

}

也许大家很困惑,为什么只关注这几行code,在该函数中主要是集中在mmc_host成员的初始化赋值。由于中断中需要处理的内容较多故采用底半部的办法来处理部分内容。

card_tasklet用于处理MMC插槽上的状态变化。finish_tasklet用于命令传输完成后的处理。Timer用于等待硬件中断。Irq则是SDHCI的中断处理。

将host添加入mmc管理,其本质即是添加host的class_dev

int mmc_add_host(struct mmc_host *host)

{       

device_add(&host->class_dev);

         mmc_start_host(host);

         return0;

}

void mmc_start_host(structmmc_host *host) –启动host

{

         mmc_power_off(host);   --关闭MMC

         if(host->caps & MMC_CAP_BOOT_ONTHEFLY)

                   mmc_rescan(&host->detect.work);  --重新扫描

         else

                   mmc_detect_change(host,0);  --处理状态改变

}

void mmc_detect_change(struct mmc_host *host,unsigned long delay)

{

         mmc_schedule_delayed_work(&host->detect,delay);

}

在mmc_alloc_host时,存在下面一行code

INIT_DELAYED_WORK(&host->detect, mmc_rescan);

到此就会发现mmc_start_host一定会执行mmc_rescan只不过一个是延时后执行,一个是没有延时执行。

void mmc_rescan(struct work_struct *work)

{

         structmmc_host *host =container_of(work, struct mmc_host, detect.work);

         u32ocr;

         interr;

         mmc_bus_get(host);

         if(host->bus_ops == NULL) { --如果为第一次扫描总线上设备。

                   /*

                    * Only we can add a new handler, so it's safetorelease the lock here.

                    */

                   mmc_bus_put(host);

                   if(host->ops->get_cd && host->ops->get_cd(host) == 0)

                            gotoout;

                   mmc_claim_host(host);  --申请一个host

                   mmc_power_up(host);   --开启host电源

                   mmc_go_idle(host);     --设置host为idle模式

                   mmc_send_if_cond(host,host->ocr_avail);--是用于验证SD卡接口操作状态的有效性命令(CMD8)。如果 SD_SEND_IF_COND指示为符合SD2.0标准的卡,则设置操作状态寄存器ocrbit30指示能 够处理块地址SDHC卡

                   /*

                    * First we search for SDIO...

                    */

                   err= mmc_send_io_op_cond(host, 0, &ocr);

                   if(!err) {

                            if(mmc_attach_sdio(host, ocr))

                                     mmc_power_off(host);

                            gotoout;

                   }

                   /*

                    * ...then normal SD...

                    */

                   err= mmc_send_app_op_cond(host, 0, &ocr);

                   if(!err) {

                            if(mmc_attach_sd(host, ocr))

                                     mmc_power_off(host);

                            gotoout;

                   }

                   /*

                    * ...and finally MMC.

                    */

                   err= mmc_send_op_cond(host, 0, &ocr);

                   if(!err) {

                            if(mmc_attach_mmc(host, ocr))

                                     mmc_power_off(host);

                            gotoout;

                   }

                   mmc_release_host(host);

                   mmc_power_off(host);

         }else {

                   if(host->bus_ops->detect && !host->bus_dead)

host->bus_ops->detect(host);

                   mmc_bus_put(host);

         }

out:

         if(host->caps & MMC_CAP_NEEDS_POLL)

                   mmc_schedule_delayed_work(&host->detect,HZ);

}

那先来看mmc_send_if_cond实现,从字面意思上看该函数就是发送一个SD标准命令,亦如usb的标准命令一样。

在这里不得不先说明一点就是在SD子系统中,所有的数据传输均是由host发起。Host发送完一命令则会等待中断的产生,在这里采用完成量来实现进程的阻塞。

void mmc_wait_for_req(struct mmc_host *host,struct mmc_request *mrq)

{

         DECLARE_COMPLETION_ONSTACK(complete);

         mrq->done_data= &complete;

         mrq->done= mmc_wait_done;

         mmc_start_request(host,mrq);  --开始request

         wait_for_completion(&complete);

}

mmc_start_request->host->ops->request(即sdhci_request)

static void sdhci_request(structmmc_host *mmc, struct mmc_request *mrq)

{

         structsdhci_host *host;

         unsignedlong flags;

         host= mmc_priv(mmc);

         spin_lock_irqsave(&host->lock,flags);

         host->mrq= mrq;

         if((mmc->caps & MMC_CAP_ON_BOARD) || (host->flags &SDHCI_DEVICE_ALIVE))

                   sdhci_send_command(host,mrq->cmd);

         else{

                   if(!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)

||(host->flags & SDHCI_DEVICE_DEAD)) {

                            host->mrq->cmd->error= -ENOMEDIUM;

                            tasklet_schedule(&host->finish_tasklet);

                   }else

                            sdhci_send_command(host,mrq->cmd);

         }

         mmiowb();

         spin_unlock_irqrestore(&host->lock,flags);

}

sdhci_request-> sdhci_send_command发送命令。

当命令传输完成系统调用中断处理函数sdhci_irq。在其中进行中断完成后的处理。

以SDIO为例其会采用mmc_attach_sdio来实现驱动和设备的匹配,其本质还是根据sdio_bus的匹配规则来实现匹配。在mmc_attach_sdio中首先是mmc匹配一个bus,即采用何种bus来进行mmc bus来处理host。在这里需要理解一点就是在SDIO中,对于SD卡存储器mmc为实体设备,而对于非SD卡存储器,如SDIO接口的设备,则mmc则表征为bus,这个比较重要。除了mmc bus外还存在SDIO_BUS。

int mmc_attach_sdio(struct mmc_host *host,u32 ocr)

{

         interr;

         inti, funcs;

         structmmc_card *card;

         mmc_attach_bus(host,&mmc_sdio_ops); --host匹配一条mmc bus

         card= mmc_alloc_card(host, NULL); --申请一个card实体,类似于总线设备。

         card->type= MMC_TYPE_SDIO;

         card->sdio_funcs= funcs;

         host->card= card;

         for(i = 0;i < funcs;i++) {

                   sdio_init_func(host->card,i + 1);

         }

         mmc_release_host(host);

         mmc_add_card(host->card);

         for(i = 0;i < funcs;i++) {

                   sdio_add_func(host->card->sdio_func[i]);      

}

         return0;

}

比较难以理解的是func,这个东东其实是一个实体设备的封装,可以认为其是一个设备。

struct sdio_func *sdio_alloc_func(structmmc_card *card)

{

         structsdio_func *func;

         func= kzalloc(sizeof(struct sdio_func), GFP_KERNEL);

         func->card= card;

         device_initialize(&func->dev);

         func->dev.parent= &card->dev;  --很明显card设备为sdio设备的父设备。

         func->dev.bus= &sdio_bus_type;

         func->dev.release= sdio_release_func;

         returnfunc;

}

上面的code一目了然,其就是具体设备实体的封装,其bus类型为sdio_bus. sdio_init_func仅仅是初始化一个设备,而并没有register。在sdio_add_func实现设备的register,同理就是card实体,在mmc_add_card之前并没有注册,在mmc_add_card函数中才实现设备的注册。

到此设备注册也就完成了,其实sdio总线在形式上类似于usb bus,为什么呢?编写过usb驱动的童鞋们应该知道,编写usb驱动仅仅是编写驱动的加载,并没有具体加载设备实体,导致很多童鞋的困惑,为什么没有设备的加载,其实在usb设备插入时,会动态的创建一个usb设备实体,在usb设备实体创建完成后,根据不同设备id调用相匹配的驱动。而SDIO设备设备也是一样的。上面的code比较混乱,总是让人看不出具体的设备的加载。其实在上面的code中,其中包括了mmc host的驱动。

三.驱动加载

我们还是以SDIO驱动为例,注册一个SDIO驱动会调用下面的函数。

int sdio_register_driver(struct sdio_driver*drv)

{

         drv->drv.name= drv->name;

         drv->drv.bus= &sdio_bus_type;

         returndriver_register(&drv->drv);

}

其实很好理解sdio_driver其实是driver的封装,并且该driver的bus为sdio_bus_type。这个设备的驱动很简单。那来看sdio_driver结构

struct sdio_driver{

         char*name; --驱动名称

         conststruct sdio_device_id *id_table;  --驱动设备ID

         int(*probe)(struct sdio_func *, const struct sdio_device_id *);

         void(*remove)(struct sdio_func *);

         structdevice_driver drv;

};

id_table很熟悉吧,嘿嘿在usb的驱动中如何将设备和驱动匹配就是根据这个东西。在SDIO中也是根据该id_table来进行设备和驱动的匹配。

四.驱动和设备匹配

在介绍了设备注册和驱动注册后,那来看这两个是怎样匹配的。记住SDIO驱动之上有两条总线一个mmc bus 一个是SDIO bus。

先来看mmc bus的match

static int mmc_bus_match(struct device *dev,struct device_driver *drv)

{

         return1;

}

这个很省事,直接就是1.

那在看sdio bus 的match

static int sdio_bus_match(struct device *dev,struct device_driver *drv)

{

         structsdio_func *func = dev_to_sdio_func(dev);

         structsdio_driver *sdrv = to_sdio_driver(drv);

         if(sdio_match_device(func, sdrv))

                   return1;

         return0;

}

通过查看上面的具体code的实现你就会发现就是根据id_table来实现设备和驱动的匹配。

五.probe

不管在设备注册还是驱动注册时,如果发现存在对应的设备和驱动则会调用对应的驱动。不过记住一点是均会先调用mmc bus的probe其次是sdio bus的probe。其实现的过程与platfrom类似,不多加赘述。

六.总结

SDIO说白了还是一种总线,其本质还是离不开驱动和设备这两者,如果有usb驱动的经验则会很好的理解SDIO总线的驱动。在linux内核是可以触类旁通的。
SDIO_WiFi驱动学习之SDIO架构介绍及源码分析 一、引言 因为WiFi驱动比较复杂,所以WiFi驱动的博客将分为两篇来写。 本篇博客主要介绍Linux下的SDIO架构及源码分析。 二、SDIO WiFi SDIO-Wifi模块是基于SDIO接口的符合wifi无线网络标准的嵌入式模块,内置无线网络协议IEEE802.11协议栈以及TCP/IP协议栈,能够实现用户主平台数据通过SDIO口到无线网络之间的转换。SDIO具有传输数据快,兼容SD、MMC接口等特点。 对于SDIO接口的WiFi,首先,它是一个SDIO的卡设备,然后具备了WiFi的功能。所 阅读详情

相关推荐

SDIO协议

SDIO协议1 概述  SDIO,全称:Secure Digital Input and Output ,即安全数字输入输出接口。2 特点①与多媒体卡系统规格书版本4.2全兼容。支持三种不同的数据总线模式:1位(默认)、4位和8位。②与较早的多媒体卡系统规格版本全兼容(向前兼容)。③与SD存储卡规格版本2.0全兼容。④与SD I/O卡规格版本2.0全兼容:支持两种不同的数据总线模式:1位(默认)和4

Let the development board fly! 3万+

linux设备驱动2

原文出自(http://wsqhs.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=amonth%3d5%26ayear%3d2009)这仍然是摘自自己工作笔记的第二部分,主要记述了我对在内核中注册驱动程序(我们这里以我的SDIO总线及wlan网卡举例)后,在内核中调用了哪些内核函数?其相应的设备树是如何形

WeekyHuang的专栏 2492

SDIO总线(一)

SDIO接口是在SD内存卡接口的基础上发展起来的接口,SDIO接口兼容以前的SD内存卡,并且可以连接SDIO接口的设备。 SDIO1.0标准定义了两种类型的SDIO卡: 1.全速的SDIO卡,传输率可以超过100Mbps; 2.低速的SDIO卡,支援的时脉速率在0至400KHz之间。       SDIO协议是由SD卡的协议演化升级而来的,很多地方保留了SD卡的读写协议,同

LiuHan的专栏 4万+

SD/SDIO(2):SDIO协议介绍和初始化流程

1、SDIO卡类型本规范定义了两种类型的SDIO卡。(1)全速支持SPI,1位SD和4位SD传输模式,时钟范围为0-25MHz,数据传输速率超过100Mb/s(2)低速该卡仅有SPI和1位SD传输模式,4位支持是可选的。低速SDIO卡应支持0-400 KHz的时钟范围。低速卡的预期用途是在使用较少引脚的情况下支持低速I/O功能,如调制解调器,条形码扫描器,GPS接收器等。2、SDIO卡模式SPI模式(强制,SDIO 2.0规范开始不强制要求支持SPI)1位SD数据传输模式(强制)

主要分享嵌入式软件、人工智能部分知识 5803

linux sdio驱动

文章目录架构sdio控制器驱动 架构 MMC/SD设备驱动在Linux中的结构层次 在Linux中MMC/SD卡的记忆体都当作块设备。MMC/SD设备驱动代码在drivers\mmc 分别有card、core和host三个文件夹, card层 存放闪存卡(块设备)的相关驱动,如MMC/SD卡设备驱动 core层 MMC的核心层,抽象了mmc驱动的公共部分,完成不同协议和规范的实现,为h...

osnet的博客 5148

Linux下SDIO驱动架构分析

持续更新中… Linux下SDIO驱动架构分析 最近在写一个SDIO的driver,参考了Linux下的SDIO driver这边做一个总结: 首先是源码存放的位置,Linux中和驱动相关的代码放在/driver中,其中SDIO 相关的code 放在 /driver/mmc中 注:这边需要提一下mmc是一种存储卡协议,EMMC 使用的就是mmc 协议,而sd 协议则是另一种协议(两者类似),由于历...

申小白 4633

SDIO架构初解2

谨以此文纪念过往的岁月以SDIO为例其会采用mmc_attach_sdio来实现驱动和设备的匹配,其本质还是根据sdio_bus的匹配规则来实现匹配。在mmc_attach_sdio中首先是mmc匹配一个bus,即采用何种bus来进行mmc bus来处理host。在这里需要理解一

zoe的专栏 6492

SDIO接口的理解

运用SD卡第一步,认识SDIO接口 做毕业设计需要用到大量的音频文件,一般的存储器满足不了存储要求,故选择SD卡作为存储器件。在这里记录一下自己的学习经历,学习一个新的IC,无非是要么根据时序图写出Read和Write函数,要么是根据通信总线和IC相关操作指令去完成Read和Write函数。只有能与对应IC“说话”,我们才能去开发它更多地可能性。这里以原子探索者为例,为大家介绍一下SD卡相关知识。...

su_fei_ma_su的博客 8486

linux设备驱动——andriod平台wlan驱动,降低CPU主频bootloader 是 2440BOOT_...-linux设备驱动——andriod平台wla...-sdio架构初解_169I...

有关linux设备模型这一块比较复杂,我不敢断定自己理解的肯定正确,但是我会在做这个驱动的过程中回过头来修改自己的笔记并且纠正自己在blog上贴的并不正确的地方。另外,我的无线网卡是挂接在SDIO总线上的,所以呢,我们之前会先介绍一点SDIO的驱动,当然并不在这篇blog上,这篇blog会是总领性的关于基础知识的介绍。下面是笔记:在进入正式的驱动代码之前,我们不得不补充一点基础知识,也就是在2.6...

weixin_39707536的博客 210

SDIO初始化流程

对STM32的SDIO——SD卡输入/输出模块摸索了一下,今天只看了POWER UP这个函数的实现。对SDIO编写驱动,需要参考SD卡的协议,我手上的SD卡协议是ver2.00的物理层简化协议。协议主要规定了主机(这里就是STM32)向SD卡写入的各种控制指令,以及SD卡的初始化过程状态转移图。了解SD卡从初始化状态转移图开始。这个图看起来有点复杂,感觉无从下手,其实仔细瞧瞧就跟我们数电学的状态转移图差不多,框框里面是各种操作,箭头指向下一步操作,直线引出去的部分就是状态发生跳转的条件。

T19900的博客 1604

光谱预处理最简单实现方法--基于OpenSA光谱分析库

系列文章目录 “光晰本质,谱见不同”,光谱作为物质的指纹,被广泛应用于成分分析中。伴随微型光谱仪/光谱成像仪的发展与普及,基于光谱的分析技术将不只停留于工业和实验室,即将走入生活,实现万物感知,见微知著。本系列文章致力于光谱分析技术的科普和应用。 文章目录系列文章目录前言一、数据来源二、代码解读2.1 读取数据2 .2 划分数据集2 .3 返回训练集和测试集并绘制光谱图片2.4 建立1-D CNN模型2.5 训练1-D CNN模型2.6 测试1-D CNN模型2.7 运行CNN模型,并用查看结果总结

Echo_Code的博客 7067

SDIO wifi驱动框架

SDHC:Secure Digital(SD) Host Controller,是指一套sd host控制器的设计标准,一般挂载sd和sdio设备,隶属于mmc子系统,其寄存器偏移以及意义都有一定的规范,并且提供了对应的驱动程序,方便vendor进行host controller的开发。Linux内核使用 net_device结构体表示一个具体的网络设备,网络驱动的核心就是初始化net_device 结构体中的各个成员变量,然后将初始化完成以后的net_device 注册到 Linux内核中。

yangzhipengyzp的博客 5700

Linux系统安装AutoDockTools、AutoGrid和AutoDock并实现分子对接(详细讲解)

linux系统为centos7.0 按照下面操作安装AutoDockTools(MGLTools) 1. 下载安装包,链接(https://ccsb.scripps.edu/mgltools/downloads/),我的linux系统是64位,下载红色标记源代码,拷贝入linux目标文件夹下。 2. shell终端进行安装: 1. 终端进入安装包所在文件夹,并获取root权限;赋予代码安装权限; cd /home/... #目标文件夹,根据目标程序文件位置进行更改 su #获

carlos_zhao的博客 1万+

SDIO—SDIO协议简介

SD卡(Secure Digital Memory Card)在我们生活中已经非常普遍了,控制器对SD卡进行读写通信操作一般有两种通信接口可选,一种是SPI接口,另外一种就是SDIO接口。SDIO全称是安全数字输入/输出接口,多媒体卡(MMC)、SD卡、SD I/O卡都有SDIO接口。STM32F103系列控制器有一个SDIO主机接口,它可以与MMC卡、SD卡、SD I/O卡以及CE-ATA设备进行数据传输。

qq_25218501的博客 9146

【低空经济】无人机充电站设计方案

随着无人机技术的快速发展和广泛应用,其在物流、农业、巡检、救援等领域的应用日益普及。然而,无人机的续航能力一直是限制其大规模应用的关键因素之一。为了解决这一问题,无人机充电站的设计与建设显得尤为重要。本项目旨在设计一套高效、智能、可扩展的无人机充电站系统,以满足不同场景下无人机的充电需求,提升其作业效率和应用范围。无人机充电站的设计将围绕以下几个核心目标展开:首先,充电站应具备快速充电能力,以减少无人机的停机时间,提高作业效率;

2959

我用 AI Agent 全自动跑 COMSOL 仿真:从建模到后处理,踩了 10+ 个深坑

本文探讨了利用AI通过COMSOL Java API实现AI芯片液冷冷板全流程自动化仿真的实践。针对700W高功耗AI芯片的散热需求,构建了包含4颗Chiplet和微通道冷板的三维液冷模型。通过严格设计的Prompt工程,AI Agent成功完成了从几何建模到结果验证的全过程,最终实现了芯片最高温度54°C的良好散热效果。文章重点分享了10个关键问题的解决经验,包括流体连通性验证、网格顺序控制、离散阶数选择、收敛判据优化等,并建立了包含流场/热场/网格独立性的三重验证体系。实践表明,AI可高效处理重复性工作

sjjsjjsjjsjjsjj的博客 965
上一篇: wifi详解(三)
下一篇: Linux内核bridge浅析
hellolwl
博客等级 码龄24年 16粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值