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
