1. AUX_EVCTL模块:CC13x2/CC26x2低功耗设计的核心枢纽
在CC13x2/CC26x2这类面向物联网的无线微控制器上做开发,如果你还在用主CPU(Cortex-M4/M0+)轮询去检查一个按键是否按下、或者等待一个ADC转换完成,那功耗表现大概率不会太理想。我经历过不少项目,初期为了快速验证功能,用简单的轮询逻辑,结果电池续航远达不到预期。后来深入研究了芯片的事件驱动架构,尤其是AUX_EVCTL(Auxiliary Event Control)这个模块,才真正把系统的功耗降了下来。
简单来说,AUX_EVCTL是连接AUX(辅助)域内各种外设(如ADC、比较器、定时器、IO)与更高级别处理器(如Sensor Controller Engine, SCE,以及主MCU)的“事件交换机”。它的核心是一个64位的同步事件总线,实时反映着数十个硬件事件的状态。更重要的是,它提供了一套完整的硬件机制,允许你配置“当A事件发生且B事件未发生时,才去唤醒某个处理器或触发某个动作”,从而将CPU从繁琐的等待和查询中彻底解放出来,实现真正的休眠与事件触发式运行。这对于依赖电池供电的传感器节点、可穿戴设备来说,是延长其寿命的关键。
2. 深入解析64位事件总线与状态寄存器
要玩转事件驱动,首先得搞清楚有哪些“事件”可用。AUX_EVCTL模块通过四个32位寄存器(EVSTAT0, EVSTAT1, EVSTAT2, EVSTAT3)组成了一个64位宽的事件状态镜像。每个位都对应一个特定的硬件信号。
2.1 事件源分类与映射
这64个事件可以大致分为几类,理解这个分类对后续的配置至关重要:
AUXIO引脚电平(事件0-31):这是最基础的一类。
EVSTAT0的bit0-bit15对应AUXIO0-AUXIO15,EVSTAT1的bit0-bit15对应AUXIO16-AUXIO31。这些位直接反映了对应AUXIO引脚的数字电平状态(注意,是经过同步后的电平)。这意味着你可以直接将一个外部传感器中断线、一个按键连接到AUXIO,其状态变化会实时体现在事件总线上。系统与定时器事件(事件32-47,主要在EVSTAT2):这部分事件非常丰富,是构建自动唤醒逻辑的核心。
AON_RTC_CH2/AON_RTC_CH2_DLY:来自Always-On域的实时时钟比较器事件,可用于周期性的定时唤醒,是超低功耗定时任务的基石。AON_RTC_4KHZ:RTC的4kHz时钟节拍,可用于需要粗粒度时间基准的场景。AON_BATMON_*_UPD:电池监控器更新事件,用于触发电池电压或温度采样。MCU_ACTIVE/PWR_DWN:指示MCU域是活跃状态还是掉电状态,可用于协调跨域任务。AUX_COMPA/AUX_COMPB:模拟比较器输出事件。这是实现模拟信号阈值触发(如唤醒)的关键,无需ADC持续工作。MCU_OBSMUX0/1:来自MCU域IO控制器(IOC)的观察复用器输出,可以将MCU域GPIO的事件路由到AUX域。MANUAL_EV:一个完全由软件控制的事件(通过MANUAL.EV位写1或0),用于软件触发测试或复杂状态机控制。
AUX域外设事件(事件48-63,主要在EVSTAT3):这部分是AUX域内部高性能外设的工作状态指示。
AUX_TIMER2_EV0-3/AUX_TIMER2_PULSE:AUX Timer2的四个比较匹配事件和一个脉冲事件,用于精确定时。AUX_TIMER0/1_EV:另外两个定时器的事件。AUX_ADC_DONE/AUX_ADC_FIFO_ALMOST_FULL/AUX_ADC_IRQ:ADC转换完成、FIFO将满、以及综合中断事件。这是实现ADC后台DMA传输或低功耗批量采样的核心。AUX_TDC_DONE:时间数字转换器完成事件。AUX_SMPH_AUTOTAKE_DONE:信号量自动获取完成事件。
注意:读取
EVSTATx寄存器得到的是事件在AUX时钟域下同步后的状态。但手册也明确指出,像AUX_TIMER2、AUX_ANAIF等“订阅者”模块,它们使用的是这些事件的异步版本。这意味着在配置这些模块使用事件触发时,需要额外考虑跨时钟域的同步延迟,在要求极高时序精度的场景下(例如用事件精确触发ADC采样时刻),这个延迟可能是不可忽略的。
2.2 高低字节别名寄存器(EVSTATxL/H)的妙用
手册中还列出了EVSTAT0L/EVSTAT0H到EVSTAT3L/EVSTAT3H这些“别名”寄存器。它们看起来只是将32位事件状态拆成了高16位和低16位的两个8位寄存器,似乎多此一举。但在Sensor Controller Engine(SCE)的汇编编程中,它们大有用途。
SCE的指令集对操作数的位宽有严格限制。很多指令,特别是位测试、跳转类指令,其操作数地址范围是有限的。EVSTAT0的地址可能超出了某些指令的寻址范围,而EVSTAT0L(偏移0x4C)和EVSTAT0H(偏移0x50)的地址更小,很可能落在SCE指令的“短偏移”寻址范围内。这样,SCE代码可以直接、高效地读取特定字节的事件状态,进行位测试和条件跳转,而无需通过更复杂的多字节加载和移位操作。在设计SCE固件进行事件判断时,优先查询这些L/H别名寄存器,往往能生成更紧凑、更高效的代码。
3. 事件的路由、组合与条件等待
仅仅能看到事件状态还不够,AUX_EVCTL的强大之处在于它能路由和组合这些事件,并让处理器进行条件等待。
3.1 事件路由:唤醒MCU与AON域
这是实现低功耗系统的关键路径。当AUX域内发生了一个关键事件(比如ADC采集完成了一组数据),我们通常希望它能唤醒处于睡眠状态的主MCU来处理数据。EVTOMCUFLAGS寄存器组就是干这个的。
工作流程如下:
- 选择事件与极性:在
EVTOMCUPOL寄存器中,为你想路由到MCU的事件选择触发条件。例如,对于AUX_ADC_DONE,你可以选择高电平(0)或低电平(1)有效。对于AUX_COMPA这类边沿信号,则选择上升沿(0)或下降沿(1)。 - 事件标志置位:当
EVSTAT3.AUX_ADC_DONE的电平符合EVTOMCUPOL.AUX_ADC_DONE的设定时,硬件会自动将EVTOMCUFLAGS.AUX_ADC_DONE标志位置1。 - 生成MCU中断:
EVTOMCUFLAGS中的每个标志位,都可以通过COMBEVTOMCUMASK寄存器选择是否参与生成一个聚合事件AUX_COMB。这个AUX_COMB事件会被连接到MCU域的事件系统(EVENT),进而可以触发CPU中断(NVIC)。你可以在MCU的中断服务程序(ISR)中查询是哪个具体事件唤醒了自己。 - 清除标志:处理完事件后,必须向
EVTOMCUFLAGSCLR寄存器的对应位写1来清除标志。这里有一个非常重要的细节:对于电平敏感的事件(如AUX_ADC_DONE),手册强调“In order to clear a level sensitive event flag, the event must be deasserted”。这意味着,如果ADC完成信号一直为高,你写清除标志是没用的,标志位会被立即重新置起。正确的做法是,先确保事件源恢复无效状态(例如,通过启动下一次ADC转换来拉低DONE信号),然后再清除标志位,否则会导致中断风暴。
EVTOAONFLAGS寄存器组的功能完全类似,只不过它是将事件路由到超低功耗的AON(Always-On)域,通常用于唤醒更底层的电源状态或触发AON域内的RTC等操作。
3.2 事件组合与条件等待:SCE的低功耗秘诀
Sensor Controller Engine (SCE) 是一个独立于主CPU的、专为低功耗传感器数据处理设计的可编程内核。它的功耗极低,但功能强大。让SCE高效工作的关键,就是SCEWEVCFG0和SCEWEVCFG1这两个寄存器。
核心逻辑:这两个寄存器共同配置了AUX_SCE:WUSTAT.EV_SIGNALS寄存器的bit 7。SCE的WEV(等待事件)和BEV(分支事件)指令可以监控这个信号,从而实现“事件条件满足时才继续执行”的节能模式。
配置模式:
- 单事件模式(
COMB_EV_EN = 0):WUSTAT.EV_SIGNALS[7]=EV0_SEL选择的事件(极性由EV0_POL控制)。SCE可以等待一个特定的事件,比如等待AON_RTC_CH2(定时事件)到来。 - 双事件组合模式(
COMB_EV_EN = 1):WUSTAT.EV_SIGNALS[7]= (EV0_SEL事件)OR(EV1_SEL事件)。这里的OR是逻辑或。结合EV0_POL和EV1_POL的极性控制,可以实现复杂的逻辑条件。
一个经典应用场景——带超时的传感器读取: 假设SCE需要等待一个外部中断(AUXIO0)变高,但同时不能无限等下去,最多等10ms。
- 配置
EV0_SEL=AUXIO0(0x00),EV0_POL=1(高电平有效)。 - 配置
EV1_SEL=AON_RTC_CH2_DLY(0x22),并预先在AON_RTC中设置一个10ms的延迟通道。EV1_POL=1(高电平有效)。 - 设置
COMB_EV_EN = 1。 - 在SCE代码中,执行
WEV指令等待WUSTAT.EV_SIGNALS[7]变高。 - 结果:
AUXIO0变高或10ms定时到达,都会让SCE退出等待。SCE醒来后,可以立即检查EVSTAT0.AUXIO0和EVSTAT2.AON_RTC_CH2_DLY的状态,来判断是被传感器触发的还是超时了。这样既保证了响应实时性,又避免了死等。
3.3 事件观察与调试:EVOBSCFG寄存器
EVOBSCFG.EVOBS_SEL寄存器允许你将64个事件总线中的任何一个,路由到AUX_EV_OBS信号。这个信号可以被连接到某个AUXIO引脚上,通过示波器或逻辑分析仪进行观察。这在调试复杂的事件交互逻辑、验证事件触发时序时是无价之宝。你可以动态切换观察的事件源,亲眼看到哪个事件在何时发生,比单靠读寄存器打印日志要直观和可靠得多。
4. 关键功能寄存器详解与实战配置
4.1 DMACTL:ADC与uDMA的自动传输桥梁
DMACTL寄存器控制着AUX ADC与MCU域uDMA(微直接内存访问)控制器之间的接口。这是实现高速、低CPU开销数据采集的关键。
EN位:必须置1,才能使能uDMA通道7与ADC FIFO的连接。SEL位:选择DMA触发条件。0: ADC FIFO中有任意数据(非空)即触发DMA请求。适用于低采样率、需要实时传输每个样本的场景。1: ADC FIFO几乎满(3/4满)时触发DMA请求。这是更高效的模式,适合批量采集。DMA会一次性传输多个样本,减少了传输次数和总线占用,降低了整体功耗。
REQ_MODE位:选择DMA请求模式。0: 突发请求(Burst)。当触发条件满足时,DMA控制器会尝试一次性搬移尽可能多的数据(直到FIFO为空或达到传输量上限)。效率最高。1: 单次请求(Single)。每次触发只搬移一个数据单元。灵活性高,但效率较低。
实战配置示例(批量ADC采样并通过DMA传输):
// 假设已配置好ADC和uDMA通道7 // 1. 配置DMA触发条件为FIFO几乎满 HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_DMACTL) = AUX_EVCTL_DMACTL_EN | AUX_EVCTL_DMACTL_SEL_ALMOST_FULL; // 2. 在uDMA配置中,设置源地址为ADC FIFO,并启用该通道。 // 3. 启动ADC连续采样。 // 此后,每当ADC FIFO达到3/4满,硬件会自动触发DMA将数据搬移到SRAM,完全无需CPU干预。 // CPU可以在大部分时间休眠,仅在DMA传输完成中断中醒来处理一批数据。4.2 PROGDLY:可编程延迟事件发生器
PROGDLY.VALUE是一个16位的递减计数器,以1MHz的固定频率递减。当VALUE减到0时,事件AUX_PROG_DLY_IDLE会变高。这个事件可以被SCEWEVCFG选择,用于实现精确的软件可编程延迟。
重要限制:手册用加粗警告,该计数器仅在AUX_SYSIF:OPMODEACK.ACK等于A(Active)或LP(Low Power)模式时才可使用。在更深度的睡眠模式下,该计数器会停止。此外,当SCE被调试器暂停或系统通过AUX_SYSIF:TIMERHALT显式暂停它时,计数器也会停止。
使用场景:当你需要一段介于硬件定时器精度(通常是us级)和RTC精度(通常是ms级)之间的延迟时,或者需要一段非标准周期的延迟时,PROGDLY非常有用。例如,SCE可以设置PROGDLY.VALUE = 1500(对应1.5ms延迟),然后等待AUX_PROG_DLY_IDLE事件。
4.3 MANUAL:软件控制的事件发生器
MANUAL.EV位是唯一一个完全由软件读写控制的事件源(对应EVSTAT2.MANUAL_EV)。它的价值在于:
- 调试与测试:可以手动置位/清除该事件,来测试SCE的事件等待逻辑或MCU的事件路由逻辑是否正常。
- 复杂状态机触发:在SCE或MCU的软件中,可以根据复杂的算法逻辑,通过设置
MANUAL.EV来触发下游的事件响应机制。它相当于在硬件事件总线中插入了一个纯软件控制的“开关”。
5. 实战经验:构建一个低功耗温湿度传感器节点
让我们用一个具体的例子,把上面的知识点串起来。假设我们要用CC2652设计一个低功耗温湿度传感器节点,每5分钟测量一次,并通过蓝牙上报。
系统架构:
- 主MCU (Cortex-M4):运行蓝牙协议栈和主应用逻辑,大部分时间深度睡眠。
- Sensor Controller Engine (SCE):负责周期唤醒、控制传感器(如I2C接口的SHT30)、读取数据,并在数据就绪后唤醒主MCU。
- 外设:使用AUX Timer2产生精确的5分钟定时,使用I2C总线连接传感器,使用一个AUXIO引脚连接传感器的数据就绪中断引脚。
步骤与配置:
初始化与时钟配置:
- 确保AUX域电源和时钟(SCLK_LF, SCLK_MF)已开启。
- 配置AUX Timer2为32位定时器,设置比较值匹配5分钟(需根据时钟频率计算)。
- 配置
AUX_SYSIF:EVSYNCRATE,设置AUX_TIMER2_SYNC_RATE,决定Timer2事件同步到事件总线的速率。
SCE侧的事件等待配置:
- 目标:SCE休眠,直到5分钟定时到达或传感器数据就绪(中断引脚变低)。
- 配置
SCEWEVCFG0.EV0_SEL=AUX_TIMER2_EV0(假设使用EV0输出)。 - 配置
SCEWEVCFG1.EV1_SEL=AUXIOx(连接传感器中断的引脚)。 - 配置
SCEWEVCFG1.EV1_POL=0(假设低电平有效)。 - 设置
SCEWEVCFG0.COMB_EV_EN = 1,使能逻辑或组合。 - 在SCE的初始化代码中,编写一个循环,末尾是
WEV指令,等待WUSTAT.EV_SIGNALS[7]。
SCE唤醒后的处理:
- SCE被唤醒后,首先读取
EVSTAT2和EVSTAT0,判断是定时器事件还是传感器中断。 - 如果是定时器事件,SCE通过I2C启动一次传感器测量,然后再次进入
WEV等待(这次可能只等传感器中断事件)。 - 如果是传感器中断,SCE读取传感器数据,将数据存入共享内存(AUX RAM中与MCU约定的区域)。
- SCE被唤醒后,首先读取
唤醒主MCU:
- SCE准备好数据后,需要通知主MCU。这里有两种选择:
- 软件事件:SCE通过写
SWEVSET.SWEV0寄存器,置位一个软件事件。该事件会通过EVTOMCUFLAGS.SWEV0路由到MCU。 - 直接事件:如果SCE处理完后有明确的硬件信号(比如操作了某个GPIO),也可以配置该GPIO变化作为事件源。
- 软件事件:SCE通过写
- 配置
EVTOMCUPOL,设置对应事件的极性。 - 配置
COMBEVTOMCUMASK,确保该事件位被包含在内,从而能产生AUX_COMB事件。 - 在MCU侧,配置NVIC,使能来自AUX_COMB事件的中断。
- SCE准备好数据后,需要通知主MCU。这里有两种选择:
MCU中断服务程序:
- MCU被
AUX_COMB中断唤醒。 - 在ISR中,读取
EVTOMCUFLAGS寄存器,检查是哪个标志位被置起(例如SWEV0)。 - 从共享内存中读取传感器数据。
- 关键一步:在确认传感器中断引脚已恢复高电平(事件无效)后,向
EVTOMCUFLAGSCLR寄存器的对应位写1,清除标志位。 - 处理数据(如进行校准计算),通过蓝牙发送。
- 再次进入深度睡眠。
- MCU被
功耗优化点睛:
- SCE的功耗:SCE在执行
WEV指令等待事件时,其时钟可以被门控,功耗极低,可能只有几百nA。 - 主MCU的睡眠:主MCU在等待期间处于深度睡眠(Shutdown模式),仅由RTC和AUX域的事件网络保持可唤醒状态,功耗在1uA以下。
- 外设电源管理:在SCE启动传感器测量前,才通过GPIO或电源开关给传感器供电;测量完成后立即断电。这个控制逻辑可以由SCE直接操作AUXIO完成。
- SCE的功耗:SCE在执行
通过这样一套基于AUX_EVCTL的事件驱动架构,主MCU和SCE都只在必要时被唤醒并工作,实现了系统级的功耗最小化。整个过程中,CPU几乎没有进行任何轮询操作,所有状态切换都由硬件事件自动触发,这正是CC13x2/CC26x2系列芯片低功耗能力的精髓所在。