当前位置: 首页 > news >正文

CC13x2/CC26x2无线MCU事件与中断系统架构解析与实战配置

1. 事件与中断系统架构解析

在CC13x2/CC26x2这类无线MCU的开发中,事件与中断系统是整个芯片实时响应能力的核心骨架。很多工程师刚开始接触这个平台时,会觉得手册里那一堆寄存器表格和事件编号特别头疼,感觉像是要背下一整本字典。但实际用起来你会发现,这套系统设计得非常巧妙,它把传统MCU里那些零散的中断控制器、DMA触发、唤醒源管理都整合到了一个统一的事件路由网络里。

简单来说,你可以把MCU事件结构想象成一个大型的中央交换机。各种外设(比如GPIO边沿检测、定时器溢出、ADC转换完成、RTC闹钟)都是这个交换机的“来电号码”(事件源),而CPU中断、DMA通道、甚至其他外设的触发输入则是“接听方”(订阅者)。这个交换机的厉害之处在于,它允许你把任意一个来电号码转接到任意一个接听方,而且还能设置多个分机同时响铃。

为什么TI要设计这么复杂的系统?我做了几个低功耗传感器项目后深有体会。传统的中断系统,CPU必须随时待命处理每个外设的请求,哪怕只是在等一个GPIO按键。但在CC13x2/CC26x2上,你可以配置DIO的边沿事件直接触发DMA搬运数据到内存,CPU全程睡觉;或者让RTC的周期性事件直接唤醒射频模块开始发送,CPU只在需要处理协议栈时才醒来。这种事件驱动的异步架构,才是实现微安级平均功耗的关键。

整个事件系统分为两大块:MCU事件结构AON事件系统。MCU事件结构主要负责运行时的外设间通信,比如定时器触发DMA、ADC完成触发中断;而AON事件系统则掌管着芯片的“生死大权”——它能在MCU深度睡眠时继续监控RTC、GPIO等唤醒源,一旦条件满足就启动唤醒序列。这两个系统通过EVTOMCUSEL等寄存器桥接,形成了从Always-On域到MCU域的完整事件通路。

2. 事件订阅者深度剖析

2.1 系统CPU订阅者:中断向量路由的核心

系统CPU是事件结构中最主要的订阅者,它对应着ARM Cortex-M内核的NVIC中断输入。手册里提到,中断向量号16到49的事件都是通过MCU事件结构路由到系统CPU的。这里有个关键点:所有电平中断事件都会被事件结构路由到系统CPU

这意味着什么?在实际编程时,你不需要像某些老旧MCU那样去手动配置中断优先级分组、使能外部中断线。你只需要在对应外设的寄存器里使能中断,然后在事件结构的CPUIRQSELx寄存器中确认事件源映射关系是否正确,剩下的路由工作硬件自动完成。

举个例子,UART0的接收中断。你首先要在UART0:IMSC寄存器中使能RXIM中断掩码,当UART收到数据时,它会生成一个“UART0 combined interrupt”事件。这个事件在硬件上已经固定映射到了CPUIRQSEL5寄存器(复位值0x24),对应着UART0的中断标志位UART0:MIS。CPU收到这个事件后,就会跳转到UART0的中断服务程序。

但这里有个容易踩坑的地方:事件编号和中断向量号是两个概念。事件编号是事件源在事件结构中的ID(比如UART0是0x24),而中断向量号是CPU用来查找ISR入口地址的索引。在startup文件里你配置的是中断向量表,对应的是向量号,不是事件编号。我刚开始就搞混过,配置了半天发现中断不触发,最后发现是向量表里填错了处理函数地址。

2.2 动态可编程事件:CPUIRQSEL30的妙用

在所有CPU中断事件中,CPUIRQSEL30是个特殊的存在——它是唯一一个可动态配置的CPU中断事件源。其他CPUIRQSEL寄存器基本都是只读的,硬件固定映射,但CPUIRQSEL30的EV字段是可读写的。

这意味着你可以把一个自定义的事件源路由到CPU中断30。比如你想用AUX Timer2的事件0来触发一个自定义的中断,就可以在CPUIRQSEL30.EV字段写入0x38。这个功能在实现软件可配置的事件响应时特别有用。

我最近在一个项目里就用到了这个特性。系统需要根据运行模式动态切换唤醒源:在数据采集模式下,用AUX ADC完成事件触发中断;在通信模式下,改用RTC周期性事件。如果每个事件都占用一个固定中断线,很快就用完了。但通过CPUIRQSEL30,我只需要在切换模式时重新配置这一个寄存器,中断服务程序可以保持不变,大大简化了代码结构。

配置时要注意,CPUIRQSEL30的复位值是0x00(Always inactive),所以默认情况下中断30是不会触发的。你需要先配置好事件源(比如设置AUX Timer2),然后在CPUIRQSEL30中写入对应的事件编号,最后在NVIC中使能中断30。顺序不能乱,否则可能错过第一个事件。

2.3 NMI订阅者:不可屏蔽的紧急通道

NMI(Non-Maskable Interrupt)订阅者只有一个非可配置的输入源——看门狗定时器(WDT)。这个设计体现了NMI的定位:处理系统级严重错误,不能被软件屏蔽

CM3NMISEL0寄存器是只读的,固定为0x63,对应WDT的不可屏蔽中断事件。当看门狗超时且WDT:CTL.INTTYPE配置为NMI模式时,这个事件会直接触发NMI异常。

在实际应用中,NMI通常用于系统恢复或紧急日志记录。比如我在一个电池供电的设备上,当检测到电压低于临界值时,通过配置WDT在短时间内超时触发NMI,在NMI处理程序中紧急保存关键数据到Flash,然后执行安全关机。因为NMI不能被屏蔽,即使主程序卡死,这个安全机制也能执行。

注意:NMI中断服务程序应该尽可能短小,避免复杂操作。因为NMI可能发生在任何上下文,包括其他中断服务程序中。如果NMI处理时间过长,可能导致系统实时性严重下降。

2.4 Freeze订阅者:调试时的外设同步器

Freeze订阅者是个很有意思的设计,它把CPU的调试暂停信号(halted)传递给特定的外设。当你在调试器中暂停CPU执行时,连接到Freeze订阅者且使能了冻结功能的外设也会同步暂停。

FRZSEL0寄存器控制着Freeze订阅者的事件选择,复位值是0x78(CPU_HALTED)。这意味着默认情况下,Freeze输出就是CPU的暂停状态。但你也可以把它配置为静态0、静态1,或者选择其他事件源。

这个功能在调试定时器相关代码时特别有用。想象一下,你在单步调试一个PWM输出程序,如果没有Freeze功能,即使CPU停了,GPTimer还在继续计数,PWM输出还在变化,你根本没法观察特定时刻的寄存器状态。但有了Freeze,你可以让定时器与CPU同步暂停,真正实现“冻结现场”。

手册里还提到了一个重要的细节:当Freeze信号有效时,RTC的主计数器会停止递增,但RTC的更新事件(去往RF核心和AON事件结构的)不会停止。这是因为更新事件是基于SCLK_LF的分频,不依赖主计数器。所以调试时RF相关的事件可能还在继续,这点需要注意。

3. AON事件系统详解

3.1 AON事件源全景图

AON(Always-On)事件系统是CC13x2/CC26x2低功耗设计的精髓所在。它运行在Always-On电源域,即使MCU主域掉电,AON事件系统仍然在工作,监控着各种唤醒源。

AON事件源主要分为几大类:

  • DIO边沿检测:DIO0-DIO31的单个引脚事件,以及DIO(任意引脚)的组合事件
  • RTC事件:包括通道0-2的事件、延迟事件、组合延迟事件和更新节拍
  • AUX事件:软件触发事件、比较器触发、ADC完成、TDC完成、定时器事件等
  • 电池监控事件:温度更新、电压更新、阈值触发等
  • 其他系统事件:JTAG事件、始终有效事件等

这些事件通过AON_EVENT模块的寄存器进行路由选择,最终可以触发MCU唤醒、产生MCU域中断,或者直接用于AON_RTC的捕获功能。

3.2 MCU唤醒源配置实战

MCUWUSEL和MCUWUSEL1这两个寄存器掌管着MCU的“闹钟”。它们各有4个字段(WU0_EV到WU7_EV),每个字段6位,可以从64个AON事件中选择一个作为唤醒源。总共8个唤醒源,任意一个有效就能触发MCU唤醒序列。

配置唤醒源时,有个严格的时序要求:必须在MCU请求掉电之前设置好唤醒事件。具体来说,就是在PRCM请求uLDO(通过PRCM:VDCTL.ULDO)之前,要先配置好AON_EVENT:MCUWUSEL。如果顺序反了,唤醒事件可能无法正确注册,导致MCU睡死过去。

我在实际项目中总结了一个可靠的配置流程:

  1. 配置IOCFGx.IOEV_MCU_WU_EN,使能特定DIO引脚对唤醒事件的贡献
  2. 配置AON_EVENT:MCUWUSEL.WUx_EV,选择具体的事件源编号
  3. 如果需要边沿检测,配置IOCFGx.EDGE_DET选择边沿类型
  4. 最后才让MCU进入低功耗模式

举个例子,要用DIO15的上升沿唤醒MCU:

// 1. 配置DIO15为输入,使能唤醒功能 HWREG(IOC_BASE + IOCFG15) = (HWREG(IOC_BASE + IOCFG15) & ~IOCFG_IOEV_MCU_WU_EN_M) | IOCFG_IOEV_MCU_WU_EN_EN; // 2. 配置边沿检测为上升沿 HWREG(IOC_BASE + IOCFG15) = (HWREG(IOC_BASE + IOCFG15) & ~IOCFG_EDGE_DET_M) | IOCFG_EDGE_DET_POS; // 3. 设置唤醒源0为DIO15事件(事件编号0x0F,因为DIO15对应0x0F) HWREG(AON_EVENT_BASE + MCUWUSEL) = (HWREG(AON_EVENT_BASE + MCUWUSEL) & ~MCUWUSEL_WU0_EV_M) | (0x0F << MCUWUSEL_WU0_EV_S); // 4. 使能唤醒源 HWREG(AON_EVENT_BASE + MCUWUSEL) |= MCUWUSEL_WU0_EV_EN;

3.3 AON到MCU的事件路由

EVTOMCUSEL寄存器负责把AON事件路由到MCU事件结构,生成AON_PROG0/1/2这三个可编程事件。这三个事件可以进一步路由到CPU中断(通过CPUIRQSEL29等)或者其他订阅者。

这里有个重要的设计细节:AON_PROG0_EV在EVTOMCUSEL寄存器中的有效选项比AON_PROG1_EV和AON_PROG2_EV少得多。从手册的表格可以看出,AON_PROG0_EV只能选择DIO边沿事件(0x00),其他选项都是保留的0。而AON_PROG1_EV和AON_PROG2_EV可以选择几乎所有的AON事件源。

这意味着在系统设计时,如果你需要一个灵活的、可从多种AON事件源触发的中断,应该优先使用AON_PROG1或AON_PROG2。AON_PROG0更适合简单的GPIO唤醒场景。

4. 事件寄存器配置指南

4.1 CPU中断选择寄存器配置

CPUIRQSEL0到CPUIRQSEL37这38个寄存器控制着每个CPU中断线的事件源选择。大部分寄存器是只读的,硬件固定映射,但理解这些映射关系对调试至关重要。

我整理了一个常用中断的事件映射速查表:

中断向量号寄存器复位值对应事件源控制寄存器
0CPUIRQSEL00x04IOC边沿检测IOC:IOCFGn.EDGE_IRQ_EN
4CPUIRQSEL40x07AON_RTC组合事件AON_RTC:CTL.COMB_EV_MASK
5CPUIRQSEL50x24UART0组合中断UART0:MIS
6CPUIRQSEL60x1CAUX软件事件0AUX_EVCTL:SWEVSET.SWEV0
14CPUIRQSEL140x18看门狗中断WDT:CTL.INTEN
15-22CPUIRQSEL15-220x10-0x0FGPT0A-GPT3B中断GPTx:TAMR/TBMR
29CPUIRQSEL290x01AON可编程事件0AON_EVENT:EVTOMCUSEL.AON_PROG0_EV
30CPUIRQSEL300x00动态可编程事件软件配置

配置中断的基本流程是:

  1. 在外设中使能中断生成(如UART0:IMSC寄存器的相应位)
  2. 确认CPUIRQSELx寄存器映射正确(通常使用复位值即可)
  3. 在NVIC中使能对应中断向量
  4. 编写中断服务程序,并在向量表中注册

对于动态可配置的CPUIRQSEL30,配置步骤稍有不同:

// 配置CPUIRQSEL30使用AUX Timer2事件0 HWREG(EVENT_BASE + CPUIRQSEL30) = (HWREG(EVENT_BASE + CPUIRQSEL30) & ~CPUIRQSEL30_EV_M) | 0x38; // 在NVIC中使能中断30 NVIC_EnableIRQ((IRQn_Type)30); // 设置中断优先级(可选) NVIC_SetPriority((IRQn_Type)30, 2);

4.2 RF核心事件路由配置

RFCSEL0到RFCSEL9这10个寄存器控制着事件到RF核心的路由。RF核心作为无线模块,需要精确的定时触发,因此事件路由的配置直接影响射频性能。

RFCSEL0-7固定映射到GPTimer的比较事件,用于产生精确的射频时序:

  • RFCSEL0: GPT0A比较事件 (0x3D)
  • RFCSEL1: GPT0B比较事件 (0x3E)
  • RFCSEL2: GPT1A比较事件 (0x3F)
  • RFCSEL3: GPT1B比较事件 (0x40)
  • RFCSEL4: GPT2A比较事件 (0x41)
  • RFCSEL5: GPT2B比较事件 (0x42)
  • RFCSEL6: GPT3A比较事件 (0x43)
  • RFCSEL7: GPT3B比较事件 (0x44)

RFCSEL8固定为RTC周期性事件(0x77),用于射频的周期性唤醒。RFCSEL9是可配置的,可以从多个事件源中选择,为射频操作提供额外的触发条件。

在射频应用中,通常需要配置GPTimer在特定时刻产生比较事件,触发RF核心开始发送或接收。配置示例:

// 配置GPT0A为比较模式 HWREG(GPT0_BASE + GPT_O_TAMR) = (HWREG(GPT0_BASE + GPT_O_TAMR) & ~GPT_TAMR_TAMR_M) | GPT_TAMR_TAMR_ONE_SHOT; HWREG(GPT0_BASE + GPT_O_TAMR) |= GPT_TAMR_TAOTE; // 使能输出触发事件 // 设置比较值(比如100ms后触发) HWREG(GPT0_BASE + GPT_O_TAILR) = 100000; // 假设时钟频率1MHz // RFCSEL0已经固定映射到GPT0A比较事件,无需额外配置 // RF核心会在GPT0A比较匹配时收到事件

4.3 GPTimer捕获事件路由

GPTxACAPTSEL和GPTxBCAPTSEL寄存器允许GPTimer的捕获单元从事件结构中选择事件源。这功能非常强大,可以实现精确的时间戳捕获。

每个GPTimer有两个捕获/比较通道(A和B),每个通道都可以独立选择捕获事件源。可选的源包括:

  • 其他定时器的比较事件(用于级联)
  • DIO边沿事件(用于脉冲宽度测量)
  • AUX事件(用于传感器数据同步)
  • RTC事件(用于绝对时间戳)

比如要测量一个外部脉冲的宽度,可以用DIO边沿事件触发GPTimer捕获:

// 配置DIO14为输入,使能边沿检测 HWREG(IOC_BASE + IOCFG14) = (HWREG(IOC_BASE + IOCFG14) & ~IOCFG_EDGE_DET_M) | IOCFG_EDGE_DET_BOTH; HWREG(IOC_BASE + IOCFG14) |= IOCFG_EDGE_IRQ_EN_EN; // 配置GPT0A捕获事件源为DIO14边沿事件(事件编号0x04) // 注意:需要根据具体DIO编号计算事件编号,DIO14对应0x0E // 但GPT0ACAPTSEL支持的事件列表中,0x04对应IOC边沿检测事件 // 实际配置需要结合IOC:IOCFGn.PORT_ID设置 HWREG(EVENT_BASE + GPT0ACAPTSEL) = (HWREG(EVENT_BASE + GPT0ACAPTSEL) & ~GPT0ACAPTSEL_EV_M) | 0x04; // 配置GPT0为边沿时间捕获模式 HWREG(GPT0_BASE + GPT_O_TAMR) = (HWREG(GPT0_BASE + GPT_O_TAMR) & ~GPT_TAMR_TAMR_M) | GPT_TAMR_TAMR_CAP; HWREG(GPT0_BASE + GPT_O_CTL) |= GPT_CTL_TAEN; // 使能定时器

4.4 DMA事件路由配置

µDMA的事件路由是最复杂的部分,但也是性能优化的关键。CC13x2/CC26x2的DMA有24个通道,每个通道都有单次请求(SREQ)和突发请求(BREQ)两个事件输入,分别对应UDMACHxSSEL和UDMACHxBSEL寄存器。

DMA事件源主要分为几类:

  1. 外设硬件触发:UART、SSI的收发事件(固定映射)
  2. 定时器触发:GPTimer的DMA触发事件(可配置)
  3. 软件触发:通过AUX_EVCTL:DMASWREQ或SWEV寄存器
  4. AON可编程事件:用于低功耗场景的唤醒触发

固定映射的通道:

  • 通道1-2: UART0 RX/TX
  • 通道3-4: SSI0 RX/TX
  • 通道5-6: UART1 RX/TX
  • 通道7: AUX DMA请求
  • 通道8: AUX软件触发
  • 通道13: AON_PROG2事件
  • 通道15: AON_RTC组合事件
  • 通道16-17: SSI1 RX/TX
  • 通道21-24: 软件事件0-3

可配置的通道(9-12, 14)可以从多个事件源中选择,包括GPTimer事件、软件事件等。

配置DMA传输的典型流程:

// 1. 配置事件源(比如用GPT0A触发DMA通道9) HWREG(EVENT_BASE + UDMACH9BSEL) = (HWREG(EVENT_BASE + UDMACH9BSEL) & ~UDMACH9BSEL_EV_M) | 0x4D; // GPT0A DMA触发事件 // 2. 配置DMA通道控制字 HWREG(UDMA0_BASE + UDMA_O_ALTCLR) = 1 << 9; // 使用主控制结构 HWREG(UDMA0_BASE + UDMA_O_DMACHCTL + 9*4) = UDMA_DMACHCTL_EN; // 使能通道 // 3. 配置GPTimer产生DMA触发事件 HWREG(GPT0_BASE + GPT_O_DMAEV) = GPT_DMAEV_TATO_DMA; // GPT0A超时产生DMA事件 // 4. 启动传输 HWREG(UDMA0_BASE + UDMA_O_SWREQ) = 1 << 9; // 软件请求启动(如果配置为软件触发)

5. 软件事件生成与应用

5.1 SWEV寄存器:软件触发的事件发生器

SWEV寄存器提供了4个软件事件(SWEV0-SWEV3),可以通过写1来触发相应的事件。这些软件事件可以路由到几乎任何订阅者,为系统提供了灵活的软件触发机制。

每个SWEV位都是写1触发,写0无效。而且只有当前值为0时写1才会触发事件,这避免了重复触发。触发后,位会自动清零,所以是单次触发。

软件事件的典型应用场景:

  1. 调试和测试:手动触发特定事件,验证事件路由配置
  2. 软件状态机同步:在不同任务间同步状态
  3. DMA软件启动:通过UDMACH21-24通道触发DMA传输
  4. 中断模拟:在特定条件下触发CPU中断
// 触发软件事件0,产生一个事件脉冲 HWREG(EVENT_BASE + SWEV) |= SWEV_SWEV0; // 软件事件0可以路由到CPU中断30(通过CPUIRQSEL30配置为0x64) // 或者路由到DMA通道21(UDMACH21BSEL固定为0x64)

5.2 事件与中断的优先级处理

虽然事件结构本身没有硬件优先级,但事件路由到CPU中断后,就受NVIC优先级控制。这里有个重要的设计原则:事件响应延迟 = 事件生成延迟 + 路由延迟 + 中断响应延迟

对于实时性要求高的应用,需要仔细考虑:

  1. 选择合适的事件源:硬件事件比软件事件快,直接外设事件比间接事件快
  2. 优化中断服务程序:ISR尽可能短,复杂处理放到任务中
  3. 合理设置NVIC优先级:避免优先级反转导致实时事件被阻塞

我遇到过的一个坑是:同时使用UART DMA传输和GPTimer捕获,两者都配置了高优先级中断。当UART DMA完成中断正在服务时,GPTimer的捕获事件可能丢失。解决方案是给GPTimer分配更高的优先级,或者使用事件直接触发DMA而不是中断。

5.3 低功耗场景下的事件配置

在低功耗设计中,事件系统的配置需要特别注意:

深度睡眠下的唤醒配置

// 配置RTC通道0事件作为唤醒源 HWREG(AON_RTC_BASE + AON_RTC_O_CHCTL) |= AON_RTC_CHCTL_CH0_EN; // 使能RTC通道0 HWREG(AON_RTC_BASE + AON_RTC_O_CH0CMP) = wakeupTime; // 设置唤醒时间 // 配置AON事件路由到MCU唤醒 HWREG(AON_EVENT_BASE + MCUWUSEL) = (HWREG(AON_EVENT_BASE + MCUWUSEL) & ~MCUWUSEL_WU0_EV_M) | 0x23; // RTC通道0事件 // 进入深度睡眠前确保配置生效 while (!(HWREG(AON_EVENT_BASE + MCUWUSEL) & MCUWUSEL_WU0_EV_EN)) { // 等待配置完成 } // 请求MCU域掉电 HWREG(PRCM_BASE + PRCM_O_PDCTL0) |= PRCM_PDCTL0_MCU_PD_EN;

外设冻结配置: 当CPU调试暂停时,你可能希望某些外设继续运行(比如RTC维持时间),某些外设暂停(比如PWM输出)。通过配置外设的冻结使能位和FRZSEL0寄存器可以实现精细控制。

// 配置GPTimer0在CPU暂停时也暂停 HWREG(GPT0_BASE + GPT_O_CTL) |= GPT_CTL_TASTALL; // 使能定时器冻结 // FRZSEL0默认就是CPU_HALTED,所以不需要修改 // 当调试器暂停CPU时,GPTimer0也会自动暂停

6. 常见问题与调试技巧

6.1 事件不触发的排查步骤

事件系统调试最头疼的就是“事件明明应该发生,但就是没触发”。根据我的经验,可以按以下步骤排查:

  1. 确认事件源是否真正产生

    • 对于GPIO事件:用示波器或逻辑分析仪确认边沿是否产生
    • 对于定时器事件:检查定时器是否使能、比较值是否正确
    • 对于软件事件:单步跟踪SWEV寄存器的写入
  2. 检查事件路由配置

    • 确认EVTOMCUSEL、CPUIRQSELx等路由寄存器配置正确
    • 注意有些寄存器是只读的,硬件固定映射,不能修改
    • 检查事件编号是否正确,参考手册的Event Number表格
  3. 验证订阅者配置

    • CPU中断:确认NVIC已使能,优先级设置合理
    • DMA通道:确认DMA通道已使能,控制结构配置正确
    • GPTimer捕获:确认定时器工作在捕获模式,捕获使能
  4. 检查电源和时钟域

    • 确保事件源和订阅者在同一个电源域,或者有正确的域间通信
    • 确认相关时钟已使能(特别是AUX域和AON域的时钟)

6.2 事件冲突与资源竞争

当多个事件试图路由到同一个订阅者,或者一个事件源被多个订阅者监听时,可能会发生冲突。CC13x2/CC26x2的事件结构是广播式的,一个事件可以同时发送给多个订阅者,这通常不是问题。但要注意:

  1. CPU中断冲突:如果多个事件映射到同一个中断向量,需要在ISR中检查多个标志位
  2. DMA通道竞争:一个DMA通道只能服务一个事件源,不能同时监听多个
  3. 唤醒源优先级:多个唤醒事件同时发生时,唤醒处理是并行的,但唤醒后的中断处理有NVIC优先级

6.3 低功耗模式下的特殊考虑

在低功耗模式下,有些事件行为会发生变化:

  1. MCU域掉电时:只有AON事件系统能产生唤醒事件,MCU事件结构不工作
  2. 外设时钟门控时:该外设无法产生事件,即使使能了事件生成
  3. Freeze生效时:某些外设可能暂停,但AON事件继续(如RTC更新事件)

一个常见的错误是:在MCU进入睡眠前配置了GPTimer事件作为唤醒源,但忘记使能GPTimer的时钟。结果GPTimer根本不运行,自然无法产生事件。

6.4 性能优化建议

  1. 用DMA代替CPU中断:对于数据搬运类任务,配置事件直接触发DMA,让CPU睡觉
  2. 事件链式触发:一个事件触发另一个事件,形成处理流水线。比如GPIO事件触发DMA,DMA完成触发中断
  3. 合理使用软件事件:在状态机复杂但实时性要求不高的场景,用软件事件简化设计
  4. 避免事件风暴:高频事件(如32kHz RTC更新)不要直接触发CPU中断,可以用作DMA或定时器的时钟源

6.5 实际项目中的经验教训

在我最近的一个无线传感器项目中,需要每10ms采集一次传感器数据并通过BLE发送。最初的设计是用RTC事件唤醒CPU,CPU读取传感器、处理数据、控制射频。结果功耗总下不来,平均电流还有几百微安。

后来重构了事件流:

  • RTC事件触发ADC采样(通过事件路由到ADC启动)
  • ADC完成事件触发DMA搬运到内存
  • DMA完成事件触发CPU中断
  • CPU只做必要的数据打包和协议处理
  • 射频操作由GPTimer事件精确触发

重构后CPU唤醒时间从每10ms醒来一次、每次持续2ms,变成了每100ms醒来一次、每次持续200μs。平均电流降到了50μA以下。

关键配置代码片段:

// RTC每10ms产生事件 HWREG(AON_RTC_BASE + AON_RTC_O_CHCTL) |= AON_RTC_CHCTL_CH0_EN; HWREG(AON_RTC_BASE + AON_RTC_O_CH0CMP) = 327; // 10ms @ 32.768kHz // RTC事件路由到ADC启动(通过AON_PROG1和CPUIRQSEL30) HWREG(AON_EVENT_BASE + EVTOMCUSEL) = (HWREG(AON_EVENT_BASE + EVTOMCUSEL) & ~EVTOMCUSEL_AON_PROG1_EV_M) | (0x23 << EVTOMCUSEL_AON_PROG1_EV_S); // RTC通道0事件 HWREG(EVENT_BASE + CPUIRQSEL30) = 0x02; // AON_PROG1事件 // ADC完成配置为触发DMA HWREG(AUX_EVCTL_BASE + AUX_EVCTL_O_DMACTL) = AUX_EVCTL_DMACTL_REQ_MODE_SINGLE; HWREG(EVENT_BASE + UDMACH7BSEL) = 0x70; // AUX ADC完成事件 // DMA完成触发CPU中断 HWREG(EVENT_BASE + CPUIRQSEL24) = 0x27; // 固定为DMA完成事件 NVIC_EnableIRQ(DMA_IRQn);

这套事件驱动的架构彻底改变了我的编程思维——从“CPU中心”转向“事件中心”。CPU不再是忙碌的调度员,而是变成了被事件唤醒的专家,只在需要时才出手处理关键任务。这种思维转变,可能是CC13x2/CC26x2事件系统带给开发者最大的价值。

http://www.jsqmd.com/news/1264577/

相关文章:

  • TI 68xx系列MCU控制寄存器实战:从原理到安全配置与调试
  • 智能法务助手:NLP与规则引擎驱动的合同审查系统
  • Spring Boot+Vue项目Docker容器化实战指南
  • 如何通过D2DX三步让经典暗黑破坏神2在现代PC上焕发新生:终极宽屏补丁与高帧率优化指南
  • 2026年云南酸辣粉供应厂家精选:口碑企业深度解析 - 装修教育财税推荐2026
  • Cursor Router智能模型路由:AI编程助手调度实战指南
  • 心电AI跨域失效问题与域泛化技术解析
  • Python+RAG构建智能知识库系统实战
  • 免费开源鼠标连点器终极指南:3分钟快速上手跨平台自动化点击
  • Windows平台libpsl编译指南与域名处理实践
  • 【分布式系统与 RPC 框架系列】从单机瓶颈到远程调用:一文理解分布式架构与 RPC 原理
  • 腾讯云IMA平台RAG技术实战:零基础构建智能问答系统
  • 3大核心优势:免费离线的智能OCR识别方案
  • RAG智能问答系统:架构设计与优化实践
  • (2026最新)孝感漏水检测维修一站式上门服务-本地专业防水补漏公司TOP5推荐:暗管漏水检测精准定位 - 安佳防水
  • 企业级助农管理系统管理系统源码|SpringBoot+Vue+MyBatis架构+MySQL数据库【完整版】
  • CC32xx电源管理实战:从硬件架构到低功耗代码实现
  • 终极阴阳师自动化助手OAS:解放双手的完整游戏管理解决方案
  • 深入解析TI CC254x无线核心:数据包、RSSI与链路层引擎实战指南
  • 基于CycleGAN的图像去雾算法优化与实践
  • 电力安全三维数字化管理:技术架构与应用实践
  • 如何永久保存你的微信聊天记忆:完全免费的本地化数据管理方案
  • 终极PS4存档管理神器:Apollo Save Tool完全使用指南
  • 无人机巡检图像数据集在智慧交通中的应用与优化
  • 可控AI在高曝光内容创作中的实践与优化
  • 2026年优选:江苏地区备受赞誉的高压胶管编织机服务商解析 - 装修教育财税推荐2026
  • Monday.com AI转型解析:智能工作流平台的技术架构与开发实践
  • AI如何优化学术写作流程与格式规范
  • Ubuntu 22.04部署CUDA 12.8与cuDNN 8.9.6全指南
  • TI AWR16xx雷达芯片MPU、ECC与测试模式寄存器配置实战