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.

[参考译文] TM4C123GH6PM:如果控制器在 ISR 执行期间复位、则不会发生 GPIO 中断

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/626337/tm4c123gh6pm-gpio-interrupt-not-happening-if-controller-resetted-during-isr-execution

器件型号:TM4C123GH6PM

我正在调试代码、并在 ISR 被处理时重新启动代码。 不过、在复位后、中断停止被检测。

如果我在程序中的任何位置重新启动代码、则不会出现此问题、但如果我在 ISR 中复位代码、则会发生此问题。

注意:我在 ISR 开始时清除中断。

这是正常现象还是有解决此问题的方法?

我的代码:

/*!
*@作者 Yash Bansod
*@日期 2017年9月19日
*
*@简介 PWM 伺服
*@详细信息 程序通过
*控制外部伺服电机的位置 改变 PWM 的占空比。 占空比可增加
* 单击板载开关 SW2 (PF0)或通过单击 SW1 (PF4)减小。
* PWM 模块。
*@注意 tm4c123ghpm_startup_ccs.c 包含
*的矢量表 微控制器。 它经过修改、可在
*上执行指定的 ISR Timer0A 和 PortF 中断。
*/
/*------------------ 包含文件 ---------- */
#include //标准整数类型库
#include //标准布尔类型库
#include "inc/tm4c123gh6m.h" // Tiva C
#include "inc/hw_memmap.h"上中断和寄存器分配的定义 //定义 Tiva C 系列器件存储器映射
的宏#include "inc/hw_types.h" //定义常用类型和宏
#include "inc/hw_gpio.h" //为 GPIO 硬件定义宏
#include "inc/hw_pwm.h" //为脉宽调制(PWM)端口
#include "driverlib/debug.h"定义和宏 //用于帮助调试驱动程序库
#include "driverlib/PWM.h"的宏 // PWM 端口的 API 函数原型
#include "driverlib/sysctl.h" //为 DriverLib
的系统控制 API 定义和宏#include "driverlib/interrupt.h" //为 DriverLib
的 NVIC 控制器 API 定义和宏#include "driverlib/gpio.h" //为 DriverLib 的 GPIO API 定义和宏
#include "driverlib/pin_map.h" //所有器件的外设到引脚的映射
#include "driverlib/rom.h" //为 driverLib 的 ROM API 定义和宏

#define PWM_FREQUENCY 50 //为 PWM 信号的频率定义一个宏,单位为 Hz

/*------ 全局变量 ---------- /uint32_t
ui32Period; //用于存储 PWM 时间周期
的变量 volatile uint8_t ui8Adcust = 75; //可用于存储 LED 占空比的变量

/*------ 函数原型 ---------- */
void PortFIntHandler (void); // GPIO 端口 F ISR 的原型

/*------------------------------------------------------- 主程序 ---------- */
int main (void){
//将系统时钟设置为80MHz,将 PWM 模块时钟设置为1.25MHz
ROM_SysCtlClockSet (SYSCTL_SYSDIV_2_5 |SYSCTL_USE_PLL |SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHz);
ROM_SysCtlPWMClockSet (SYSCTL_PWMDIV_64);

//启用外设 PortF、PortD 和 PWM1的时钟
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_PWM1);
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);

//将 PD0配置为 PWM 信号(PWM 模块1发生器0)
ROM_GPIOPinTypePWM (GPIO_PORTD_BASE、GPIO_PIN_0);
ROM_GPIOPinConfigure (GPIO_PD0_M1PWM0);

//删除开关 SW2 (连接到 PF0)上的锁定并提交更改
HWREG (GPIO_PORTF_BASE + GPIO_LO_LOCK)= GPIO_LOCK_KEY;
HWREG (GPIO_PORTF_BASE + GPIO_CR)|= GPIO_PIN_0;
HWREG (GPIO_PORTF_BASE + GPIO_LO_LOCK)= 0;

//将 PF0、PF4设置为输入并将其配置为上拉
ROM_GPIODirModeSet (GPIO_PORTF_BASE、GPIO_PIN_4|GPIO_PIN_0、GPIO_DIR_MODE_IN);
ROM_GPIOPadConfigSet (GPIO_PORTF_BASE、GPIO_PIN_4 | GPIO_PIN_0、GPIO_Strength _2mA、GPIO_PIN_TYPE_STD_WPU);

//为 PF0和 PF4配置和启用中断
ROM_IntEnable (INT_GPIOF);
ROM_GPIOIntTypeSet (GPIO_PORTF_BASE、GPIO_PIN_4 | GPIO_PIN_0、GPIO_FALLING_EDGE);
GPIOIntEnable (GPIO_PORTF_BASE、GPIO_INT_PIN_0 | GPIO_INT_PIN_4);
//主机中断启用所有中断的 API
ROM_IntMasterEnable();

//计算 PWM 模块的定时器周期。
uint32_t ui32PWMClock = SysCtlClockGet ()/64;
ui32Period =(ui32PWMClock / PWM_FREQUENCY)- 1;
//将 PWM1 Genrator0配置为在递减计数模式下工作
ROM_PWMGenConfigure (PWM1_base、PWM_GEN_0、PWM_GEN_MODE_DOWN);
//将计算的时间段加载到 PWM1模块的 Generator0
ROM_PWMGenPeriodSet (PWM1_base、PWM_GEN_0、ui32Period);

//将 PWM 占空比设置为指定值
ROM_PWMPulseWidthSet (PWM1_base、PWM_OUT_0、ui8Adust * ui32Period / 1000);
//启用 PWM 模块1的 PWM0引脚作为输出
ROM_PWMOutputState (PWM1_base、PWM_OUT_0_bit、true);
//启用 PWM 发生器
ROM_PWMGenEnable (PWM1_base、PWM_GEN_0);

while (1);
}/*

------------------------------------------------------- 函数定义 ---------- //
void PortFIntHandler (void){
//用于 GPIO PortF 中断处理的 ISR
GPIOIntClear (GPIO_PORTF_BASE、GPIO_INT_PIN_4 | GPIO_INT_PIN_0);

//如果按下 SW1 (PF4)、则减小占空比
if (ROM_GPIOPinRead (GPIO_PORTF_BASE、GPIO_PIN_4 | GPIO_PIN_0)= GPIO_PIN_0){
ui8Adife--;
if (ui8Adust < 50){
ui8Ad正义= 50;
}
ROM_PWMPulseWidthSet (PWM1_base、PWM_OUT_0、ui8Adust * ui32Period / 1000);
}
//如果按下 SW2 (PW0)、则增加占空比
if (ROM_GPIOPinRead (GPIO_PORTF_BASE、GPIO_PIN_4 | GPIO_PIN_0)= GPIO_PIN_4){
ui8Adife++;
if (ui8Adust > 100){
ui8Adsit= 100;
}
ROM_PWMPulseWidthSet (PWM1_base、PWM_OUT_0、ui8Adust * ui32Period / 1000);
}
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Yash、
    您使用的是 CCS 吗?
    当您说"重新启动代码"时、您是否在调试器控制界面上点击了带有"循环箭头"的按钮?
    我的经验是、在调试期间重新启动代码会导致问题、或者至少是不确定性、应该避免这种情况。 我不会像您说的那样将其称为"问题"、因为调试代码时当然还有其他方法不会频繁地重新启动代码。 让我们看看其他人对这件事的评价是不是预期的、但"留下"可能还不错...
    此致
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    描述的很好,布置的很好——干得好。  (IMHO)

    我们是否可以问:

    • 您对"如何重置 MCU"的描述
    • 您对"How you verified (如何验证)"进行此类复位(在 ISR 期间/内部)的描述?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Bruno、
    感谢您的参与。 "重新启动"实际上并不是一个复位。 它不会将 PC 设置为0x0、而是直接设置到入口点。 这通常是_c_int00。 MCU 硬件未复位。 它可能与重新启动有关、但在 PC 被移动到入口点之前、不会清除中断标志、从而导致后续中断无法被 CPU 正确识别。 通常我不使用重新启动。 我只需单击系统复位。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、我使用的是 CCS7
    是的、我是指调试器控制接口上的循环箭头
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我没有使用复位按钮复位 MCU。 我的意思是、在 ISR 被处理时"重新启动代码"。
    此外、有关在 ISR 中如何重新启动代码的说明:我在第94行上放置了一个断点、当程序在我按下按钮时停止了该断点时、我单击了重新启动代码按钮。
    我将其称为复位、因为我认为这是我按下"Restart"时发生的情况。 现在我知道我错了。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、我们知道几乎所有缺失的细节! CB1的问题"您确定如何重置"、刚刚暂挂? 您是否在 SysCtlClockSet 行附近的某个位置设置了断点、是吗?

    不过,正如查尔斯所指出的,那个箭头没有太多的作用,它并不是一个真正的重置。 我想基本答案是:调试时不要依赖它

    Charles、通过"只需单击系统重置"、您是否意味着 CCS 界面上有一些隐藏的命令? 还是板上的物理复位按钮? 当然、第二个选项会进一步破坏正在进行的调试器、对吧?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、
    我不认为这是不清除中断标志的问题。 正如我提到的,即使在处理 GPIOIntClear ()后重新启动代码,但 PC 仍在 ISR 中,问题仍然存在。
    我还尝试在启用 GPIO 中断后(在第64行之后)添加 GPIOIntClear () API、但我的中断仍然不起作用。 我怀疑这是一个问题、如果在 ISR 被处理时发生复位、我的中断可能不会被处理。
    我想知道一种确保这不是问题的方法。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Bruno、
    我的意思是单击“Run->System Reset (运行->系统重置)”下的“System reset (系统重置)”将重置设备。 是的、这将重置器件、调试将始终启动。 有时我使用 Run->Core Reset 下的 Core 重置。 我认为这只会将 PC 移动到0x0、而不会复位器件。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    否、我在第94行(在 ISR 中)设置断点、以便在程序进入 ISR 时停止程序。
    我无法知道如果在处理 ISR 时复位控制器会发生什么情况。
    不过,我想知道我所做的错误,正是这一问题的根源。 即使重新启动只是导致 PC 跳转到起始点、在我启用到外设的中断后清除中断标志也应该解决这个问题?
    此外、如果我在 ISR 中发生标志清除后重新启动、为什么问题仍然存在。
    注意:如果我在其他任何位置(在 main 中)重新启动代码、则不会发生此问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Yash、
    我的意思是:这里没有问题、因为在"复位后、当硬复位恰好在程序之前为 ISR 提供服务时、最终产品不会进入 ISR 的风险"中。
    这可能只是由 CCS 在调试期间执行的重新启动函数引起的一些程序指针混乱。
    但是、如果您想进行双次检查、以下是一个简单的想法:再次执行您的"在 ISR 内重新启动"、并让程序运行。 然后、它将运行 while (1)循环、对吧? 按下并松开按钮。 您可能没有收到中断、代码永远不会进入 ISR -但无论如何会暂停执行、查看 GPIO 中断寄存器、让我们知道是否设置了该特定的中断标志。 然后、我们可以从中获取。
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢您、这解决了我的问题。 在处理 ISR 时、我尝试了系统和内核复位、中断仍在运行。 谢谢你。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Yash、
    您对进行了编译器优化吗? 您想尝试一件事吗? 关闭优化并重试、看看它是否会产生影响。 有时在进行优化后、您放置在 C 窗口中的断点可能与实际的汇编代码不对应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Yash、
    如果您对使用系统/内核复位进行调试感到满意、那么您可以尝试体验编译器优化。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我没有编译器优化。 我正在调试模式下进行调试、所有优化均已关闭。 无论如何、非常感谢支持、只有当我重新启动代码时、问题才会发生、如果我重置代码则不会发生。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢、我在释放模式下尝试了它、它在复位后也在工作。