1

QUESTION:

For educational purposes, I'm in the process of trying to understand exactly how the RaspberryPI interfaces with its GPIO headers. I have a simple program that control an LED on an expansion board that works well. However, I wanted to use GDB to see the program changing bits in the mapped control registers. Normally I would do something like this in GDB:

x /t 0x20200000

But this seems to result in the following error, presumably as the target memory is not in the process space:

0x20200000: Cannot access memory at address 0x20200000

I tried mapping a memory region but didn't seem to help.

mem 0x20200000 0x20208192

I also true to write a function to call from GDB, but couldn't figure out how to write something that returned entire block of memory I am interested in so can view as binary (I don't want to peek each byte as write bits are quite spread out over area). Is there any way I can do this in GDB?

Supporting Code

Memory addresses to map:

#define BCM2708_PERI_BASE   0x20000000
#define GPIO_BASE           (BCM2708_PERI_BASE + 0x200000)

Pointer to mapped memory:

static volatile uint32_t *gpio ;

Mapping routine:

int gpio_init (void)
{
  int      fd ;
  uint8_t *gpioMem;

  if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
  {
    fprintf (stderr, "gpio_init: unable to open /dev/mem: %s\n", strerror (errno)) ;
    return -1 ;
  }

  if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
  {
    fprintf (stderr, "gpio_init: malloc failed: %s\n", strerror (errno)) ;
    return -1 ;
  }

  if (((uint32_t)gpioMem % PAGE_SIZE) != 0)
    gpioMem += PAGE_SIZE - ((uint32_t)gpioMem % PAGE_SIZE) ;

  gpio = (uint32_t *)mmap((caddr_t)gpioMem, BLOCK_SIZE, PROT_READ|PROT_WRITE,  MAP_SHARED|MAP_FIXED, fd, GPIO_BASE) ;

  if ((int32_t)gpio < 0)
  {
    fprintf (stderr, "gpio_init: mmap failed: %s\n", strerror (errno)) ;
    return -1 ;
  }

  return 0 ;
}
Scruffers
  • 4,984
  • 8
  • 35
  • 41

1 Answers1

2

The physical memory address 0x20200000 is being mapped into your process address space at an address stored in the variable gpio, so that's the address you should be examining in gdb. Just print the contents of gpio after gpio_init() has been called and use that value.

As an aside the way the mapping is done is confused. There is no need to allocate a memory block with malloc and then map over it, and it also fails to close the file descriptor. That entire function could be better written as:

int gpio_init (void)
{
  int      fd ;

  if ((fd = open ("/dev/mem", O_RDWR) ) < 0)
  {
    fprintf (stderr, "gpio_init: unable to open /dev/mem: %s\n", strerror (errno)) ;
    return -1 ;
  }

  gpio = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;

  if (gpio == MAP_FAILED)
  {
    fprintf (stderr, "gpio_init: mmap failed: %s\n", strerror (errno)) ;
    close(fd);
    return -1 ;
  }

  close(fd);
  return 0 ;
}
caf
  • 233,326
  • 40
  • 323
  • 462
  • I'm glad I wasn't the only one who looked at that and saw the MAP_FIXED + malloc and wondered what was going on. – Flexo Jul 17 '12 at 07:01
  • Thanks for re-write, will test. Without your changes, executing this 'x /t gpio' results in '0xABCDEF: Cannot access memory at address 0xABCDEF'. Would you expect your changes to alter this? – Scruffers Jul 17 '12 at 09:08
  • @Scruffers: That sounds like `gpio_init()` has not been called yet. – caf Jul 17 '12 at 09:40
  • @caf - I'm sure it has. Reading this thread, perhaps what I am trying is not possible? http://stackoverflow.com/questions/654393/examining-mmaped-addresses-using-gdb?rq=1 – Scruffers Jul 17 '12 at 09:52
  • @Scruffers: Ahh yes - you're right, the `/dev/mem` device obviously doesn't implement ptrace accessors. – caf Jul 17 '12 at 10:00