0

I tried to write a Linux driver that writes and reads values to and from GPIO pins. Also, to test the driver I wrote a small shared library ( somehow based on bcm2835 library, I took from there the algorithm that map the pins) and I tested it on a Raspberry B+ model with Raspbian, kernel 3.12.35+.

The code from the driver that writes/reads a value to/from a specific address is:

 switch(ioctl_num)
    {
    case _IOCTL_WRITE:
      {

    driver_info("\t%s:IOCTL Write:0x%08X 0x%08X!\n",DEVICE_NAME,ioctl_buffer.address,ioctl_buffer.write_value);
    p_memory=(unsigned *)ioctl_buffer.address;
    *p_memory=ioctl_buffer.write_value;

      }
      break;
    case _IOCTL_READ:
      {
    driver_info("\t%s:IOCTL Read:0x%08X 0x%08X!\n",DEVICE_NAME,ioctl_buffer.address,ioctl_buffer.write_value);

    p_memory=(unsigned *)ioctl_buffer.address;
    ioctl_buffer.read_value=*p_memory;
    var_to_user=TRUE;
      }
      break;
    default:
      {
    mutex_unlock(&p_gpio_dev->io_mutex);
    return -ENOTTY;
      }
    }

and the function from the library that I tested is:

extern BOOL set_pin(uint8_t pin,uint8_t value)
{
  if(pin<0 || pin>32)
    return FALSE;
  volatile uint32_t *pin_address;
  if(value)
    {
      pin_address=bcm2835_gpio+BCM2835_GPSET0/4+pin/32;
      uint8_t shift=pin%32;
      if(control_device(WRITE_OPERATION,pin_address,(1<<shift))==-1)
    return FALSE;
    }
  else
    {
      pin_address=bcm2835_gpio+BCM2835_GPCLR0/4+pin/32;
      uint8_t shift=pin%32;
      if(control_device(WRITE_OPERATION,pin_address,(1<<shift))==-1)
    return FALSE;
    }
  return TRUE;

}

where

bcm2835_gpio = (uint32_t*)BCM2835_GPIO_BASE;
BCM2835_GPIO_BASE=0x20000000+0x200000;
BCM2835_GPSET0=0x001c;

values took from bcm2835 library.

the function control_device(WRITE_OPERATION,pin_address,(1<

Now, the problem is that I tested the function set_pin() with values set_pin(11,1) and when I run the test program. If I run dmesg to see the output have the next trace:

[  186.487190] gpio:Open...
[  186.487618] gpio:IOCTL...
[  186.487643]  gpio:IOCTL Write:0x2020001C 0x00000800!
[  186.487682] Unable to handle kernel paging request at virtual address 202000$
[  186.499469] pgd = da12c000
[  186.503723] [2020001c] *pgd=00000000
[  186.510236] Internal error: Oops: 805 [#1] PREEMPT ARM
[  186.516776] Modules linked in: gpio(O) ppp_generic slhc snd_bcm2835 snd_soc_$
[  186.544366] CPU: 0 PID: 2201 Comm: test Tainted: G           O 3.12.35+ #730
[  186.552895] task: db301940 ti: da346000 task.ti: da346000
[  186.559788] PC is at device_ioctl+0x13c/0x1e8 [gpio]
[  186.566263] LR is at device_ioctl+0x134/0x1e8 [gpio]
[  186.572660] pc : [<bf0d5184>]    lr : [<bf0d517c>]    psr: 40000013
[  186.572660] sp : da347f00  ip : 20000093  fp : bebb67a4
[  186.586980] r10: 00000000  r9 : bebb6784  r8 : da282580
[  186.593626] r7 : da346000  r6 : 40044b01  r5 : bf0d5824  r4 : bebb6784
[  186.601594] r3 : 2020001c  r2 : 00000800  r1 : 00000000  r0 : 00000028
[  186.609561] Flags: nZcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
[  186.618191] Control: 00c5387d  Table: 1a12c008  DAC: 00000015
[  186.625450] Process test (pid: 2201, stack limit = 0xda3461b0)
[  186.632769] Stack: (0xda347f00 to 0xda348000)
[  186.638578] 7f00: 00000000 2020001c 00000800 00000000 00001000 da28ce60 0000$
[  186.649731] 7f20: bebb6784 c00f7e38 00001000 00000001 c05f4b38 c00c8014 000b$
[  186.661046] 7f40: da346000 80000013 db301940 da193bd0 b6f6f000 00000022 0000[  186.672384] 7f60: 00001000 00000000 40044b01 00000003 00000000 bebb6784 da28[  186.683723] 7f80: 00000000 c00f8058 ffffffff 00000000 00000800 00000000 0000[  186.695150] 7fa0: c000e068 c000dec0 00000800 00000000 00000003 40044b01 bebb[  186.706787] 7fc0: 00000800 00000000 00008664 00000036 00000000 00000000 b6f7[  186.718550] 7fe0: 00000000 bebb6780 b6f2cb00 b6ec000c 60000010 00000003 0000[  186.730491] [<bf0d5184>] (device_ioctl+0x13c/0x1e8 [gpio]) from [<c00f7e38>][  186.743735] [<c00f7e38>] (do_vfs_ioctl+0x3f4/0x5dc) from [<c00f8058>] (SyS_i[  186.756003] [<c00f8058>] (SyS_ioctl+0x38/0x60) from [<c000dec0>] (ret_fast_s[  186.768369] Code: e59f1090 eb4dc1e0 e59d3004 e59d2008 (e5832000)
[  186.768369] Code: e59f1090 eb4dc1e0 e59d3004 e59d2008 (e5832000)
[  186.784109] ---[ end trace 82a3393dd834bb5a ]---
[  186.791604] gpio:Release...

Can someone help? I know something is wrong but I'm not really sure what. I suppose that the address where I try to write is not OK, but that's the way how is calculated in bcm2835 library.

The address where I try to write the value is: 0x2020001C

1

The library you based your examples on is a user land library (like my pigpio and wiringPi).

The Memory Management Unit (MMU) maps the peripherals to a base address of 0x7E000000 for the kernel (not 0x2000000 as used in user land).

  • Ok, I tried with base address 0x7E000000 and I have the same error. I also took another look to the BCM2835-ARM-Peripherals document and I saw that: – 23ars Dec 31 '14 at 12:59
  • Virtual addresses in kernel mode will range between 0xC0000000 and 0xEFFFFFFF. Virtual addresses in user mode (i.e. seen by processes running in ARM Linux) will range between 0x00000000 and 0xBFFFFFFF. Peripherals (at physical address 0x20000000 on) are mapped into the kernel virtual address space starting at address 0xF2000000. Thus a peripheral advertised here at bus address 0x7Ennnnnn is available in the ARM kenel at virtual address 0xF2nnnnnn.But with 0xF2 as base address, seems to work but no voltage on the pin – 23ars Dec 31 '14 at 13:07
  • There is a macro GPIO_BASE defined in the kernel. Perhaps best to use that for kernel modules. – joan Dec 31 '14 at 23:08
  • Thanks! I'll take a look! I think I also managed to map correctly the addresses. I read the datasheet for BCM2835 very carefully and I understood the idea. Thank's a lot for your help! – 23ars Jan 1 '15 at 0:19
0

As an idea for those who maybe will have the same problem. The base address used is 0xF2000000. But you won't have voltage on the pin unless you set the pin mode/direction, output or input, using the GPFSEL registers.

Thanks for you help, joan! It was really helpful because I understood better the address mapping for Raspberry Pi.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.