This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] [参考译文] [常见问题解答]处理 MSP430系统复位事件

Guru**** 1135610 points
Other Parts Discussed in Thread: MSP430F5529
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/746272/faq-handling-msp430-system-reset-events

主题中讨论的其他器件:MSP430F5529

处理系统复位事件

MSP430提供多个系统复位中断事件。 这些事件包括欠压复位(BOR)、看门狗超时(WDTTO)或监控器高侧欠压(SVSH)等事件。

当一个复位发生时,MSP430 CPU 的系统外设(SYS)记录事件的原因。 与 MSP430上的其他分组中断一样、您可以通过读取相关的中断矢量寄存器来确定引起中断的事件;在这种情况下、该寄存器称为 SYSRSTIV (系统复位中断矢量)。

中断向量寄存器根据发生的最高优先级事件返回一个数字。 例如、对于 MSP430F5529上的 SYSRSTIV、事件(和相关的枚举)包括:

注意:请查看器件的相关用户指南和数据表、了解准确的 SYSRSTIV 寄存器说明。  

读取 SYSRSTIV 寄存器

在 MSP430上处理分组中断的最常用方法是使用 switch 语句读取相关的中断矢量寄存器、以解密当前挂起的最高优先级事件。

‘F5529 SYSRSTIV 的示例如下:

switch (__even_in_range (SYSRSTIV、SYSRSTIV_PMMKEY)
){
案例 SYSRSTIV_NONE: 中断; //无中断挂起
案例 SYSRSTIV_BOR: 中断; // SYSRSTIV:BOR
案例 SYSRSTIV_RSTNMI: 中断; // SYSRSTIV:RST/NMI
案例 SYSRSTIV_DOBOR: 中断; // SYSRSTIV:执行 BOR
案例 SYSRSTIV_LPM5WU: 中断; // SYSRSTIV:端口 LPM5唤醒
案例 SYSRSTIV_SECYV: 中断; // SYSRSTIV:安全违规
案例 SYSRSTIV_SVSL: 中断; // SYSRSTIV:SVSL
案例 SYSRSTIV_SVSH: 中断; // SYSRSTIV:SVSH
案例 SYSRSTIV_SVML_OVP: 中断; // SYSRSTIV:SVML_OVP
案例 SYSRSTIV_SVMH_OVP: 中断; // SYSRSTIV:SVMH_OVP
案例 SYSRSTIV_DOPOR: 中断; // SYSRSTIV:执行 POR
案例 SYSRSTIV_WDTTO: 中断; // SYSRSTIV:WDT 超时
案例 SYSRSTIV_WDTKEY: 中断; // SYSRSTIV:WDTKEY 冲突
案例 SYSRSTIV_KEYV: 中断; // SYSRSTIV:闪存密钥违反
案例 SYSRSTIV_FLLUL: 中断; // SYSRSTIV:FLL 解锁
案例 SYSRSTIV_PERF: 中断; // SYSRSTIV:外设/配置区域获取
案例 SYSRSTIV_PMMKEY: 中断; // SYSRSTIV:PMMKEY 违规
默认值: 中断;
} 

通过从'430f5529.h'文件复制/粘贴 SYSRSTIV_值来快速创建此切换语句。 每个 MSP430器件都有自己的相关头文件、该文件定义了该器件中的寄存器符号。  

您在哪里使用 IV 切换用例语句?

如果您已经编写了 switch case 语句来处理中断,例如 GPIO 端口或计时器,那么您可能已经知道如何使用它们。 作为快速复习,下面是处理 GPIO 中断的示例。

您通常会在中断服务例程中找到切换情况语句。 您可以通过执行两项操作来创建中断服务例程:(1)使用_interrupt 关键字创建中断函数;(2) vector pragma 告知 MSP430代码生成工具将下一个函数的地址放入中断矢量表中。

#pragma vector=Port1_vector
__interrupt void button_ISR (void){switch (__even_in_range (P1IV、10))
}{
情况0x00:中断;//无
情况0x02:中断;//引脚0
情况0x04:中断;//引脚1
情况0x06:中断;//引脚2
案例0x08:中断;//引脚3
情况0x0A:中断;//引脚4
情况0x0C:中断;//引脚5
情况0x0E:中断;//引脚6
情况0x10:中断;//引脚7
默认值:_never_executed();

GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);
中断;
} 

请注意、由于在运行中断服务例程(ISR)时禁用了中断(默认情况下)、因此当您的中断响应代码不仅仅是读取或写入寄存器(如上例所示)时、您需要小心谨慎。 如果您的代码涉及更多,我们强烈建议您在 ISR 函数中设置一个标志,并在 main()中处理事件。

应在何处处理 SYSRSTIV?

您的第一个反应可能是创建一个与上面显示的 GPIO 中断示例类似的复位 ISR 函数。 (…,这是我们试图做的事情 它失败了。)

问题最终是工具忽略以下行:

#pragma vector=reset_vector 

即使器件头文件定义了 RESET_Vector、工具也会忽略 pragma… 这是一件好事。 复位矢量由 C 编译器使用函数 c_int00()自动处理。 此函数处理各种操作,如设置堆栈、初始化全局和静态变量以及分支到 main()。 由于您可能不想从头开始重写此函数,因此这些工具忽略了 RESET_Vector #pragma 是很好的。 (如果您真的很好奇,可以在编译器运行时支持(RTS)库附带的源文件 boot.c 中找到此函数。)

处理 SYSRSTIV 的最简单方法是将代码放置在 main()函数的开头。 在本例中,我们决定创建一个 Reset_ISR()函数并从 main()调用它,如下所示:

void main (void){

//停止看门狗计时器
WDT_A_HOLD (WDT_A_base);
//确定先前复位事件
RESET_ISR()的原因;
//初始化 GPIO
initGPIO();
while (1)
{
__NO_OPERATION ();
}


}void Reset_ISR (void){

switch (__even_in_range (SYSRSTIV、SYSRSTIV_PMMKEY)
}{
案例 SYSRSTIV_NONE: //无中断挂起
__no_operation();
中断;
案例 SYSRSTIV_BOR: // SYSRSTIV:BOR
__no_operation();
中断;
案例 SYSRSTIV_RSTNMI: // SYSRSTIV:RST/NMI
__no_operation();
中断;
案例 SYSRSTIV_DOBOR: // SYSRSTIV:执行 BOR
__no_operation();
中断;
案例 SYSRSTIV_LPM5WU: // SYSRSTIV:端口 LPM5唤醒
__no_operation();
中断;
案例 SYSRSTIV_SECYV: // SYSRSTIV:安全违规
__no_operation();
中断;
案例 SYSRSTIV_SVSL: // SYSRSTIV:SVSL
__no_operation();
中断;
案例 SYSRSTIV_SVSH: // SYSRSTIV:SVSH
__no_operation();
中断;
案例 SYSRSTIV_SVML_OVP: // SYSRSTIV:SVML_OVP
__no_operation();
中断;
案例 SYSRSTIV_SVMH_OVP: // SYSRSTIV:SVMH_OVP
__no_operation();
中断;
案例 SYSRSTIV_DOPOR: // SYSRSTIV:执行 POR
__no_operation();
中断;
案例 SYSRSTIV_WDTTO: // SYSRSTIV:WDT 超时
__no_operation();
中断;
案例 SYSRSTIV_WDTKEY: // SYSRSTIV:WDTKEY 冲突
__no_operation();
中断;
案例 SYSRSTIV_KEYV: // SYSRSTIV:闪存密钥违反
__no_operation();
中断;
案例 SYSRSTIV_FLLUL: // SYSRSTIV:FLL 解锁
__no_operation();
中断;
案例 SYSRSTIV_PERF: // SYSRSTIV:外设/配置区域获取
__no_operation();
中断;
案例 SYSRSTIV_PMMKEY: // SYSRSTIV:PMMKEY 违规
__no_operation();
中断;
默认值:中断;
}
} 

当然,您需要用应用程序所需的代码替换上面的__no_operation()调用。

最后、编译器确实提供了一种将代码插入 c_int00()复位函数的方法。 如果已定义、复位函数会调用一个名为_system_pre_init ()的函数。 虽然我们的首选是显式处理 main()中的复位评估,但如果有迫切需要,使用 pre-init 函数可以更早地处理事件。