编译器 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_irq
是volatile
,不只是它指向什么...这样定义它:
extern irq_instance * volatile uart_irq;
当我为我的 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_irq
是volatile
,不只是它指向什么...这样定义它:
extern irq_instance * volatile uart_irq;