打印
[信息]

STM32L5 入门课程系列(三) TrustZone环境下新的用户编程模型

[复制链接]
1516|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
powerantone|  楼主 | 2023-11-27 15:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

欢迎大家继续关注STM32L5入门课程(三):Trustzone环境下新的用户编程模型。


通过上一期的介绍,大家应该理解了STM32L5是如何把“隔离”的概念和措施,从内核延伸出来,部署到全片系统。这一期,我们结合一个具体的GPIO trustzone例程,对前两期介绍的知识点,理论结合实际来深入体会一下。




GPIO TrustZone


我们要运行和分析的第一个STM32L5上的trustzone例程是GPIO toggle。它位于STM32CubeL5固件包里,Nucleo板子下、pre-build好的GPIO例程目录下。


从这个最基本的简单例程,我们可以体会,在前面讲到过的TZ软件开发模型。即一个工程空间里,至少包含两个工程项目,一个运行在安全世界,一个运行在非安全世界。它们有各自的源文件,包括应用文件,中断处理函数it.c文件,各自的linker链接文件。至于启动汇编文件startup.s,里面是中断向量表,和Reset handler,可以两个工程复用,因为在向量表和reset处理上,这个例程没有什么区别。如果实际应用中,需要有不同的reset处理,可以分开两个启动汇编文件。


我们借用这个最基本的trustzone例程来体会:一个基于TrustZone平台的项目,从安全世界启动,初始化和配置系统安全属性,切换到非安全世界运行,再调用安全世界代码的过程。






到工程目录下,我们以IAR为例,打开GPIO IOToggle TrustZone工程空间文件:project.eww

工程空间由上、下两个项目组成,项目名称分别是_S和_NS的尾缀。

>> 安全世界的工程包含的C文件,对应文件夹Secure中的src目录下所有C文件

>> 非安全世界的工程包含的C文件,对应文件夹NonSecure中的src目录下所有C文件

这些文件,熟悉STM32的开发者都不会陌生,除了一个文件,可能是在ST的例程第一次看到,就是在Secure文件夹的Src目录下的,secure_nsc.c。NSC就是前面讲的non secure callerble的意思。顾名思义,大家可以猜到,那些安全世界准备暴露出来给非安全世界调用的函数,就在这个文件里定义。安全项目编译链接后,会在Secure_nsclib文件夹下,生成secure_nsclib.o。该库文件和对应的头文件,会被包含到非安全世界的项目中。这样,非安全世界,才知道有哪些安全世界的API可以供他们调用。


在进一步分析项目结构和实现细节之前,现在我们先把例程跑起来~




首先,我们通过选项字节对芯片做初始化。我们使用STM32CubeProgrammer来把STM32L5的选项字节做如下配置:TZEN和DBANK都置1。然后把L5的片上512K flash的前半部分设置成安全区域,把后半部分设置成非安全区域。


如果你手上的Nucleo-L5板子,之前没有设置过TZ,就是说,在User Configuration的Tab里,TZEN没有被checked,你是看不到后面和User Configuration Tab并列的Secure Area 1和2的tab的。所以你要先把TZEN打上勾,同时DBANK也打上勾,然后点击Apply。先把TZEN给apply到系统里。然后第二次连接,就可以看到Secure Area1和2个Tab了。


如果你之前TZEN是使能了的,也在Secure Area的Tab里做过设置,而DBANK是没有使能的。这种情况下,去设置DBANK是无法成功的,需要先把secure memory或者HDP区域都disable掉,然后才能改变DBANK的设置。


芯片的选项字节配成我这个样子:TZEN、DBANK都是1;Secure Area1里,安全区域,从page编号0,到page编号0x7F,共128个page,256K字节,即整个bank1。后面256K字节,即bank2,设置成不安全区域,因此只要把安全范围起始地址设置成大于结束地址即可。


接下来,我们对工程空间里的 两个项目,分别进行编译和下载。注意,要先编译安全项目,然后再编译非安全项目。

先编译安全世界的工程。先不要问为什么,就照做,后面会讲为什么。


再编译非安全世界的工程。如果你实在想知道,可以试一试先编译非安全世界的工程。


好,两个项目都编译链接成功。接下来我们烧录两个项目的image,由于是烧录到不同的地址空间,因此烧写的顺序没有特别的要求。我习惯先烧NS的项目,使用Download  download active来下载;然后切换到S项目,同样使用Download -> download active来下载。然后按下板子的复位键,可以看到:黄灯和蓝灯,以不同的频率在闪烁。


大家可能觉得这是一个平淡无奇的例程演示,就是两个LED闪烁,但是它是基于TrustZone,和以往的LED闪烁的工程完全不一样。接下来,我们就庖丁解牛,把背后的从原理到实现,都一一梳理一遍




原理和实现


首先面对的第一个问题是,在这个GPIO闪烁的例程中,安全世界和非安全世界是如何划分的?

第一个问题中的第一个问题,片上512K用户flash和256K ram,是如何划分Secure区域,NSC区域,以及NS区域?


上一期讲L5片上系统对隔离的实现时,我们知道CPU的视角,看谁安全看谁不安全,是有IDAU和SAU决定。刚刚复位时,SAU的寄存器复位值,使得CPU看出去,整个4G地址空间都是安全的,因此无论IDAU的实现是如何划分,经过IDAU和SAU二者共同定义的结果,就是整个4G空间都是安全的。


但是IDAU还有一个非常重要的作用,上一期讲了,就是给Code区、SRAM区、Peripheral区,定义了别名,严格讲是定义了“别名地址空间”。这里的Code、SRAM、Peripheral区,不是芯片厂家实现的512K flash,256K ram的区域,而是ARM定义的memory map里的大区域。即图中最左边一栏,Code区域是0x0到0x1FFF,FFFF,整个512M空间;SRAM是0x2000 0000开始,到0x4000 0000的512M空间;Peripheral是接下去0x4000 0000到0x6000 0000的512M空间。


别名地址空间,大家其实不是第一次在ARM Cortex-M芯片里碰到了。以前CortexM3的时候,SRAM区域,和外设区域的bit-banding就是使用别名地址,别名地址空间的一个word,对应实际空间的一个bit,从而方便的对位进行操作。

这里的IDAU别名也一样,但不是一个bit对应一个word,而是一一对应。


IDAU对Code区域,0x0800 0000开始的64M空间,定义了别名区对应0x0C00 0000开始的64M空间。意思就是说,从0x0800 0000去访问一个字节,和从0x0C00 0000去访问的一个字节,物理上都是我们512K 片上flash的第一个字节。CPU去访问0x0800 0000的时候,从SAU/IDAU看来,它是去访问不安全的区域,此时无论CPU本身的状态是安全还是不安全的,SAU/IDAU都会被这条transaction降级成非安全的transaction。但是,如果CPU去访问0x0C00 0000的时候,从SAU/IDAU看来,它就是去访问安全区域。那么如果是指令访问,无论此时CPU的安全状态,SAU/IDAU都会放行这条访问,并且标志该transaction是安全的transaction。如果是数据访问,如果此时CPU处于非安全状态,那么SAU/IDAU认为它要去访问一个安全区域的数据,就会block掉这条访问企图。大家可以再回过头,看一下上一期结束时三个图解,展示的CPU访问规则。






CPU怎么看,是由IDAU以及上电后可配置的SAU决定的。


实际物理的512M片上flash,哪些区域是安全,哪些是不安全的,由flash controller来配置,因为flash memory是TZ aware的外设。我们刚才在做准备工作的时候,通过选项字节,把512Kflash的前半部分,即bank1配置成安全的,后半部分,bank2配置成非安全的。


对于取指访问,第一级检查,SAU/IDAU都会放行,出来的transaction安全性取决于SAU/IDAU看到的区域的安全性。为了CPU的视角看出去的目标地址的安全性,和物理设备实际配置的安全性一致,对低256K空间里的安全flash访问,CPU应该走0x0c000 0000开始的地址;对高256K空间里的非安全flash访问,CPU应该走0x0800 0000开始的地址。即0x0804,0000。


我们看一下两个项目的linker文件,是如何规定自己的工程项目,代码区域的地址范围。

主要关心三个区域,intvec、ROM_region、RAM_region

>> 我们把两个linker文件里,两个项目各自关键的三个区域的地址范围,放在这个表格里。

>> 像刚才说的,安全世界的代码,放在实际地址0开始的地方,而CPU要从0x0C00 0000去寻址,方能和flash自身这部分区域的安全属性匹配得上。就是0x0C00 0000开始的256K空间,从0x0C00 0000到0x0C03 FFFF。

>> 非安全世界的代码,放在实际地址0x4 0000开始的地方,CPU要从0x0800 0000去寻址,才能和这块不安全区域的属性一致,因此是非安全项目,ROM区域的范围是0x0804 0000开始的256K空间,到0x0807 FFFF结束。


安全区域,需要预留一小部分,作为NSC区域,这里例子,使用了安全世界里最后8K空间。


而SRAM,也是划分了两部分,从偏移地址0到0x1 7FFF,即SRAM的低96K空间,作为安全区域,分配给安全世界的工程,放置堆栈;而剩下160K的高偏移量空间,留给非安全世界的项目使用。


使用特权

评论回复
沙发
powerantone|  楼主 | 2023-11-27 15:35 | 只看该作者



我们来看运行时不同阶段,CPU对不同区域的访问情形。同样一个物理地址,在不同时候,CPU使用不同的别名地址去访问,看到的情形是不一样的。这个完全是TrustZone平台特有的现象,大家在以前传统STM32平台上调试,从未碰到过的情况。


首先,芯片刚刚复位时,程序还没有跑起来。这个时候IDAU作为静态配置,已经生效;而SAU的作用效果,取决于它的寄存器复位值。那么此时,从内核角度看出来,所有的4G地址空间都是安全的,包括所有的flash区域,RAM区域。


>>在刚刚复位时,选项字节对flash区域的安全属性配置也生效了:低256K是安全的,高256K是不安全的。一个物理区域,在IDAU的作用下,还有它的别名区,因此我们看到这里两条绿色的,两条红色。两条绿色的,是同一块flash区域的两个地址空间,红色的也是一个意思。

>> RAM区域的安全配置,也是由寄存器控制,来自GTZC模块的MPCBB,它的复位状态,是所有SRAM区域都是安全的。


表格里最后一列,是前面看的GPIO toggle两个工程各自linker文件里指定的代码区域,绿色字体是安全项目里定义的区域;红色字体是非安全项目定义的区域。其中,粗体字,是各自的linker文件里直接指明的地址,而对应的斜体字,是它的别名区域。比如说,0x0c00,0000到0x0c03,0000的256K空间,是在安全工程里定义的放置安全工程向量表,代码,以及供非安全世界调用的代码API所在区域。和它同享一块物理地址的,0x0800 0000到0x0803,0000地址空间,按照以往的经验,看到的应该是同样的内容





我们来看运行时不同阶段,CPU对不同区域的访问情形。同样一个物理地址,在不同时候,CPU使用不同的别名地址去访问,看到的情形是不一样的。这个完全是TrustZone平台特有的现象,大家在以前传统STM32平台上调试,从未碰到过的情况。


首先,芯片刚刚复位时,程序还没有跑起来。这个时候IDAU作为静态配置,已经生效;而SAU的作用效果,取决于它的寄存器复位值。那么此时,从内核角度看出来,所有的4G地址空间都是安全的,包括所有的flash区域,RAM区域。


>>在刚刚复位时,选项字节对flash区域的安全属性配置也生效了:低256K是安全的,高256K是不安全的。一个物理区域,在IDAU的作用下,还有它的别名区,因此我们看到这里两条绿色的,两条红色。两条绿色的,是同一块flash区域的两个地址空间,红色的也是一个意思。

>> RAM区域的安全配置,也是由寄存器控制,来自GTZC模块的MPCBB,它的复位状态,是所有SRAM区域都是安全的。


表格里最后一列,是前面看的GPIO toggle两个工程各自linker文件里指定的代码区域,绿色字体是安全项目里定义的区域;红色字体是非安全项目定义的区域。其中,粗体字,是各自的linker文件里直接指明的地址,而对应的斜体字,是它的别名区域。比如说,0x0c00,0000到0x0c03,0000的256K空间,是在安全工程里定义的放置安全工程向量表,代码,以及供非安全世界调用的代码API所在区域。和它同享一块物理地址的,0x0800 0000到0x0803,0000地址空间,按照以往的经验,看到的应该是同样的内容





我们实际来看一下:在刚才的GPIO toggle工程空间里,把安全工程,设置为active project,然后用IAR连接一下,在复位后停下来,看看flash高地址和低地址两块区域,在各自默认的地址空间,和对应的别名空间,CPU看到的情况。


可以看到,0800和0c00,内容都一样,就是安全工程的代码(看一下右边汇编窗口里的地址);寄存器SP和PC,就是从安全工程的向量表里取出来的两个值。而0804,0c04看到的就全部是0。为什么会这样呢?不是说好,既然别名空间,都是同一块物理地址吗?


原因就是,上一集讲到的,使能了TrustZone安全扩展的STM32L5上,CPU数据访问的访问规则。

第一,我们通过调试器去看,相当于CPU当前处于安全状态;

第二,我们去看memory窗口,汇编窗口,属于数据访问。


因此,无论我们要看哪里的内容,transaction都是S的;而Flash自身的配置,如果和transaction属性不一致,就不会访问成功。因此只有和transaction同为绿色的flash的区域,才能看到内容。






我们接着往下运行,当代码开始运行起来,配置了SAU后,从CPU看出去的区域,安全属性有了变化。它在4G地址空间默认的安全区域里,分别在Flash和SRAM挖出了两块非安全区域,这是给非安全工程放代码和堆栈的地方,然后在安全区域里还额外设置了一小块NSC区域。这样CPU的视角看我们的flash就和刚才不一样了。再结合flash自身的安全设置,可以想象,第一行,绿色对绿色,属性匹配,可以访问成功;第二行,红色对红色,属性匹配,也可以访问成功;第三行,同样绿色对绿色,属性匹配,可以访问成功;第四行,绿色对红色,属性不匹配,应该看不到内容。


SRAM的四个区域,也是一样的。





我们单步运行程序,在执行完SAU_Setup之后停下来,看一下flash的四个区域,和sram的四个区域,验证一下刚才的判断。

flash的四个区域,前三个都符合访问规则了,因此前三个地址看出去,都能看到内容。





SRAM区域本身的设置,要代码运行到安全工程里,调用GTZC的MPC配置后才能完成。也是配置低地址96K是安全的,给安全工程用于堆栈空间;高160K是不安全的,给非安全工程用于堆栈空间。配置好之后,可以想象,RAM区域,前三行的地址都可以正确读出内容。我们来验证一下:





单步运行程序,或者直接把断点打在安全工程main.c的main函数里,GTZC_init函数之后,然后运行到断点停下来。

RAM的前三个地址空间,符合trustzone的访问规则,可以看到正确内容。




使用特权

评论回复
板凳
powerantone|  楼主 | 2023-11-27 15:46 | 只看该作者



现在,我们按照程序的运行顺序,理一下运行逻辑。系统复位后,从Secure的工程开始运行。复位时,CPU看出去,看到全部flash和sram都是安全区域。CPU处于安全状态。


【1】开始执行初始化任务;

【2】首先设置SAU,重塑CPU的世界观,不是所有区域都是安全的,0x0804开始的256K是非安全的,那里应该放非安全工程的代码;0x2001 8000开始的96K是非安全的,那里应该放非安全工程的堆栈。

【3】选项字节的配置让物理Flash的下半部分,具有非安全属性,和CPU视角一致;代码执行,让SRAM的后半部

【4】分配到非安全世界;GPIO

【5】本来都是默认安全的,代码仅保留PC.7是安全的,驱动LED1,其他GPIO引进都分到非安全世界去,其中PB.7驱动LED2。

【6】默认所有中断发生后,都是target到安全世界,即去安全世界里查阅中断向量表,取出中断ISR地址,如果需要,可以把某些中断retarget到非安全世界里。retarget的操作,只能在安全世界执行。

【7】CM33内核有两个systick,在S和NS世界独立运行,中断也是各有一个。现在先使能安全世界的systick,产生1ms定时。

【8】使能GTZC中断,这个中断线,默认是target在安全世界的。

【9】最后安全世界的初始化全部完成,跳到非安全世界执行。





和以前一样,复位向量ResetHandler里先执行SysteInit。


TZ_SAU_Setup是SystemInit里新增的一个操作。它作为内联函数,在《partition_stm32l552xx.h》中实现。主要有四部分功能组成:


首先是设置SAU区域。本来SAU默认是4G地址空间都是安全的,用户需要在这里根据应用,至少挖出3个区域来重新设置,就像这个例程里面,两个NS区域,分别给非安全工程的代码和堆栈,一个NSC给安全工程的被外调用的函数入口。如果要修改的话,不是改函数体里面,在这个样本实现里,拉到文件的最上面,在这里修改宏定义,region起始地址,结尾地址,region的属性。默认不改就是S,0就是NS,1就是NSC。


第二部分,设置系统控制快SCB里和低功耗,中断相关的属性。内核的低功耗,复位,是仅能被安全代码使能,还是安全/非安全代码都可以。还包括上上集讲内核时,提到的是否要把retarget到安全世界的中断向量,优先级都集体抬高,是否要把Bus fault,NMI异常retarget到非安全世界,同时把HardFault优先级提到比NMI异常的优先级还高。在这个gpio toggle例程里,我们都没有用到这些属性,因此都是使用默认设置。


第三部分是关于FPU浮点单元的设置,我们这个gpio toggle例程中没有用到浮点,暂时不去管它,使用默认设置。


第四部分,很重要,如果用户想把某些中断retarget到非安全世界,就在这里配置。改这四个value中的一个或某个。当然如果不在这里修改,也可以后面使用NVIC的API修改,但是一定要是在安全世界里才能执行。这个gpio toggle例程里也没有用到这个功能,但是下一集,我们会用到它。





继续安全项目里的安全属性初始化。GTZC模块,可以配置内容SRAM,外部flash,AHB,APB外设的安全属性。这个例子,我们是配置SRAM的前96K部分为安全,后160K部分为非安全。使用相同的HAL层API:GTZC_MPCBB_ConfigMem,配置区域由第一个参数里指明,SRAM1和SRAM2。其实,根据这个函数的名字,大家可能已经猜到,它是由STM32CubeMX自动生成的,我们确实可以通过CUbeMX在图形界面里配置,下一集我们会演示这个功能。


接下来,在GPIO配置里,更改PB.7原来的安全属性,从安全配置成不安全,它将被非安全工程代码控制,去翻转LED2的亮灭,




这不是一条普通的函数指针,因为有了CMSE_NS_CALL关键字的加持,编译器才会有。


第二大段之前,先看一下IAR窗口,调试一下,看汇编;


>> 执行BLXNS之前 vs. 之后,寄存器上下文


编译器产生的汇编语句,把general register都清零,只有R4有值,但是包含的是NS世界的信息;SP是当前S世界的堆栈,LR此时是调用返回后S世界下一句的地址。R4还是刚才的值,未变;SP自动切换到NS世界的堆栈;LR被硬件刷成0xF,都未暴露S世界的信息







现在,我们跳到非安全世界开始执行了,通过刚才看到的“CMSE_NS_CALL”这个关键字修饰的函数指针,以绝对地址调用的方式跳了过来。先跳到的是非安全工程的向量表里reset handler entry里包含的地址,执行最开始的初始化,结构和安全工程里差不多,也是调用SystemInit,只是这里的SystemInit没有做太多事情,直接跳到非安全工程的main函数里。


在main函数一来,就是调用安全世界的代码。这是怎么实现的呢?

【1】首先安全世界要先定义一些可供非安全世界调用的API,

【2】然后把它的入口放在安全世界里的NSC区域。当然这些都是编译器帮你去做的,只要在定义这些对外函数时,使用编译器的一些关键字。

【3】NS的代码,先跳到NSC区域,执行第一条安全指令SG,把CPU切换到安全状态,然后就可以执行紧随SG指令后面的,跳转到真正安全函数定义的跳转指令了。当然这些也都是编译器会拆解成合适的指令来实现。


可以看到,NS世界调用S的代码时,是知道API函数名字的,不是通过指向绝对地址的指针来调用。


那么NS世界是如何知道它可以调用的S世界的函数名字的呢?








同样也是通过编译器以及IDE的帮忙。


安全项目里有一个特殊的C文件,secure_nsc.c,里面定义了Secure_registerCallback;这个函数在定义时,使用了编译器关键字“CMSE_NS_ENTRY”,那么链接器会把该函数的入口地址连同SG指令,一起放到安全工程定义的NSC区域。同时,在安全项目里,指定把secure_nsc.c生成库文件secure_nsc.o,然后导入到非安全世界里。非安全世界再把secure_nsc.h头文件包含到项目里,它就知道自己可以调用哪些安全世界暴露出来的函数API接口了。






我们来看一下运行时代码是如何从非安全世界,跳到安全世界的。注意观察:跳过去时,编译器做了哪些安排?跳回来时,编译器做了哪些事情。


观察点:简单的是:NS世界的通用寄存器,LR,都带了过去;复杂的是:跳转几次,

NS的起点,先到NS的veneer;再到S的NSC区域//SG,再到S的函数实际地方。执行完成后,返回到NS:相同的是要清零用到的通用寄存器(这里是R0、R1、R2),由于NS的LR还有效,直接BXNS LR,即可返回。


小结一下,函数调用引起的从NS跳到S过程中,编译器无需做现场清零工作,共享的通用寄存器内容可以带过去。进入安全世界执行的第一条指令,一定是SG,而且该指令一定是在NSC区域中。


从S世界返回到NS世界,编译器会产生指令来清零现场,以确保安全世界里执行的上下文,不会泄露到非安全世界,最后通过BXNS指令跳转回来。




我们来看一下NS工程的业务逻辑。首先一来,它通过安全世界API的Secure_RegisterCallback,把SecureFault_Callback和SecureError_Callback注册到安全世界里。这两个函数,实际是定义在非安全世界里的。这样当系统异常SecureFault,或者用户中断GTZC发生时,由于全部默认是target到安全世界的,因此会到安全工程里的it.c里,执行对应的ISR。由于注册了非安全世界的异常和错误处理函数,安全中断ISR中,可通过函数指针直接调用这些定义在非安全世界的回调函数。





接下去,非安全工程的初始化还包括:使能NS世界里的systick,也是产生1ms定时;配置GPIO的PB.7,驱动LED2;使能Cache。这个Cache也是属于Securable的外设,默认处于非安全状态,如果想把它配置成安全状态的外设,需要在安全工程的初始化那里,和配置SRAM的安全和非安全区域一样,通过GTZC来配置。





借这个GPIO toggle的例子,我们体会一下上上集介绍CM33内核时,关于异常和中断的retarget概念。

胶片中,左边这个表格,就是来自上上集的课件。系统异常里,有些是铁定target在安全世界的,比如绿色原点标志的Reset/HardFautl/SecureFault;有些异常,是两边各有一套,也很好理解,比如Systick异常,systick本身就是在安全世界和非安全世界各有一个硬件,一旦被使能后,就各自运行起来,到达各自配置的reload值,会触发各自systick的溢出中断。没有道理说,安全世界的systick倒计时到了,触发的中断去非安全世界处理。因此,systick的异常是各有一套。还有一些异常,和用户中断一样,不是banked的,而是通过寄存器来配置,要么target在安全世界,要么target到非安全世界。这些寄存器复位值都是0,意味着所有的可retarget的异常和中断,都是默认在安全世界去处理。结合gpio这个例程,一共根据应用定制实现了3个ISR,其中2个是systick,一个是SecureFault。我们去看看两个工程下各自的it.c。


NS的it.c,只实现了banked的那5个ISR;

关于这个基于TrustZone技术的gpio toggle的例程,就讲解完毕。我们从现成的例程空间讲起,先编译连接,然后下载,体会了TZ应用由两个工程组成。然后按照启动,运行的时间顺序,分别解析了从安全工程开始的初始化,配置,到非安全工程的业务运行,在此过程中,体会了两个世界是如何互相调用另一个世界的代码。


下一期,我设计了一个更加完备的小例程,一方面,我们会从CubeMX入手开始配置,体会CubeMX是如何支持TZ应用的;另一方面,它会覆盖前两集讲到的所有重点的理论知识,比这个gpio toggle的小例子更全面一些。敬请大家持续关注。谢谢观看。



使用特权

评论回复
地板
Uriah| | 2024-7-21 07:31 | 只看该作者

环氧树脂由于硬度的原因不能用于应力敏感和含有贴片元件的模块灌封,在模块电源中基本被淘汰

使用特权

评论回复
5
帛灿灿| | 2024-7-21 09:27 | 只看该作者

产生一个充电放电的过程

使用特权

评论回复
6
Bblythe| | 2024-7-21 10:30 | 只看该作者

齐纳二极管作为ESD保护与单向TVS原理相同

使用特权

评论回复
7
周半梅| | 2024-7-21 12:26 | 只看该作者

之所以称为ESD静电保护器

使用特权

评论回复
8
Pulitzer| | 2024-7-21 13:29 | 只看该作者

钳位二极管最常用于集成电路中

使用特权

评论回复
9
童雨竹| | 2024-7-21 15:25 | 只看该作者

它迅速由高阻态变为低阻态

使用特权

评论回复
10
Wordsworth| | 2024-7-21 16:28 | 只看该作者

减少反射,避免振荡,方便调试

使用特权

评论回复
11
Clyde011| | 2024-7-21 17:31 | 只看该作者

大于1的定义为极高导热的性能,而对于模块电源此水平的导热系数是无法达到其散热功能的需求

使用特权

评论回复
12
公羊子丹| | 2024-7-21 18:24 | 只看该作者

得到正常工作状态下的输出电压和电流。

使用特权

评论回复
13
万图| | 2024-7-21 19:27 | 只看该作者

在电路中有部分电子元器件比较“脆弱”

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

567

主题

2517

帖子

4

粉丝