hoop 发表于 2021-6-19 16:52

FAQ0111--代码异常跳过__WFI()命令问题说明

本帖最后由 hoop 于 2022-3-19 13:36 编辑

Questions:应用有时会遇到无法正常进入低功耗的问题?具体表现为执行__WFI()命令进入低功耗时,在无唤醒条件的情况下,系统却直接跳过该命令,代码继续向下执行的现象。 Answer:本文将采用低功耗的Standby模式为例进行分析及说明。【问题根本原因】:进入低功耗调用的__WFI()命令实质为“等待中断”,若在执行__WFI()命令时,NVIC中断内已有处于挂起且未被响应的中断的话,代码就会跳过__WFI命令继续向下执行。此为ARM内核的特性,所有以ARM内核为基础设计的芯片均会存在此现象。【问题解法】:在执行__WFI()前,清除NVIC中断内所有处于挂起状态的NVICpending位。Analysis:本文将采用低功耗的Standby模式加上USART1的接收中断为例进行说明分析。【问题代码段示例】(其中不参与本文说明的代码未贴出):
crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); ///<①开启PWR时钟nvic_irq_enable(USART1_IRQn, 0, 0);          ///<②使能USART1对应的NVIC中断usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE); ///<③使能USART1接收中断__disable_irq();    ///<④禁止所有NVIC中断响应while(usart_flag_get(USART1, USART_RDBF_FLAG) == RESET); ///<⑤等待RDBF标志置位pwc_standby_mode_enter(); ///<⑥进Standby的命令while(1);
【问题逻辑分析】:在实际运行时,当收到数据后1) USART1的RDBF标志被置位;2) 因③的设定,USART1对应的NVIC pending位会跟随RDBF置位;3) 因②的设定,置位的NVICpending位会跳转到对应的中断函数执行;4) 但又因④的设定,代码实际不会跳转到中断函数执行,且NVIC pending位将被一直保持置位状态;5) 故在⑥执行的时,因存在NVIC pending位处于置位状态,系统会直接跳过⑥内的__WFI();命令而继续向后执行,最终PC会停留到代码最后的while(1)语句。【问题解法示例】:为了能正常进入Standby,应用需要在执行__WFI()前清除处于置位状态的NVICpending位,即在前示例代码的⑤⑥之间添加如下代码:
usart_flag_clear(USART1, USART_RDBF_FLAG); ///<清除USART1的RDBF标志NVIC_ClearPendingIRQ(USART1_IRQn); ///<清除USART1对应的NVIC pending标志
【注意事项】:A.   本文只针对调用__WFI()进入的低功耗,__WFE()不存在类似问题;B.   若不使能外设对应的NVIC中断,此时NVIC pending位同样会被置位,不过该置位的NVIC pending位不会对应用产生任何影响;C.   问题解法中,在清除NVIC pending标志前,一定要先清除对应外设的中断标志,如前述示例中,USART1对应的NVIC pending位会跟随RDBF置位,若不先清除RDBF的话,将无法清除其对应的NVIC pending位;D.   在非低功耗应用中,同样需要注意本文所述问题,因为置位的NVIC pending位会带来后续中断函数额外多执行一次的现象;E.   一般带有指令跳转的IAP或其他相关应用会很容易撞到本文所述问题。建议初始设计时要严格注意使用到的外设对应的NVIC pending位的状态。 类型:MCU应用适用型号:AT32全系列主功能:NVIC pending位清除,执行__WFI()进低功耗异常次功能:无
页: [1]
查看完整版本: FAQ0111--代码异常跳过__WFI()命令问题说明