Reputation: 139
When I compile my code for my STM32F429 CPU everything works fine when I use the -O0
flag but as soon as I use a higher optimization (-O1, -O2, and -O3)
the code breaks.
I'm using the CMSIS+HAL libraries from ST and some basic code.
The problem is that even though *uart_irq
is defined as volatile
the if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART)
in the main loop is never evaluated.
I have tried to define uart_irq
as a volatile void *
without success.
The only thing that work is if uart_irq
is defined as a volatile uint32_t
and the integer is cast to a irq_instance
when used as the compiler wont remove that during optimization.
I would be happy if anybody would shed some light on the problem.
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
The receive
pointer is freed inside 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
The HAL_UART_RxCpltCallback
are called after each successful UART receive.
#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);
}
Upvotes: 1
Views: 339
Reputation: 144715
The variable uart_irq
is volatile
, not just what it points to... Define it this way:
extern irq_instance * volatile uart_irq;
Upvotes: 0
Reputation: 12999
If I read this correctly then you are changing the uart_irq
inside the IRQ handler and it's this change of pointer value that the optimizer cannot see in the regular program flow and hence is optimizing away.
The correct declaration for a volatile pointer is irq_instance * volatile uart_irq
. The way that you have declared it tells gcc that the value pointed to by the pointer is volatile. If this is also the case then you may combine the two with volatile irq_instance * volatile uart_irq
.
Upvotes: 1
Reputation: 1736
volatile irq_instance *uart_irq
says that the thing pointed to by uart_irq is volatile. But
if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART)
is looking at the pointer itself, not the thing that's being pointed to. If the pointer itself is also volatile, which looking at your code it is, then declare it like this:
volatile irq_instance * volatile uart_irq
Upvotes: 1