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.

[参考译文] MSP430F149:不可能的 C 运行方式

Guru**** 2460600 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1430161/msp430f149-impossible-c-behavior

器件型号:MSP430F149

工具与软件:

为什么 main ()不跳到 l_delay ()? 请注意 l_delay()子例程中的 while (1)。 这会导致程序崩溃。 但 无论对 l_delay ()执行什么操作、主循环仍然以65kHz 的频率运行。

此操作在使用 ICC 编译器的 Atmel 处理器(及其端口和位标签)上按预期运行。 多年来、我一直使用类似这样的粗略延迟例程。

#define bit_tst(A,B) (A & B)
#define bit_set(A,B) A |= B
#define bit_clr(A,B) A &= ~B
#define bit_tog(A,B) A ^= B

#include <msp430f149.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "ILI9163lcd.c"

// button ports
#define BUTN_ENTER      !P6IN,BIT0
#define BUTN_UP         !P6IN,BIT1
#define BUTN_DOWN       !P6IN,BIT2
#define BUTN_LEFT       !P6IN,BIT3
#define BUTN_RIGHT      !P6IN,BIT4

#define RUN_LED_ON()    bit_set(P2OUT,BIT7)
#define RUN_LED_OFF()   bit_clr(P2OUT,BIT7)

static init_ports(void)
{
    P1DIR = 0xFF;
    P2DIR = 0xFF;
    P6DIR = 0x0;
    P1OUT = 0x0;
    P2OUT = 0x0;
    P6OUT = 0x1F;  // pull ups
}

void l_delay(int d)
{
   int a,b;
while(1);
    for (a = 0; a < d; a++)
         for (b = 0; b < d; b++);
}

int main()
{
	WDTCTL = (WDTPW | WDTHOLD);  // stop watchdog timer
    init_ports();
//  init_uart();
	RUN_LED_OFF();
//	ILI9163_init(0);
	RUN_LED_ON();
	
	while(1)
	{
	    l_delay(1000);
	    RUN_LED_OFF();
	    l_delay(1000);
	    RUN_LED_ON();
	}

}

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

    Andy、您好!

    也许这正被编译器优化掉吗?  我不熟悉 ICC 编译器、但它可能会被删除。  在调试器中、您是否可以查看反汇编并查看其实际放置在那里?   

    对于 MSP430、我们通常使用" __delay_cycles (10000);"来实现非常基本的延迟。   

    谢谢!

    JD

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

    嗯,不是试图在这里滑稽,但什么给编译器 权限盲目地删除代码没有人工许可? 我将查看反汇编器。

    来自 Atmel 和 ICC_AVR 的20年经验,我对 CCS 印象不是很深刻。

    对于 __delay_cycles (10000)、ICC_AVR 具有类似的延迟库函数。 但在这里我能在 CCS 中找到这些扩展函数的列表吗?

    请注意、它确实会抛出这两条评论:

    "../main.c", line 38: remark #1527-D: (ULP 2.1) Detected SW delay loop using empty loop. Recommend using a timer module instead
    "../main.c", line 39: remark #1544-D: (ULP 13.1) Detected loop counting up. Recommend loops count down as detecting zeros is easier

    但是、my for 循环仍然是完全合法的 C 表达式、并对我而言具有多年的成熟功能。

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

    嗨、Andy、

    幸运的是、编译器让我们不必编写汇编代码、但遗憾的是、大家开始决定如何在该汇编代码中实现我们的 C 代码。   

    您可以在工程设置中关闭编译器优化设置、如下所示:

    如果将其降至0、则会尝试尽可能进行字面解释。   

    希望这对您有所帮助、祝您周末愉快。

    JD

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

    嗯、JD、您 说得对! 在调试模式下运行时,它会跳过 l_delay()调用,就像它甚至没有一样。 这是什么?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在这里不想好笑、但什么赋予编译器在 未经人类许可的情况下盲目删除代码的权利? 我将查看反汇编器。

    好的 C 编译器多年来一直在这样做(删除无效代码)。 编译器分析代码、发现其不执行任何会影响其他任何内容的操作、然后将其删除。 加快速度是关键、因此它不关心您的预期延迟。

    至于 delay_cycles、它不是函数、而是导致编译器生成所需代码。 对于__delay_cycles (1)确实很简单、但对于较长的延迟则更复杂。

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

    "幸运的是、编译器让我们不必编写汇编代码、但不幸的是、我们决定了如何在该汇编代码中实现我们的 C 代码。 "

    是的、我知道优化器可能会产生问题、但我从未听说过这样一个删除代码的消息? 它不是编译器报告的"空循环"。 这是一个延迟例程,没有太多的不同页的 NOP 返回在 PDP-11天,以获得毫秒计时!

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

    好的、Dave、但是我在哪里可以找到这些 CCS 特定函数的库列表? 我  在 K&R C bible 中找不到__delay_cycles (1)。

    我在使用  __delay_cycles (1)时没有问题、实际上这只是为了测试这里的硬件。 但我现在关心的是编译器可能发生的其他变化、这是我不知道的。 生成带有建议的优化报告、但不要盲目修改代码 引导 RTOS CPU 操作。 允许开发人员判断和测试优化改进。

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

    delay_cycles (x)正常工作。 但这并不准确。 使用我的 CCS 禁止方法、我可以调整内部循环以获得精确的计时、其中100实际上为100ms。

    使用其中一个硬件计时器? 是的、我这样做是为了实现非常精确的计时、但这会占用中断时隙、而这可能变得至关重要。 可调延迟方法通常在关键循环之外时足够接近、比_delay_cycles ()更接近。

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

    编译器动态生成代码、因此没有库列表。 它可能需要一个环路、也可能不需要。

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

    关键字"volatile"可用于使编译器独立处理您的代码。 最近这里有一个关于这个的主题。。。

    e2e.ti.com/.../msp430fr5969-question-about-the-use-of-volatile-in-the-blink-the-led-example

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

    误解? 你和 JD 都建议使用__delay_cycles (),这很好。 但是、您是如何知道该函数存在的呢? 我的 K&R C 圣经示例是 C 语言的真实列表。 如果我想知道 printf()有什么作用、我可以在那里查找它。

    关于__ delay_cycles ()的更多问题-传递的值是否是 uint8、uint16、int16、int32? 如果有什么、它会返回什么结果? 此函数的文档在哪里?  

    那么、在 CCS 中哪里可以找到这些非标准编译器特定函数的列表? 我相信还有其他一些非常有用的内容。

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

    CCS 编译器指南针对__delay_cycles ()等内在函数引用了 IAR 指南。