DSP——从入门到放弃系列2——PLL锁相环(持续更新)

1、概述   

        锁相环(Phase Locked Loop,PLL)是处理器的时钟源,控制着C6678处理器中C66x内核、各外围设备的时钟的时钟比、对准和选通功能。

2、功能描述

       

上图显示了PLL和PLL控制器的逻辑实现。PLL控制器提供通过软件可配置的分频器(PLLDIV1 至 PLLDIV16)来修改内部时钟输入信号,具有灵活性和便利性。PLL控制器还包含寄存器(PLLM和SECCTL),用于驱动PLL的PLLM(锁相环乘法器),输出分频和旁路逻辑。PLL 控制器生成的时钟被输出传递到 DSP 内核、外设和其他模块。

CLKIN:从外部晶体振荡器的输入信号(3.3V),CLKMODE0 = 1

注意: 主 PLL 控制寄存器可以被器件中的任何主设备访问。

倍频器的 PLLM[5:0]位被PLL控制器中的 PLLM 寄存器控制,PLLM[12:6]位被器件级 MAINPLLCTL0 寄存器控制。 输出除数和 PLL 旁路(Bypass)逻辑被 SECCTL 寄存器相应的域控制。

在 C6678 器件里,只有 PLLDIV2,PLLDIV5 和 PLLDIV8 是可编程的。

主PLL用于驱动内核、交叉开关网络(Swich Fabric)和大多数外围设备的时钟(除了 DDR3 和网络协处理器(PASS))。 主PLL的 PLL 控制器管理不同的时钟分频器。对准和同步。

主 PLL 的 PLL 控制器具有一些 SYSCLK 输出,每个 SYSCLK 具有 一个相应的分频器对 PLL 输出的时钟分频。

注意:除了在下面描述中明确提到可编程的 SYSCLK 外,其他时钟分频器不是可编程的。

SYSCLK1: 用于内核的全比例时钟

SYSCLK2: 1/ x 比例时钟,用于内核(仿真)。默认的比例是 1/3,这是可编程的,范围 从/1 到/32,该时钟最大不能超过 350MHz。

SYSCLK2 可以被软件关掉 SYSCLK3: 1/2 比例时钟,用于 MSMC 时钟、Hyperlink. CPU/2 SCR,DDR EMIF 和 CPU/2 EDMA.

SYSCLK4: 1/3 比例时钟,用于交又开关网络和高速外围设备。Debug_SS 和 ETBs 也 会使用这个时钟

SYSCLK5: 1/y 比例时钟,只用于系统追踪(System Trace)模块。默认比例是 1/5,可 以被配置,最大配置时钟是 210MHz最小配置时钟是 32MHz。SYSCLK5 可以被软件关掉

SYSCLK6: 1/64 比例时钟(emif_ptv),被用于驱动 DDR3 EMIF PVT 补偿缓冲

SYSCLK7: 1/6 比例时钟,用于慢速外围设备和资源的系统输出引脚

SYSCLK8: 1/z 比例时钟,该时钟被用作系统中的慢速系统时钟,默认的比例是 1/64, 可以被编程设置为/24~/80.

SYSCLK9: 1/12 比例时钟,用于 SmartReflex,

SYSCLK10: 1/3 比例时钟,只用于 SRIO。

SYSCLK11: 1/6 比例时钟,只用于 PSC. 

2.1 分频器

时钟分频器(PLLDIV1 至 PLLDIV16)的可编程范围从 ÷1 到 ÷256,并且可以被禁用。当一个时钟分频器被禁用时,该分频器不会输出任何时钟信号。只有在相应的 PLLDIV n 寄存器中启用分频器时,分频器才会输出时钟。

2.2 倍频器

PLL 控制器中的 PLLM 寄存器用于控制 PLL 的 PLLM 逻辑。

2.3 PLL 控制寄存器和次级控制寄存器


        设备复位后,PLL 控制寄存器(PLLCTL)中的 PLL 使能位(PLLEN)的值可以更改,但这不会对 PLL 控制器的功能产生任何影响。要使能 PLLEN 位,必须首先将 PLLCTL 寄存器中的 PLLENSRC 位清除为 0。一旦 PLLEN 位被使能,它就可以用来选择 PLL 控制器的旁路模式或 PLL 模式,如接下来的两节所讨论的。PLLCTL 中的 PLLRST 位用于重置 PLL 控制器。
次级控制寄存器(SECCTL)用于驱动 PLL 的输出分频和旁路逻辑。
根据 PLLCTL 和 SECCTL 寄存器中的 BYPASS、PLLENSRC 和 PLLEN 位的状态,PLL 可以在旁路模式或 PLL 模式下运行,这将在接下来的两节中讨论。

2.4 旁路模式

当BYPASS = 1(在PLL Mux中使能bypass)即处于旁路模式时,PLL的PLLM、PLLD和OUTPUT DIVIDE逻辑被旁路,PLL的输入参考时钟(CLKIN)直接输入到PLL控制器。PLL模块正在以旁路模式运行。
当PLLENSRC=0且PLLEN=0(在PLL控制器复用器中启用旁路)时,整个PLL模块将被旁路,PLL的参考输入被直接作为输入提供给PLL控制器。PLL控制器模块正在以旁路模式运行。

注意 :设备上电时,默认情况下PLL以旁路模式启动。 一旦PLL在PLL模式下初始化完成,除非用户打算关闭设备或重新编程PLL以达到更高的时钟频率,否则不应重新初始化回旁路模式。

 2.5 PLL模式

当BYPASS = 0(在PLL Mux中)即处于PLL模式时,PLL的PLLM、PLLD和OUTPUT DIVIDE逻辑被使用。PLL的输出(PLLOUT)被用作PLL控制器的输入。PLL模块正在以PLL模式运行。
当PLLENSRC=0且PLLEN=1(在PLL Controller mux中)时,PLL的输出(PLLOUT)被用作PLL控制器的输入。PLL控制器模块正在以PLL模式运行。
此外,当使能(DnEN = 1)时,系统时钟分频器(D1-D16)会根据PLLDIVn中的RATIO值对PLL的输出时钟进行分频。系统时钟分频器生成50%占空比的输出时钟SYSCLKn。     

3、主PLL初始化顺序

PLL和PLL控制器在复位后由软件初始化。PLL控制器寄存器应仅由CPU或仿真修改。外部主设备,例如PCIe,不应直接用于访问PLL控制器寄存器。应尽可能在程序开始时,初始化任何外设之前,执行PLL控制器的初始化。设备复位后,必须执行以下软件初始化程序,以正确设置PLL和PLL控制器:

1、位于Bootcfg空间的PLL配置寄存器(MAINPLLCTL0和MAINPLLCTL1)在上电时受到写保护。

2、软件在写入任何芯片级寄存器之前,必须先解锁KICK0和KICK1寄存器。软件在写入任何芯片级寄存器后,必须锁定KICK0和KICK1寄存器,以防止任何意外的更改。

3、用户在启用特定PLL之前,必须确保适用的电源域已启用。例如,在启用ARM PLL之前,必须启用ARM电源域。

3.1 PLL模式初始化


1. 如果在设备上电后立即执行此序列,必须允许时间让PLL稳定。PLL稳定时间为100μs。
2. 检查SECCTL寄存器中的BYPASS位的状态,如果BYPASS == 1(如果启用了旁路),请执行以下步骤;如果BYPASS == 0,则跳至步骤3
   (a) 在MAINPLLCTL1中,写ENSAT = 1(以获得最佳的PLL操作)
   (b) 在PLLCTL中,写PLLEN = 0(在PLL控制器复用器中启用旁路)
   (c) 在PLLCTL中,写PLLENSRC = 0(启用PLLEN控制PLL控制器复用器)
   (d) 等待参考时钟CLKIN的4个周期(以确保PLL控制器复用器正确切换到旁路)
   (e) 在SECCTL中,写BYPASS = 1(在PLL复用器中启用旁路)
   (f) 在PLLCTL中,写PLLPWRDN = 1(关闭PLL)
   (g) 根据参考时钟CLKIN至少等待5微秒(PLL关闭切换时间)
   (h) 在PLLCTL中,写PLLPWRDN = 0(开启PLL。跳至步骤4)
3. 在PLL控制器中启用BYPASS
   (a) 在PLLCTL中,写PLLEN = 0(在PLL控制器复用器中启用旁路)
   (b) 在PLLCTL中,写PLLENSRC = 0(启用PLLEN控制PLL控制器复用器)
   (c) 等待参考时钟CLKIN的4个周期(以确保PLL控制器复用器正确切换到旁路)
4. PLLM被分割在两个不同的寄存器中。在PLL乘数控制寄存器(PLLM)中设置PLLM[5:0],在MAINPLLCTL0寄存器中设置PLLM[12:6]
5. BWADJ被分割在两个不同的寄存器中。在MAINPLLCTL0中设置BWADJ[7:0],在MAINPLLCTL1中设置BWADJ[11:8]。BWADJ[11:0]应该根据方程式BWADJ = ((PLLM+1) >> 1)设置为与PLLM[12:0]值相关的值。
6. 在MAINPLLCTL0寄存器中设置PLLD
7. 在SECCTL中,写OD(输出分频)= 1(即分频为2)
8. 如有必要,设置PLLDIVn。如果PLL以前已经设置为PLL模式并且在此次初始化期间正在重新编程,则不要重新设置PLLDIVn的值。注意,您必须应用GO操作来将这些分频器更改为新的比例(见第3.2节)。
9. 在PLLCTL中,写PLLRST = 1(PLL复位被断言)
10. 根据参考时钟CLKIN至少等待7微秒(PLL复位时间)
11. 在PLLCTL中,写PLLRST = 0(PLL复位被取消断言)
12. 至少等待500 × CLKIN周期 × (PLLD + 1)(PLL锁定时间)
13. 在SECCTL中,写BYPASS = 0(启用PLL复用器切换到PLL模式)
14. 在PLLCTL中,写PLLEN = 1(启用PLL控制器复用器切换到PLL模式)
15. PLL和PLL控制器现在已在PLL模式下初始化。

注意:软件在对PLL中的任何寄存器进行操作时,必须始终执行读-修改-写操作。
这是为了确保只有寄存器中相关的位被修改,包括保留位在内的其余位不受影响。


设备上电时,默认情况下PLL处于旁路模式。一旦PLL在PLL模式下初始化完成,除非用户打算关闭设备或重新编程PLL以达到更高的时钟频率,否则不应重新初始化回旁路模式。

3.2 在PLL模式下重新编程主PLL

一些设备的拓扑结构限制了主电源可以承受的瞬态负载。这些用例可以通过分阶段地提高PLL频率来实现,以减少瞬态功率消耗。例如,可以首先将主PLL初始化为最终设备操作频率的一半,然后在短暂的时间后重新编程PLL到最终设备操作频率。

PLL的重新编程应该只在设备初始启动后的ROM引导加载程序(RBL)初始化期间进行。RBL使用启动模式引脚来确定如何首次编程PLL。如果希望RBL将PLL编程为设备数据手册中给出的选项以外的频率(例如操作频率的一半),可以通过使用启动模式引脚向RBL错误地表示输入时钟频率来实现。在RBL中,每个频率设置为了最小化系统和/或应用程序的影响,PLL的重新编程应该在RBL初始化之后进行——设备应该处于低功耗状态,其中外设应该被关闭,且没有执行应用程序级别的代码。PLL重新编程的顺序与上一节中介绍的顺序相同,只是PLLDIVn对于SYSCLKn的值不得重新编程。

4、分频器n(D1至Dn)和GO操作

4.1 GO操作

GO操作会写入PLLDIV n寄存器中的RATIO字段。寄存器不会立即改变分频器的分频比。只有在GO操作期间,PLLDIV n分频器才会改变为新的RATIO比率。

PLL控制器时钟对齐控制寄存器(ALNCTL)决定了哪些SYSCLKs需要对齐。在GO操作之前,设置ALNCTL以确保在GO操作期间适当地对齐时钟。

通过将PLLCMD中的GOSET位设置为1来启动GO操作。在GO操作期间:
- 如果ALNCTL中的相应ALN n位和DCHANGE中的SYS n位设置为1,则任何SYSCLK n在下降沿暂停。然后PLL控制器会同时重新启动所有这些SYSCLKs,并在上升沿对齐。当SYSCLKs重新启动时,SYSCLK n将以PLLDIV n中RATIO字段设置的速率切换。
- 如果ALNCTL中的相应ALN n位清除,并且DCHANGE中的SYS n位设置,则任何SYSCLK n会立即切换到RATIO字段中新设置的速率。
- PLLSTAT中的GOSTAT位在GO操作期间一直被设置。

注意:为防止错误,在执行GO操作之前,必须停止所有设备操作。

4.2 软件修改PLLDIVn Ratios的步骤

执行以下步骤修改PLLDIV n:
1. 检查PLLSTAT中的GOSTAT位是否已清除,以显示当前没有正在进行的GO操作。
2. 将PLLDIV n中的RATIO字段设置为所需的新分频率。如果RATIO字段改变,PLL控制器将在DCHANGE对应的位上标记这一变化。
3. 在ALNCTL中设置相应的ALN n位,以便在GO操作后对齐任何SYSCLKs。
4. 将PLLCMD中的GOSET位设置为启动GO操作,以改变分频值并按程序对齐SYSCLKs。
5. 读取PLLSTAT中的GOSTAT位,确保该位返回到0,表示GO操作已完成。

5、主PLL电源关闭

PLL可以被关闭电源,在这种情况下,PLL处于旁路模式,而DSP则从一个分频后的输入参考时钟运行。DSP能够响应事件,因为它仍然由旁路时钟(直接来自CLKIN)提供时钟信号,尽管频率较低。

执行以下程序关闭PLL电源:
1. 在SECCTL中,写入BYPASS = 1(旁路模式)。
2. 等待PLLOUT或CLKIN中较慢的一个的4个周期。
3. 在PLLCTL中,写入PLLPWRDN = 1以关闭PLL电源。

6、主PLL唤醒

执行以下程序来从电源关闭模式唤醒PLL:
1. 在SECCTL中,写入BYPASS = 1(旁路模式)。
2. 在PLLCTL中,写入PLLPWRDN = 0以唤醒PLL。
3. 按照第3.1.1节中的PLL复位序列(步骤3至9)来复位PLL。等待PLL锁定并从旁路模式切换到PLL模式。

7、DDR3 PLL初始化顺序

在初始化DDR3 PLL之前,必须先初始化主PLL和PLL控制器。必须按照以下顺序初始化DDR3 PLL:

1. 在DDR3PLLCTL1中,写ENSAT = 1(以获得最佳的PLL操作)。
2. 在DDR3PLLCTL0中,写BYPASS = 1(将PLL设置为旁路模式)。
3. 在DDR3PLLCTL0寄存器中设置PLLM和PLLD。
4. 在DDR3PLLCTL0中设置BWADJ[7:0],在DDR3PLLCTL1中设置BWADJ[11:8]。BWADJ[11:0]应该根据以下公式设置为与PLLM[12:0]值相关的值:BWADJ = ((PLLM+1) >> 1) - 1。
5. 在DDR3PLLCTL1中,写PLLRST = 1(PLL被断言)。
6. 根据参考时钟等待至少5微秒(PLL复位时间)。
7. 在DDR3PLLCTL1中,写PLLRST = 0(取消PLL复位)。
8. 等待至少500 × REFCLK周期 × (PLLD + 1)(PLL锁定时间)。
9. 在DDR3PLLCTL0中,写BYPASS = 0(切换到PLL模式)。
10. DDR PLL现在已初始化。

8、PASS PLL初始化顺序

在初始化PASS PLL之前,必须先初始化主PLL和PLL控制器。必须按照以下顺序初始化PASS PLL:

1. 在PASSPLLCTL1中,写ENSAT = 1(以获得最佳的PLL操作)。
2. 在PASSPLLCTL0中,写BYPASS = 1(将PLL设置为旁路模式)。
3. 在PASSPLLCTL0寄存器中设置PLLM和PLLD。
4. 在PASSPLLCTL0中设置BWADJ[7:0],在PASSPLLCTL1中设置BWADJ[11:8]。BWADJ[11:0]应该根据以下公式设置为与PLLM[12:0]值相关的值:BWADJ = ((PLLM+1) >> 1) - 1。
5. 在PASSPLLCTL1中,写PLLRST = 1(PLL被断言)。
6. 根据参考时钟等待至少5微秒(PLL复位时间)。
7. 在PASSPLLCTL1中,写PLLSELECT = 1(选择PASS PLL的输出作为PASS的输入)。
8. 在PASSPLLCTL1中,写PLLRST = 0(取消PLL复位)。
9. 等待至少500 × REFCLK周期 × (PLLD + 1)(PLL锁定时间)。
10. 在PASSPLLCTL0中,写BYPASS = 0(切换到PLL模式)。
11. PASS PLL现在已初始化。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于glibc-all-in-one下载libc2.35以上报错问题

./download libc版本 下载2.35时报错:原因是缺少解压工具zstd sudo apt-get install zstd 下载后重新输命令就可以了 附加xclibc命令 xclibc -x ./pwn ./libc-版本 ldd pwn文件 xclibc -c libc版本

Git记录 上传至Gitee

1.GitHub拉去的代码需要上传至自己的Gitee需要清除原有remote服务器信息 查看原始远程服务器信息,后删除远程服务器信息 git remote -v git remote rm origin 2.Gitee新建软件仓库 法1)不用初始化仓库,初始化会自动生成.git。如果本地.git…

【第18章】Vue实战篇之登录界面

文章目录 前言一、数据绑定1. 数据绑定2. 数据清空 二、表单校验1. 代码2. 展示 三、登录1.登录按钮2.user.js3. login 四、展示总结 前言 上一章完成用户注册&#xff0c;这一章主要做用户登录。 一、数据绑定 登录和注册使用相同的数据绑定 1. 数据绑定 <!-- 登录表单 -…

Postman接口测试之postman设置接口关联,实现参数化

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 postman设置接口关联 在实际的接口测试中&#xff0c;后一个接口经常需要用到前一个接口返回的结…

【C#上位机应用开发实战】—— UI界面设计与实践代码

在C#上位机应用开发中&#xff0c;UI界面设计是至关重要的一环。一个好的UI设计不仅可以提升应用的用户体验&#xff0c;还可以提高应用的易用性和效率。本文将介绍一些UI界面设计的实战经验和技巧。 在这个示例中&#xff0c;我们创建了一个名为MainForm的窗体类。该窗体包含了…

Table 布局的妙用 - 多行联动布局

1. 前言 最近产品需求遇到一个布局的问题&#xff0c; 大致是两列&#xff0c; 两行的关系&#xff0c; 左侧的文案区域的高度根据右侧内容的高度自动撑满&#xff0c; 左侧文案的宽度根据左侧单元格的最大宽度来适配&#xff0c; 大致如下&#xff1a; 我们通过一般用DIVCSS的…

短剧APP开发,探索短剧市场的新机遇

近几年&#xff0c;短剧市场得到了繁荣发展&#xff0c;随着短剧的快速发展&#xff0c;短剧APP也得到发展&#xff0c;受到了越来越多用户的喜欢。通过短剧APP&#xff0c;为大众带来多样、高质量的短剧内容。对于影视创作者来说&#xff0c;短剧APP在线观看系统的开发也将成为…

Tuple 元组

文章目录 一、什么是元组 &#xff1f;二、元组的具体操作2.1 创建元组2.1.1 tuple() 创建元组函数和 list() 创建列表函数总结 2.2 元组的元素访问操作2.3 元组的元素计数操作2.4 zip 对象 一、什么是元组 &#xff1f; 列表属于可变序列,可以任意修改列表中的元素。 元组的…

5G+北斗高精度定位终端技术,赋能千行百业应用

5G北斗高精度定位终端技术的融合&#xff0c;正以前所未有的精准度和实时性&#xff0c;为千行百业带来革命性的变革。从智慧城市的精细化管理&#xff0c;到智能交通的实时调度&#xff0c;再到精准农业的播种与收割&#xff0c;这一技术正不断拓宽其应用领域&#xff0c;为各…

【Linux】自定义shell(命令行解释器)

原理&#xff1a; shell是命令行解释器&#xff0c;当有命令需要执行时&#xff0c;shell创建子进程&#xff0c;让子进程执行命令&#xff0c;而shell只需等待子进程退出即可。 其中我们使用了下面这几个函数&#xff1a; 获取命令行&#xff08;fgets函数&#xff09;。解析…

C++ 66 之 类模版

#include <iostream> #include <string> using namespace std;// 习惯性 < >中 类模板用class 普通的函数模板就用typename // template<class NAMETYPE, class AGETYPE> template<class NAMETYPE, class AGETYPE int> // 可以设置默认的类型值…

Beyond Compare 文件对比工具下载2024最新版-Beyond Compare详细安装步骤

Beyond Compare是一款不可多得的专业级的文件夹和文件对比工具。使用它可以很方便地对比出两个文件夹或者文件的不同之处&#xff0c;相差的每一个字节用颜色加以表示&#xff0c;查看方便&#xff0c;支持多种规则对比。是程序工程师以及上班族必备的有效辅助工具 安 装 包 获…

并发编程理论基础——解决死锁【等待-通知机制优化循环等待】(五)

在破坏占用且等待条件时&#xff0c;如果使用while死循环 在并发量不大的情况下循环几十上百次也就好了如果while中执行方法时间比较长&#xff0c;或者并发量大时&#xff0c;可能要循环上万次才能获取到锁&#xff0c;非常消耗CPU 相较于使用while死循环&#xff0c;更好的方…

位图法-有效的数独

有效的数独&#xff0c;主要是判断每行每列每宫有无重复元素。 每行每列用二重循环&#xff0c;每宫比较复杂&#xff0c;需要考虑每一宫的坐标与二重循环ij对应关系 行i&#xff0c;每一宫3行&#xff0c;3列 x3*(i/3)j/3 y3*(i%3)j%3

超简洁的待办事项自托管便签todo

什么是todo todo 是一个自托管的 todo web 应用程序&#xff0c;可让您以简单且最少的方式跟踪您的 todo。 搭建 使用Docker命令行方式进行搭建 docker run -d -p 8000:8000 -v todo_db:/usr/local/go/src/todo/todo.db prologic/todo Docker-compose.yml version: 3 ​ se…

全球首个开源类Sora模型大升级,16秒720p画质电影感爆棚!代码和权重全面开源!

目录 01 视频界开源战士 02 深度解码技术 03 打破闭环&#xff0c;开源赋能 潞晨Open-Sora团队刚刚在720p高清文生视频质量和生成时长上实现了突破性进展&#xff01; 全新升级的Open-Sora不仅支持无缝生成任意风格的高质量短片&#xff0c;更令人惊喜的是&#xff0c;团队选…

BC153 [NOIP2010]数字统计

数字统计 一.题目描述二.输入描述&#xff1a;三.输出描述&#xff1a;四.数字范围五.题目思路六.代码实现 一.题目描述 请统计某个给定范围[L, R]的所有整数中&#xff0c;数字2出现的次数。 比如给定范围[2, 22]&#xff0c;数字2在数2中出现了1次&#xff0c;在数12中出现1次…

VM4.3 二次开发04 方案输出结果设置

方案输出结果设置&#xff0c;这个设置是为了在二次开发的上位机软件中显示我们想要的数据&#xff0c;和在二开中如何获取这些结果。 打开方案点下如中的图标。 打开如下图。 再点点红色圈出来的图标&#xff0c;打开参数设置界面。 输出设置可以要输出的数据和参数名称。点上…

基于YOLOv10深度学习的高密度人脸智能检测与统计系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Java23种设计模式(二)

1、单例模式 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有…