编译器 arm-none-eabi-gcc v4.9.3 优化了对指针的远离操作

Compiler arm-none-eabi-gcc v4.9.3 optimizes away operations to pointers

当我为我的 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
HAL_UART_RxCpltCallback 在每次成功接收 UART 后被调用。

#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);
}
volatile irq_instance *uart_irq

表示 uart_irq 指向的东西是易变的。但是

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

正在查看指针本身,而不是被指向的东西。如果指针本身也是易变的,看看你的代码,那么声明它是这样的:

volatile irq_instance * volatile uart_irq

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

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

结合使用

变量uart_irqvolatile,不只是它指向什么...这样定义它:

extern irq_instance * volatile uart_irq;