TC33x/TC32x 【SCU 配置】

发布时间:2026/7/28 22:17:26
TC33x/TC32x 【SCU 配置】 引言在英飞凌 AURIX™ TC33x/TC32x 系列 MCU(以 TC333 为例)中,SCU(System Control Unit,系统控制单元)是芯片的 “管家”,负责管理核心资源:时钟、电源、安全看门狗、外设使能等。其中,系统时钟配置是 SCU 的核心功能之一 —— 芯片的 CPU 主频、外设工作频率、中断定时器精度均依赖于正确的时钟配置,配置错误可能导致系统死机、外设异常或性能不达标。CCU和CLC的区别维度CCU(Clock Control Unit)CLC(Clock Control Logic)管理范围全局(整个芯片的时钟架构)局部(单个或一类外设的时钟)核心作用时钟源选择、PLL 配置、主时钟生成与分配外设时钟使能 / 禁用、局部分频 / 滤波依赖关系不依赖其他时钟控制模块,是时钟源头管理者依赖 CCU 提供的基础时钟,在此基础上做局部控制寄存器特点寄存器数量少但功能复杂(如 PLL 配置、主时钟选择)每个外设可能有独立的 CLC 寄存器(如UART_CLC、SPI_CLC)一、先搞懂 TC333 的时钟架构基础时钟流:时钟源→PLL 倍频→CCU时钟分配→CPU/外设/定时器时钟源:TC333 支持 3 类基础时钟源HSE(外部晶体振荡器,如代码中 16MHz 晶振);HSI(内部高速振荡器,默认频率);EVR(内部稳压器时钟,临时过渡时钟)。PLL:分为两类,独立控制不同域的频率SYSPLL(系统 PLL):给 CPU、内存(RAM)提供高频时钟;PERPLL(外设 PLL):给外设(如 CAN、SPI、UART)提供适配时钟。CCU:时钟控制单元(Clock Control Unit),负责将 PLL 输出的时钟分频后,分配给各个外设和模块(如 STM 定时器、MCAN)。TC333 的系统时钟配置需严格遵循 “解锁→临时时钟→PLL 配置→时钟切换→分配→锁定” 的流程,每个步骤都涉及特定寄存器操作,以下结合代码逐步解析。二、系统时钟配置分步讲解(基于Scu_CcuInit函数)步骤0:执行安全机制解锁代码讲解:(目的是为了安全配置时钟寄存器)硬件对ENDINIT位的修改有严格的时序依赖:不能直接从默认状态(如复位后的ENDINIT=0)直接置 0 并生效,必须先经过 “置 1→置 0” 的过渡,且整个过程必须在LCK=0(解锁WDTxCON0寄存器)的窗口期内完成。(总之记住就行了,这两步骤是为了解锁能配置时钟寄存器)生效条件:此时LCK=0(寄存器已解锁),且密码验证通过,因此ENDINIT=1的配置会被硬件接受并生效。作用:这一步不是 “要开放权限”,而是触发硬件进入 “允许修改ENDINIT位的状态”。硬件设计中,ENDINIT从 0→0 的直接修改是不被允许的(防止误操作),必须先临时置 1,才能后续置 0。生效条件:虽然此时设置了LCK=1(重新锁定),但由于上一步已将LCK临时改为 0(解锁),本次写入仍处于 “解锁窗口期” 内(硬件允许在解锁后立即执行一次锁定操作,并接受其中的ENDINIT配置),因此ENDINIT=0会被硬件接受并生效。作用:这是最终目标 —— 在 “解锁窗口期” 内,将ENDINIT从 1 改为 0,完成 “关闭初始化权限” 的操作,同时通过LCK=1重新锁定寄存器,防止后续误修改。初始化:/*Convert the original password into a valid password */ uint16 password = 0; password = SCU_WDTCPU0CON0.B.PW; /* B:(32-bit) , PW:(14-bit) belongs to B */ password ^= 0x003F; /* B:(32-bit) , PW:(14-bit) belongs to B */ /* Check the lck bit to determine if unlocking is required. */ if (SCU_WDTCPU0CON0.B.LCK) { SCU_WDTCPU0CON0.U = (1 0u) |/* ENDINIT */ (0 1u) |/* lck */ (password 2u) | (SCU_WDTCPU0CON0.B.REL 16u); } /* After completing the unlocking configuration, re-lock the registers.*/ SCU_WDTCPU0CON0.U = (0 0u) |/* Clear ENDINT */ (1 1u) |/*set LCK */ (password 2u) | (SCU_WDTCPU0CON0.B.REL 16u); /* read back ENDINIT and wait until it has been cleared */ while (SCU_WDTCPU0CON0.B.ENDINIT == 1) { }寄存器: CCUCON0