Debugging got even better!

While reading an article online (https://nullprogram.com/blog/2023/04/29/) I learned that it is possible to dial up debug information levels with gcc. Previously, I would use a build command of the following form:

arm-none-eabi-gcc -static -mthumb -g -mcpu=cortex-m0 *.c -T linker_script.ld -o main.elf -nostartfiles

This worked fine but when it came to inspecting things like I/O ports defined by macros it left me with lots of work to do in a gdb debug sesssion.

Consider the following definition

typedef struct {                                /*!< (@ 0x48001400) GPIOF Structure                                            */
  __IOM uint32_t  MODER;                        /*!< (@ 0x00000000) GPIO port mode register                                    */
  __IOM uint32_t  OTYPER;                       /*!< (@ 0x00000004) GPIO port output type register                             */
  __IOM uint32_t  OSPEEDR;                      /*!< (@ 0x00000008) GPIO port output speed register                            */
  __IOM uint32_t  PUPDR;                        /*!< (@ 0x0000000C) GPIO port pull-up/pull-down register                       */
  __IM  uint32_t  IDR;                          /*!< (@ 0x00000010) GPIO port input data register                              */
  __IOM uint32_t  ODR;                          /*!< (@ 0x00000014) GPIO port output data register                             */
  __OM  uint32_t  BSRR;                         /*!< (@ 0x00000018) GPIO port bit set/reset register                           */
  __IOM uint32_t  LCKR;                         /*!< (@ 0x0000001C) GPIO port configuration lock register                      */
  __IOM uint32_t  AFRL;                         /*!< (@ 0x00000020) GPIO alternate function low register                       */
  __IOM uint32_t  AFRH;                         /*!< (@ 0x00000024) GPIO alternate function high register                      */
  __OM  uint32_t  BRR;                          /*!< (@ 0x00000028) Port bit reset register                                    */
} GPIO_Type;                                    /*!< Size = 44 (0x2c)                                                          */

#define GPIOA_BASE                  0x48000000UL
#define GPIOA                       ((GPIO_Type*)             GPIOA_BASE)

This allows me to write lines of code like this:

GPIOA->MODER |= (1 << 6); // Make bit 3 an output

In a GDB debug session it is nice to be able to look at the various registers in a port structure. Previously I would have done something like this:

print/x *((GPIO_Type *)0x48000000

This is cumbersome and requires you to know the correct names of the data structures and the various addresses they live at in memory. The blog entry mentioned above however pointed at a better way. The build command is changed as follows:

arm-none-eabi-gcc -static -mthumb -g3 -mcpu=cortex-m0 *.c -T linker_script.ld -o main.elf -nostartfiles

Note the “g3” i.e. turn up debugging information to the max.

Now, when I run a GDB session I can issue commands like this:

print/x *GPIOA

The extra debugging information allows GDB to work through all the macro definitions and show the contents of the port structure. Autocomplete even works :)))

Leave a comment