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/MSP430FR5969:始终读取0xFF的调试表达式

Guru**** 2589300 points
Other Parts Discussed in Thread: MSP430FR5969

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/633842/ccs-msp430fr5969-debug-expressions-read-0xff-always

部件号:MSP430FR5969
主题中讨论的其他部件:MSP430WARE

工具/软件:Code Composer Studio

调试表达式始终读取0xFF (例如,变量的最大值取决于数据类型)。

这些程序不能按预期工作,就好像变量实际上达到了最大值一样。

如果不进行调试,整个过程似乎就会按预期工作。

过去的一切都是正常的,突然就不能再工作了。 已更新至CCS 7.3 ,问题仍然存在。

问题也可通过简单的示例直接从tirrex中解决。

在本例中,msp430fr59xx_lpm3-5_02.c始终将LED设置为亮起,因为ledstate在调试时始终读取0xFF。

如果不进行调试,LED指示3.5 灯似乎会闪烁,即使它不应该闪烁-例如,当MSP处于L黎巴嫩 时,LED指示灯熄灭,我认为它不应该闪烁。

(因此,它可能仍会读取0xFF,但仅在3.5 中熄灭,启动时再次将其恢复为0xFF...?)

我出什么问题了吗? 欢迎提供任何建议。

请参考tirrex中的3.5 示例:

/*--版权--,BSD_EX
*版权所有(c) 2012,Texas Instruments Incorporated
*保留所有权利。
*
**
允许以源代码和二进制格式重新发布和使用,无论是否进行*修改,只要
满足以下条件*:
*
****重新发布源代码必须保留上述版权
*声明,此条件列表和以下免责声明。
*
***以二进制格式重新分发时,必须在

随分发提供的*文档和/或其他材料中复制上述版权*声明,此条件列表和以下免责声明。
*
***

未经事先书面许可,不得使用德州仪器(TI)公司的名称或*其贡献者的名称来支持或促销由本软件衍生的产品*。
*
*本软件由版权所有者和贡献者"按原样"提供
*,

不提供任何明示或暗示的担保,包括但不限于*对适销性和特定*用途适用性的暗示担保。 在任何情况下,版权所有者或
*贡献者均不对任何直接,间接,附带,特殊,
*示范, 或后果性损害(包括但不限于
*购买替代商品或服务;使用,数据或利润损失;
(*或业务中断),但根据任何责任理论
,*无论是合同,严格责任还是侵权行为(包括疏忽或
*其他),均因使用本软件而导致*
,即使已被告知此类损害的可能性。
*
******************
*
** MSP430代码示例免责声明
*
MSP430代码示例是独立的低级程序
,通常*以高度
*简洁的方式演示单个外设功能或器件功能。 因此,代码可能依赖于设备的开机默认
值*寄存器值和设置(如时钟配置),
在合并多个示例中的代码时必须*小心,以避免潜在的副作用
*。 另请参阅www.ti.com/grace了解GUI,并参阅www.ti.com/msp430ware
*了解外围设备配置的API功能库方法。
*
**--/copyright--*//************************************************************************************************************************

// MSP430FR59xx演示- 3.5 中唤醒间隔为2秒的RTC_B
//
说明:RTC_B模块处于计数器模式,计数器中断
//每2秒触发一次。 然后,设备将进入L黎巴嫩(LLA2N 3.5
),等待// RT1PSIFG中断。 从LPMx.5唤醒后,设备将根据
ledState变量恢复//以前的WFP 1.0 LED状态。 然后,它会切换
//电路板上的WFP 1.0 LED,并将LED状态存储到FRAM内存0x4400中。
//这是一个很好的示例,用于演示如何在
//进入LPMx.5之前保存GPIO状态并在唤醒时恢复GPIO状态。
// WFP 4.6 用作心跳信号,表明设备正在从
BOR重置或LPMx.5唤醒//。
//
// ACLK = 32.768kHz,MCLK = SMCLK = DCO =~1MHz
//
MSP430FR59xx
// --------
// /|\\| Xin|-
// || | 32kHz
// --|RST XOUT|-
// | |//
| WFP 1.0 |--> LED
// | GOOMC|--> Probe Out (探头输出)/LED
//William
Goh
//德州仪器(TI)
// 2013年1月
//使用Code Composer 4.6 v 5.5 和嵌入式工作平台5.60
//******************************************************************************构建
#include <MSP430-h>

void initBoard(void);
void initRtc(void);
void WakeUpLPM35(void);

//将LED的状态存储在FRAM中,其中该变量
//在启动过程中未进行C初始化。 这使得
//某些变量可以在
不需要闪存充电泵的情况下在非易失性存储器中轻松恢复和管理//。
//这样可以加快启动时间。
#if defined(__TI_Compiler_version__)
#pragma NOINIT(ledState);
#pragma location=0x4400
unsigned char ledState;
#Elif defined(__IAR_systems_icc__)
__persistent unsigned char ledState;
#else
//对于其他编译器,将此变量插入FRAM内存
unsigned char ledState;
#endif

{main.int

WDTCTL = WDTPW | WDTHOLD; //停止WDT

//初始化板
initBoard(); // GPIO和CS的常规初始化代码

//确定我们是从LPMx.5还是定期重置。
IF (SYSRSTIV == SYSRSTIV_LPM5WU)
{
//当从3.5 唤醒时,重新连接
WakeUpLPM35(); // LPMx.5唤醒特定初始化代码
__enable_interrupit(); // RTC中断应立即触发...
}
否则
{
ledState = 0; //初始化LED状态变量
P1OUT = 0x00; //初始将P1OUT初始化为零
initRtc(); // RTC_B的常规初始化代码
}

//使用WFP 4.6 LED作为心跳,表示设备重新启动
//来自LPMx.5或完全通电
P4OUT |= BIT6;

//使用定时器A进行短暂延迟,使WFP 1.0 LED闪烁
TA0CCTL0 = CCIE; //已启用TACR0中断
TA0CCR0 = 1000;
TA0CTL = tassel__ACLK | MC__UP; // SMCLK,向上模式
__bis_sr_register (LPM3_bits | GIE);
TA0CTL &=~(MC__UP); //停止计时器

P4OUT &=~BIT6; //清除WFP 4.6 LED

//序列进入3.5。
PMMCTL0_H = PMMPW_H; //打开用于写入的PMM寄存器
PMMCTL0_L |= PMMREGOFF; //并设置PMMREGOFF

//在启用中断的情况下进入3.5 模式。 请注意,此操作会执行此操作
//不返回。 3.5 会通过重置事件退出,结果为
//重新启动代码。
__bis_sr_register (LPM3_bits | GIE);
__no_operation();

返回1;
}

void initBoard(void)
{
//端口配置
//从变量重置之前,恢复WFP 1.0 LED状态
//存储在FRAM中
P1OUT = ledState;
P1DIR = 0xFF;
P2OUT = 0x00;
P2DIR = 0xFF;
P3OUT = 0x00;
P3DIR = 0xFF;
P4OUT = 0x00;
P4DIR = 0xFF;
PJOUT = 0x00;
PJSEL0 || BIT4 | BIT5;
PJDIR = 0xFFFF;

//禁用GPIO开机默认高阻抗模式以激活
//以前配置的端口设置
PM5CTL0 &=~LOCKLPM2;

//设置时钟
CSCTL0_H = CSOKEY >> 8; //解锁CS寄存器
CSCTL1 = DCOFSEL_0; //将DCO设置为1MHz
CSCTL2 =拉美经济体系0 | SESS_3 | SELM_3; //设置ACLK = XT1;MCLK = DCO
CSCTL3 = DIVA_0 | DIVS_0 | DIVM_0; //将所有分禾器设置为1
CSCTL4 &=~LFxTOFF; //启用LFXT1

做
{
CSCTL5 &=~LFxTOFFG; //清除XT1故障标志
SFRIFG1 &=~OFIFG;
} 同时(SFRIFG1和OFIFG); //测试振荡器故障标志
CSCTL0_H = 0; //锁定CS寄存器
}

void initRtc(void)
{
//配置RTC_B
//配置BCD模式,停止RTC,然后启用RTC
RTCCTL01 = RTCBCD | RTCHOLD | RTCTEV_0;
//将RTC第二级分隔器设置为256
// RTC每2秒中断一次
RTCPS1CTL = RT1IP_7 | RT1PSIE;

//启动RTC日历模式
RTCCTL01 &=~RTCHOLD;
}

void WakeUpLPM35(void)
{
//重新配置/启动RTC
//配置BCD模式,停止RTC,然后启用RTC
RTCCTL01 || RTCBCD | RTCHOLD | RTCTEV_0;
//将RTC第二级分隔器设置为256
// RTC每2秒中断一次
RTCPS1CTL = RT1IP_7 | RT1PSIE;

//启动RTC日历模式
RTCCTL01 &=~RTCHOLD;
}


#if defined(__TI_Compiler_version__)|| defined(__IAR_systems_ICC__)
#pragma vector=RTC_vector
__interrupt void RTC_ISR(void)
#Elif defined(__GNUC__) void
__attribute__(RTC(((retch_vector))#void)不

支持编译器#error_error!
#endif
{
开关(__偶 数_IN_RANGE (RTCIV,RTCIV_RTCOFIFO))
{
案例RTCIV_NONE: 中断;
案例RTCIV_RTCRDYIFG:中断;
案例RTCIV_RTCTEVIFG:中断;
案例RTCIV_RTCAIFG:中断;
案例RTCIV_RT0PSIFG:中断;
案例RTCIV_RT1PSIFG:
//切换WFP 1.0 上的LED
P1OUT ^= BIT0;

//将WFP 1.0 输出状态存储为变量
ledState =(P1OUT & BIT0);
中断;
CASE RTCIV_RTCOFIFO:中断;
}
}//

计时器A0中断服务例程
#if defined(__TI_Compiler_version__)|| defined(__IAR_systems_icc__)
#pragma vector=TIMER0_A0_vector
__interrupt Timer_a(void)
#Elif defined(__GNU__) void
__attribute__(interrupt (TIMER0_Timer_a)#void_a) vector


#endif
{
__BIC_SR_REGISTER_ON_EXIT (LPM4_bits);
}

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

    您好Daniel:

    看起来您使用的是较旧版本的代码示例msp430fr59xx_lpm3-5_02.c. 如果我使用最新的MSP430Ware版本3.80 的版本,或者如果我使用TI.com产品文件夹中的版本: www.ti.com/.../slac536 ,那么我看到它使用 #pragma persistent将变量放置在FRAM中,而不是"location"。 这种情况下的问题是,默认情况下,FRAM由内置在较新版本CCS中的MPU工具进行保护。 使用 #pragma persistent将变量放入FRAM时, 这样,编译器和链接器文件就可以自动知道FRAM中有一个变量,并相应地调整FRAM分区-这是正确的方法,因为它可以防止冲突,正如您在使用硬编码地址时看到的那样,因为这需要使用“位置” 自定义MPU设置。 这就是为什么代码示例是最新的,现在我们在新版本的CCS和IAR中默认启用了此MPU保护。

    您是否可以尝试更新版本的代码示例并返回报告?

    此致,
    Katie

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢你Katie,这解决了我的问题。
    事实上,我在理解#pragma persistent,NOINIT或data_section的差异或用例时确实有一些困难。

    在存储必须在3.5 中运行的UART可更新参数时,应选择哪一个?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好Daniel:

    如果要在FRAM中放置变量,以便通过电源周期或LPMx.5事件保留它们,那么正确的方法是使用 #pragma persistent。

    以下是后台发生的情况:如果您在项目中查找设备的链接器文件lnk_msp430fr5969.cmd,您可以看到有一个称为.ti.persistent的部分。 使用 #pragma persistent标记的每个变量都将放置在此.TI.persistent部分中,而不是放置在RAM中的正常.bss或.data部分。 您可以看到.TI.PERSISTAL位于FRAM的开头,地址为0x4400,位于一个名为"READ_WRITE MEMORy"的组中。 基本上,链接程序文件将所有应以读+写访问权限进入FRAM的数据与应以读+执行访问权限进入FRAM的代码(无写入)进行分组。 这样,该工具就可以自动配置MPU,将不同FRAM段的单独权限设置为读取+写入访问权限与读取+执行访问权限。 另请注意.TI.noinit部分在默认情况下是如何放置在RAM中的,这意味着它不会通过LPMx.5模式保留。

    使用data_section"或"location"将变量放置在特定位置,但它们是比持久的更一般的pragma -基本上持久的是特殊的,只是为了将内容置于读+写FRAM中而创建的。 而data_section可用于将数据放入链接程序文件中定义的任何部分(无论您指定哪一个)。 例如,您可以使用 #pragma data_section(x,".ti.persistent")执行与使用 #pragma persistent相同的操作,或者您可以使用data_section.将x放置在.data或修改链接器文件时您自己定义的部分等其他位置。 使用"location"指定某项内容的硬编码地址,但通常最好让链接程序文件放置一些内容以避免任何冲突。

    由于持久用于将数据放置在FRAM中, 非易失性,这也意味着只能在程序加载时使用其默认值加载变量-之后,在连续启动/重置时,c-startup代码将不会重新初始化变量,因为它不是易失性的,因此它仍应保留其最后一个值。 这可防止保留的数据被改写。 在这种意义上,持久性与NOINIT类似,只不过它具有一个定义的默认值,用于首次加载设备时(基本上,它将具有一个使用二进制代码映像写入的值)。

    我希望这有助于使事情更加清晰,而不是进一步混淆-如果您有一些后续问题,请告诉我,我可以尝试解释更多。

    此致,
    Katie