I am trying to debug my STM32F446RE Nucleo board using OpenOCD and GDB (launched via VSCode as a visual debug interface) and i am having trouble accessing variables using print
.
Here is my main.c
#include "../architecture/CMSIS/inc/stm32f4xx.h"
#include "system_stm32f4xx.h"
#define WAIT(x) for (int i = 0; i < (x); i++)
inline static void init_led2();
int main() {
init_led2(); // setup led3
while (1) {
#define INDEX 5
GPIOA->BSRR = 1 << INDEX; // set led2 output
WAIT(0x1FFFF); // wait for awhile
GPIOA->BSRR = 1 << INDEX << 16; // reset led3 output
WAIT(0x1FFFF);
#undef INDEX
}
return 0;
}
// led3 is connected to GPIO pin PB3
inline void init_led2() {
#define MASK 3 // 2bit mask
#define INDEX 5 // index of the port
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // enable GPIOA clock
// set the mode to general purpose output
GPIOA->MODER &= ~(MASK << (INDEX * 2)); // clear bit field
GPIOA->MODER |= 1 << (INDEX * 2);
// set output mode to push-pull
GPIOA->OTYPER &= ~(1 << (INDEX));
// set low speed
GPIOA->OSPEEDR &= ~(MASK << (INDEX * 2));
// no pull up/down resistors
GPIOA->PUPDR &= ~(MASK << (INDEX * 2));
#undef MASK
#undef INDEX
}
I have two breakpoints, one at
GPIOA->BSRR = 1 << INDEX; // set led2 output
and the other at:
GPIOA->BSRR = 1 << INDEX << 16; // reset led3 output
And my code runs fine (the LED blinking is working) and i can successfully get into this main loop and stop at these points.
I am trying to use print GPIOA->ODR
to print the output register for my LED to view it but whenever i do so i get and error:
No symbol 'GPIOA->ODR' in current context
Even though i have broken inside the main loop and can see the LED being turned on and off whenever i hit continue.
This same error occurs no matter what i type:
No symbol 'GPIOA' in current context
No symbol 'GPIOA->BSRR' in current context
No symbol 'GPIOA->MODER' in current context
GPIOA->ODR
is a derefence of the field ODR
pointed to by GPIOA
structure which should be the value stored at address 0x40020014
. If i type x 0x40020014
in the debug console window to view that register it actually returns fine and i can even see it toggle on each breakpoint.
why won't print
work and why does it not recognize GPIOA
or any of its member variables/addresses?
STM32 peripherals like GPIOA
are defined using chains of preprocessor macros -- for example:
#define PERIPH_BASE ((uint32_t)0x40000000)
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
By, preprocessor macros are not visible in the debugger -- it is only aware of objects which were defined for the compiler (variables, functions, structures, etc). You can fix this by adding -g3
to your compiler flags; alternatively, you can expand the macro "manually":
print ((GPIO_TypeDef *) 0x40020000)->ODR