【问题标题】:Compiler arm-none-eabi-gcc v4.9.3 optimizes away operations to pointers编译器 arm-none-eabi-gcc v4.9.3 优化了指向指针的操作
【发布时间】:2015-12-27 02:33:48
【问题描述】:

当我为我的 STM32F429 CPU 编译代码时,当我使用 -O0 标志时一切正常,但一旦我使用更高的优化 (-O1, -O2, and -O3),代码就会中断。
我正在使用 ST 的 CMSIS+HAL 库和一些基本代码。

问题在于,即使 *uart_irq 被定义为 volatile,主循环中的 if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART)从未评估
我试图将uart_irq 定义为volatile void *,但没有成功。
唯一有效的是uart_irq 被定义为volatile uint32_t 并且在使用时整数被转换为irq_instance,因为编译器在优化期间不会删除它。

如果有人能阐明这个问题,我会很高兴。

  • 这应该是标准行为吗?
  • 这是编译器中的已知错误吗?

main.h

#define API_COMMAND_SIZE 6
typedef struct irq_instance_s
{
    uint8_t SOURCE;
    uint8_t TYPE;   
    uint8_t *CONTEXT;  
    uint8_t SIZE; 
} irq_instance;
extern volatile irq_instance *uart_irq;

main.c
receive 指针在 hande_command 内部被释放

#include "main.h
volatile irq_instance *uart_irq = 0;

int main(void)
{
    uint8_t *receive  = 0;
    <Initialize stuff>

    /* Initialize first UART recieve */
    receive = malloc(API_COMMAND_SIZE);
    while (HAL_UART_Receive_IT(&huart1, receive, API_COMMAND_SIZE) == HAL_BUSY);
    /* Program Main loop */
    while(1) {
        if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART) { /* <---- Problem is here */
            handle_interrupt(uart_irq);
            free((void *)uart_irq);
            uart_irq = 0;
        }
     }
}

stm32f4xx_it.c
在每次成功的 UART 接收后调用HAL_UART_RxCpltCallback

#include "main.h"

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    uint8_t *receive  = 0;
    uart_irq          = calloc(1, sizeof(irq_instance));
    uart_irq->SOURCE  = IRQ_SOURCE_UART;
    uart_irq->CONTEXT = huart->pRxBuffPtr - huart->RxXferSize;
    uart_irq->SIZE    = huart->RxXferSize;
    uart_irq->TYPE    = IRQ_TYPE_COMMAND;

    receive = malloc(API_COMMAND_SIZE);
    while (HAL_UART_Receive_IT(&huart1, receive, API_COMMAND_SIZE) == HAL_BUSY);
}

【问题讨论】:

  • 我不确定我是否完全理解您为什么希望它不稳定。你想让指针还是指针对象是可变的?
  • uart_irq 没有声明为volatile,而是它指向的对象!

标签: c gcc optimization volatile


【解决方案1】:
volatile irq_instance *uart_irq

表示 uart_irq 指向的东西是 volatile 的。但是

if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART)

正在查看指针本身,而不是被指向的东西。如果指针本身也是易失性的,看看你的代码,然后像这样声明它:

volatile irq_instance * volatile uart_irq

【讨论】:

  • 所以第一个volatile 说结构是易失的,第二个说指针本身是易失的。如果你写 volatile irq_instance volatile *uart_irq 会发生什么?
【解决方案2】:

如果我没看错,那么您正在更改 IRQ 处理程序中的 uart_irq,而优化器在常规程序流中看不到指针值的这种变化,因此正在优化。

易失性指针的正确声明是irq_instance * volatile uart_irq。您声明它的方式告诉 gcc 指针指向的值是易失的。如果也是这种情况,那么您可以将两者与volatile irq_instance * volatile uart_irq 结合使用。

【讨论】:

    【解决方案3】:

    变量uart_irqvolatile,而不仅仅是它所指向的...这样定义:

    extern irq_instance * volatile uart_irq;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      相关资源
      最近更新 更多