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.

[参考译文] CCS/MSP432P401R:MSP432仅在我暂停并重新启动调试时工作

Guru**** 2603845 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/650571/ccs-msp432p401r-msp432-only-works-when-i-pause-and-restart-debugging

器件型号:MSP432P401R

工具/软件:Code Composer Studio

我将使用适用于 MSP432P401R 的 TI Launchpad。 此程序仅在我调试时才起作用:当我单击"运行"时、它将卡在某个位置、当我单击"暂停"时、它将显示为在 for 循环中、我单击"恢复"、程序继续正常运行、并打印出内容。 如果我在 for 循环后面的 print 语句中放置一个断点、则在我暂停然后重新启动之前、它永远不会到达该断点。

#include "main.h"

/**
* main.c
*/
const Timer_a_UpModeConfig upConfig =
{
Timer_A_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
Timer_A_CLOCKSOURCE_DELAG_64、 // SMCLK/1 = 3MHz
5000、 // 5000个周期
Timer_A_TAIE_INTERRUPT_DISABLE、 //禁用计时器中断
Timer_A_CCIE_CCR0_INTERRUPT_ENABLE,//启用 CCR0中断
Timer_A_do 清除 //清除值
};

const eUSCI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
26、 // BRDIV = 78
0、 // UCxBRF = 2
0、//111、 // UCxBRS = 0
EUSCI_A_UART_NO_奇 偶校验、 //无奇偶校验
EUSCI_A_UART_LSB_FIRST、 // LSB 优先
EUSCI_A_UART_One_stop_bit、 //一个停止位
EUSCI_A_UART_MODE、 // UART 模式
EUSCI_A_UART_LOW_FREQUENCY _BAUDRATE_general//EUSCI_A_UART_overSAMPLING_BAUDRATE_generation //低频率模式
};

int putchar (int _x)
{
MAP_UART_transmitData (eUSCI_A0_BASE、(unsigned char)_x); //输入字符
返回((unsigned char)_x); //返回
}

int getchar (void)
{
返回0xFF; //返回接收到的字符
}

int fputc (int _c、寄存器文件*_fp)
{
返回 putchar (_c);
}

int fputs (const char *_ptr、寄存器文件*_fp)
{
unsigned int i、len;
len = strlen (_ptr);
for (i = 0;i < len;i++){
putchar (_ptr[i]);
}
返回 len;
}

void main (void)
{
volatile uint32_t ii;
MAP_WDT_A_HOLDTimer ();//停止看门狗计时器

MAP_GPIO_setAsOutputPin (GPIO_PORT_P9、GPIO_PIN7);
MAP_GPIO_setOutputLowOnPin (GPIO_PORT_P9、GPIO_PIN7);

/*将 Timer_A1配置为向上计数模式*/
MAP_Timer_A_configureUpMode (timer_A1_base、&upConfig);

/*启用中断并启动计时器*/
MAP_Interrupt_enableSlepOnIsrExit();
MAP_Interrupt_enableInterrupt (INT_TA1_0);
MAP_Timer_A_startCounter (timer_A1_base、timer_A_up_mode);

MAP_Interrupt_enableMaster();

//在 UART 模式下选择 P1.2和 P1.3
MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、
GPIO_PIN2 | GPIO_PIN3、GPIO_PRIMARY_MODULE_FUNCTION);

CS_setDCOCenteredFrequency (CS_DCO_FREQUENCY);//将 DCO 设置为3MHz

/*配置 UART 模块*/
MAP_UART_initModule (EUSCI_A0_BASE、uartConfig);

/*启用 UART 模块*/
MAP_UART_enableModule (EUSCI_A0_BASE);

printf ("测试\n\r");
while (1){
对于(ii = 0;ii < 48000;ii +)
{
}
printf ("Test\n\r");
}
}

void TA1_0_IRQHandler (void)
{
MAP_GPIO_toggleOutputOnPin (GPIO_PORT_P9、GPIO_PIN7);
MAP_Timer_A_clearCaptureCompareInterrupt (TIMER_A1_BASE、
Timer_A_CAPTURECOMPARE 寄存器_0);
} 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我不会得到与您相同的症状、而是"测试"一次、然后什么也没有(断点或否)。 在我的案例中、这是由以下原因造成的:

    >MAP_Interrupt_enableSlepOnIsrExit();

    我建议您不要这样做。 它将导致您的程序在第一次计时器中断后冻结。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Seth、

    在 Bruce 的评论下、我稍微倾向于同意。 明天我必须在办公室中测试这个、但是通过设置 enableSlepOnISRExit、您将在第一个计时器 ISR 之后自动进入睡眠状态。

    我之所以说这种情况可能会发生、是因为:
    1) 1)在调试模式下、器件仅模拟 LPM3和 LPM4模式、从而使时钟系统保持唤醒和活动状态。 因此、如果器件由于您称为 enableSlepOnISRexit 而意外进入某些 LPM3或4状态、那么您将不会看到这会影响您的应用、直到...
    2) 2)在应用模式下运行器件时、 然后、器件实际上会关闭您用于计时器的时钟系统(SMCLK/MCLK (而非 ACLK))、因此您会运行您的第一个 ISR、因为您实际上不会将器件发送到睡眠模式、请点击第一个 ISR、 然后、器件将进入睡眠模式、并且永远不会唤醒、因为您在 ISR 退出时启用睡眠模式、LPM3/4模式将关闭计时器的 SMCLK、并且永远不会再次唤醒。

    总之、正如 Bruce 所说的、不要使用该 API、但该 API 没有明显的错误(我一直使用它)。 如果您希望 ISR 在睡眠模式下运行、最好确保您使用在低功耗模式下保持唤醒状态的时钟为计时器供电。 这些信息可在 MSP432P401R 产品页面的技术参考手册中找到。

    Bruce、如果我错误地描述了您对 enableSlepOnISR 退出函数的反馈、请给我一个更正。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当我在原始 POST 中尝试源时、它在第一个计时器中断(有足够的时间打印一行)后停止、这正是我所期望的、考虑到 SLEEPONEXIT。 删除我指出的行使程序功能按预期工作。 我无法做的是重新生成所描述的精确症状;这意味着可能还有其他事情发生。

    对于 SLEEPONEXIT 的一般使用问题、我有礼貌地表示不同意。 这不是"错误"、但它是一个高级主题。 它在严格控制的情况下提供了一些好处,但也带来了许多危险(种族状况)。 我认为它不应随意使用、一般而言、它不应全局设置(初始化中的"设置并忘记")。 在这场辩论中,理智的人可以不同意,我只是提出另一方。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Bruce、

    我很尊敬地认为我们在同一页上,我在写上述内容时有点累,所以我的观点可能没有那么有效:) 我同意 SLEEPONEXIT 是 ISR 中使用的"高级用户"类型的函数、对于保持严格控制的应用非常有用、我同意它会带来许多竞争条件。 我相信你和我在同一页上。

    对我来说、它在第一个中断后停止是有意义的、因为在退出第一个 ISR 之前没有显式睡眠命令。 我同意不应像您所描述的那样使用它来设置和忘记它。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Seth、

    总之、您遇到的问题应该是 ISR API 退出时的睡眠问题。 请删除该内容、您的应用程序应该可以正常工作。 请确认它是否解决了问题!

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

    这确实可以解决我发布的示例代码上的问题! 感谢您快速回复。

    我是否可以询问"MAP_Interrupt_enableSlepOnIsrExit"为什么位于 TI 资源页面上的所有示例代码中?

    是否有任何方法可以使其与外部时钟配合使用?

    例如、我希望将 I2C 与该程序配合使用、示例代码中包含以下内容:

    while (sendStopCondition = false)
    {
    /*在传输数据时进入睡眠状态*/
    MAP_Interrupt_enableSlepOnIsrExit();
    MAP_PCM_gotoLPM0InterruptSafe ();
    } 

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

    Seth、

    其中包含在 ISR 退出时启用睡眠功能、因为您从中挑选的示例程序很可能是为了展示该示例的低功耗特性而构建的。 因此、开发人员希望器件在睡眠模式之间切换、然后针对 ISR 进行唤醒。

    您会看到在这些示例中,它们具有将器件置于睡眠状态的命令(即 MAP_PCM_gotoLPM3 ();)。

    要在低功耗模式下使用计时器、您需要使用 LFXT 提供 ACLK。 以下代码示例的功能与计时器 A1配置为每秒唤醒一次并读取计时器 A2 TAR 的功能类似。

    /*-版权所有-、BSD
    *版权所有(c) 2017、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *--/版权--*/
    
    *
    * MSP432P4111
    * ----------
    * /|\| |
    * || |
    * -|RST |
    * | |
    * | |
    * | P4.2 |<- TA2CLK、输入已知频率的方波
    * | |
    *
    
    ********************* /*
    DriverLib 包括*/
    #include 
    
    /*标准包括*/
    #include 
    #include 
    
    #define NUMBER_TIMER_CAPTURES 20
    
    //使用 TA2和 TA1进行设计,因为它们位于同一电源域中*//
    * Timer_A2连续模式配置参数*/
    const Timer_A_ContinuousModeConfig continuousModeConfigTA2 =
    {
    Timer_A_CLOCKSOURCE_EXTERNAL_TXCLK、// TAxCLK 时钟源 P4.2
    Timer_A_CLOCKSOURCE_divider _1、 //
    Timer_A_TAIE_INTERRUPT_DISABLE、 //禁用计时器 ISR
    Timer_A_do 清除 //清除计数
    器};
    
    // Timer_A1连续模式配置参数*/
    const Timer_A_ContinuousModeConfig ContinuousModeConfigTA1 =
    {
    Timer_A_CLOCKSOURCE_ACLK、 // ACLK 时钟源
    Timer_A_CLOCKSOURCE_divider _1、 // 32kHz
    Timer_A_TAIE_INTERRUPT_ENABLE、 //启用计时器 ISR
    Timer_A_skip_clear //跳过清除计数
    器};
    
    //静态
    易失性 uint32_t rotationCount = 0;
    
    int main (void)
    {
    /*停止看门狗*/
    MAP_WDT_A_HOLDTimer();
    
    /*终止所有剩余的引脚以最大限度地降低功耗。 这是
    由寄存器访问来完成、以简化并最大程度地减少分支 API
    调用*/
    MAP_GPIO_setAsOutputPin (GPIO_PORT_PA、PIN_ALL16);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_PB、PIN_ALL16);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_PC、PIN_ALL16);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_PD、PIN_ALL16);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_PE、PIN_ALL16);
    MAP_GPIO_setAsOutputPin (GPIO_PORT_PJ、PIN_ALL16);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_PA、PIN_ALL16);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_PB、PIN_ALL16);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_PC、PIN_ALL16);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_PD、PIN_ALL16);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_PE、PIN_ALL16);
    MAP_GPIO_setOutputLowOnPin (GPIO_PORT_PJ、PIN_ALL16);
    
    /*启动 LFXT 并从其获取 ACLK 和 BCLK */
    MAP_CS_setExternalClockSourceFrequency (32000、48000000);
    MAP_GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_PJ、
    GPIO_PIN0 | GPIO_PIN1、GPIO_PRIMARY_MODULE_FUNCTION);
    
    /*将 LFXT 设置为最低驱动强度和电流消耗*/
    MAP_CS_startLFXT (CS_LFXT_Drive0);
    
    MAP_CS_initClockSignal (CS_ACLK、CS_LFXTCLK_SELECT、CS_CLOCK_DEVIDER_1);
    
    /*将 P4.2配置为 TA2CLK 的外设输入*/
    MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN2、
    GPIO_secondary 模块功能);
    
    /*配置连续模式*/
    MAP_Timer_A_configureContinuousMode (timer_A1_base、&continuousModeConfigTA1);
    MAP_Timer_A_configureContinuousMode (timer_A2_base、&continuousModeConfigTA2);
    
    /*启用组0内块0和组31内块31的保留
    *组3在进入 LPM3之前、默认情况下启用所有 SRAM 组。
    *
    SYSCTL_A->SRAM_BLKRET_CTL0 = 0x8000000001;
    
    /*禁用高侧电压监视器/监控器*/
    MAP_PSS_disableHighSide();
    
    ////启用“粗鲁”模式,无论
    //如何,都强制设备进入睡眠状态 *未处理的时钟请求
    // *
    MAP_PCM_enableRudeMode();
    
    MAP_Interrupt_enableSlepOnIsrExit();
    MAP_Interrupt_enableInterrupt (INT_TA1_N);
    
    /*启用主中断*/
    MAP_Interrupt_enableMaster();
    
    /*在连续模式下启动 Timer_A0 */
    MAP_Timer_A_startCounter (TIMER_A1_base、TIMER_A_Continuous_mode);
    MAP_Timer_A_startCounter (TIMER_A2_base、TIMER_A_Continuous_mode);
    
    /*转至 LPM3 */
    while (1)
    {
    /*请注意、虽然此示例仅用于 LPM3、但 LPM4本质上是
    仅 LPM3禁用了 WDT_A/RTC_C。 为方便起见、用户可以这样做
    如果希望 API 处理、请使用 MAP_PCM_gotoLPM4 ()函数
    禁用这些组件*/
    MAP_PCM_gotoLPM3 ();
    }
    }
    
    //*********
    //
    //这是 TIMERA 中断向量服务例程。
    ////
    *********
    void TA1_N_IRQHandler (void)
    {
    /*获取计时器 A2计数器(转子计数)*/
    rotationCount = MAP_Timer_A_getCounterValue (timer_A2_base);
    
    /*清除计时器 A2计数器*/
    MAP_Timer_A_clearTimer (TIMER_A2_base);
    
    /*清除计时器 A1中断标志*/
    MAP_Timer_A_clearInterruptFlag (timer_A1_base);
    }
    
    

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

    问题已解决。