C 虽然循环在满足条件后不会达到收支平衡,但如果使用";printf";在while循环中

C 虽然循环在满足条件后不会达到收支平衡,但如果使用";printf";在while循环中,c,embedded,atmel,atmelstudio,C,Embedded,Atmel,Atmelstudio,首先,我会解释一下情况: 这是一个菜单驱动程序,在该程序中,所选选项将继续执行,直到其他选项被输入 该选项通过USB端口馈送至微控制器,ISR调用处理输入命令解析的函数 只要输入了进入无限while循环的选项,程序就可以正常运行 在它进入无限循环后,即使输入停止程序的命令,它也不能从中中断 程序即使在执行while循环时也会输入ISR,这已通过在ISR中使用printf进行了检查 当在ISR中遇到停止程序的命令时,它将设置由while循环检查的标志 现在是奇怪的部分。如果我在while循环中插入

首先,我会解释一下情况:

  • 这是一个菜单驱动程序,在该程序中,所选选项将继续执行,直到其他选项被输入
  • 该选项通过USB端口馈送至微控制器,ISR调用处理输入命令解析的函数
  • 只要输入了进入无限while循环的选项,程序就可以正常运行
  • 在它进入无限循环后,即使输入停止程序的命令,它也不能从中中断
  • 程序即使在执行while循环时也会输入ISR,这已通过在ISR中使用printf进行了检查
  • 当在ISR中遇到停止程序的命令时,它将设置由while循环检查的标志
  • 现在是奇怪的部分。如果我在while循环中插入printf(“%u”,命令),同样的代码也会开始工作
  • sudo代码如下:

    ISR_USB()
    {
        char command=read_from_buffer();
        printf("Entered ISR and command = %c",command); // Prints on serial port and confirms the program entered ISR 
        if(command==STOP_DEMO)
            FLAG_TO_BREAK_WHILE=true;
        printf("%u",FLAG_TO_BREAK_WHILE); // Confirms correct value of flag is set
        command_parser(command);
     }
    
     command_parser(command)
    {
        if(command=='1')
             printf("HELLO WORLD");
        else if(command=='2')
        {
            printf("While started");
            while(!FLAG_TO_BREAK_WHILE); // Gets stuck here 
            /*
             starts working if the above while is replaced by :
             while(!FLAG_TO_BREAK_WHILE)
             {
              printf("%u",FLAG_TO_BREAK_WHILE);
              }
            */
        }
        else if (command=='3')
            printf("stop command executed");
    }
    
    请帮助我了解这里的情况和这种行为


    注意:解析器位于另一个文件中,并且变量是外部变量。

    发生的情况是,
    而(!FLAG)
    正在优化以

    if(!FLAG)
    {
        while(true)
        {
             //do stuff
        }
    }
    

    若要修复此问题,请将标志定义为volatile,编译器将被迫在每次代码访问该标志时从内存中读取该标志。

    发生的情况是,
    而(!flag)
    正被优化为

    if(!FLAG)
    {
        while(true)
        {
             //do stuff
        }
    }
    

    若要修复此问题,请将标志定义为volatile,并且每次代码访问该标志时,编译器都将被迫从内存中读取该标志。

    该标志是否为volatile?嵌入式系统101:人们已经发现这是一件易变的事情。但一般来说,如果添加printf或类似的调用导致成功,而在其他情况下失败,则会发生以下两种情况之一:,1)延迟printf导致了延迟,因此出现了竞态条件2)printf明显更改了代码,因此编译器输出发生了更改2a)这可能是您暴露的编译器错误,或者2b)我们在这里看到的是您暴露的程序员错误。或者一个非常遥远的2c)芯片/处理器错误…在所有情况下,您的第一个想法应该是检查编译器的汇编输出延迟/竞争条件,或者当printf修复某个问题时,您的代码中的一个错误是两个主要候选项。@old_timer是竞争条件,这是我在使用单核嵌入式处理器时应该关注的问题没有操作系统的系统?如果是,那么它是如何在这样一个系统中发生的?对于汇编来说,这是一个很好的调试技巧。许多不能通过直接查看代码来发现的错误都得到了纠正。标志是否易变?嵌入式系统101:人们已经发现这是一件易变的事情。但一般来说,如果添加printf或类似的调用导致成功,而在其他情况下失败,则会发生以下两种情况之一:,1)延迟printf导致了延迟,因此出现了竞态条件2)printf明显更改了代码,因此编译器输出发生了更改2a)这可能是您暴露的编译器错误,或者2b)我们在这里看到的是您暴露的程序员错误。或者一个非常遥远的2c)芯片/处理器错误…在所有情况下,您的第一个想法应该是检查编译器的汇编输出延迟/竞争条件,或者当printf修复某个问题时,您的代码中的一个错误是两个主要候选项。@old_timer是竞争条件,这是我在使用单核嵌入式处理器时应该关注的问题没有操作系统的系统?如果是,那么它是如何在这样一个系统中发生的?对于汇编来说,这是一个很好的调试技巧。很多通过直接查看代码无法发现的错误都得到了纠正。我理解volatile在代码中的用法,但是为什么添加printf会使代码正常工作呢?是因为printf强制编译器检查值还是什么?或者,只有当while为空时才对其进行优化?因为优化器选择不执行此优化。也许您的编译器不知道printf是否对全局内存进行了任何更改,因此它被迫重新评估全局标志。也许昂贵的printf调用让优化器认为这个相对较小的优化不值得。无论哪种方式,这两种情况都很可能是实现定义的,并且可能有一些带有printf的版本会永远循环的实现。@user19961检查反汇编以了解在这种情况下发生了什么。我了解volatile在这段代码中的用法,但为什么添加printf会使代码工作?是因为printf强制编译器检查值还是什么?或者,只有当while为空时才对其进行优化?因为优化器选择不执行此优化。也许您的编译器不知道printf是否对全局内存进行了任何更改,因此它被迫重新评估全局标志。也许昂贵的printf调用让优化器认为这个相对较小的优化不值得。无论哪种方式,这两种情况都很可能是实现定义的,并且可能有一些带有printf的版本会永远循环的实现。@user19961检查反汇编以了解在这种情况下发生了什么。