C GPIO
#11
(08-25-2016, 11:17 AM)MarkHaysHarris777 Wrote:
(08-25-2016, 08:24 AM)martind1983 Wrote: One more question. All the pins led out on the board and which are also dedicated to some peripherals I have to first turn off special functionality before using them as normal GPIO?

No, not necessarily.

... as long as the pins (channels) are not actually being used 'now' you can use them for what-ever you want. But, that's a big if.  If a driver is running that uses the channel, you will need to stop and unload the driver... but, you don't necessarily have to edit the dtb|dts in order to do this.

That said, it is best to use GPIO pins that are 'free' first.  On the diagram , the green and then maybe the blue. The main exception right now is the pin(7) GPIO04 which is s-pwm and used for the LCD backlight... because it is on a pwm channel even though you can turn it on and off (if you have the correct base address, or use sysfs) it still doesn't work right, because it is 'very' dim ... and, it has a pwm signal on it.  In this case you must not only edit the dtb|dts, but also unassociate the pin, and you need to stop the driver and unload it (a lot of work, just use another GPIO pin).

Hello Mark

One more question related to my issue with GPIOs. I already tried to access free pin PC4, but with the same faulty result. Below is part of my C code. Check comments. I do not understand what is the numbering of PIOs.

I use this All-winner user's manual

http://dl.linux-sunxi.org/A64/Allwinner%...20v1.0.pdf

I still do not understand why I cannot access PC4 gpio. I alos tried to change for PC6 which also is free of peripherals and the same without any response.


Thanks for your help. Wink


// map memory image to virtual memory for direct writing in the peripherals
    // BASE_ADDR is 0x01C20000
    p_mem = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR);
    if (p_mem == (void *) -1) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    // convert void * to unsigned long *; gpio variable is type unsigned long pointer
    gpio = (volatile unsigned long *) p_mem;

    /*
     * add offset 0x800 to mapped base address to get to PIO registers
     * plus add offset to PC_CFG0_REG 0x48 to PC4 (PI-2 pin 32) as output,
     * &= ~(3 << 17) should set PC4 to output mode as by default pins are disabled (every pin = 0x7)
     * for output to set to log 1, the same I set offset 0x800, plus I add offset to PC_DATA_REG 0x58
     * and set 1 by |= 0x10 for PC4
     */

    *(gpio + GPIO_REG_OFFSET + 0x48) &= ~(3 << 17);
    *(gpio + GPIO_REG_OFFSET + 0x58) |= 0x10;

    while(active) {
        *(gpio + GPIO_REG_OFFSET + 0x58) |= 0x10;
        sleep(2.5);

        *(gpio + GPIO_REG_OFFSET + 0x58) &= 0x00;

        sleep(2.5);
    }

    return 0;
}
  Reply
#12
For the sake of this discussion, lets keep it to PC4.

... I am going to post a script below written by longsleep which converts Pine GP names to their Pine GPIO number. There are three ways to number the pins on the PI bus (let's just keep the discussion there for now).

Board numbers:  the actual physical number of the pin on the pcb... 

BCM numbers:  the broadcom GPIO numbering scheme

Pine GPIO:  the numbers of the GPIO pins from the Pine perspective.

The following script will convert the name of the pin (in this case PC4) to its Pine GPIO number.  Place the code in a script called sysfs_gpio.sh   chmod it with 0754,  and run it with  ./sysfs_gpio.sh PC4   ... it will return 68.

sysfs_gpio.sh
Code:
#!/usr/bin/python3

import sys
import string

def convert(value):
    value = value.upper()
    alp = value[1]
    idx = string.ascii_uppercase.index(alp)
    num = int(value[2:], 10)
    res = idx * 32 + num
    return res

if __name__ == "__main__":
    args = sys.argv[1:]
    if not args:
        print("Usage: %s <pin>" % sys.argv[0])
        sys.exit(1)

    print("%d" % convert(args[0]))

Try activating the pin(32) , GPIO(12), PineGPIO(68) using sysfs, or using RPi.GPIO-PineA64.

If it works you know that the hardware is not at fault.  If not, there may be something wrong on your board. If it works with sysfs, then try again with your C coding.  Thank you for sharing;  I have not used C to access the GPIO on the PineA64-- very interesting.  Hopefully you will get enough of a hint about the PineA64 numbering with pin 68, PC4, GPIO(12),  pin(32)....

edit: try using 0x44 which is the hex for 68
marcushh777    Cool

please join us for a chat @  irc.pine64.xyz:6667   or ssl  irc.pine64.xyz:6697

( I regret that I am not able to respond to personal messages;  let's meet on irc! )
  Reply
#13
hi, I just did some testing with Pine GPIO68 [ pin 32, GPIO12 ] ... 

... again, try using 0x44 in your C code ( the hex number for GPIO 68 ).  I verified that GPIO68 works well for IN | OUT , defaults to 0 , and drives standard LED brightly with the normal 330 ohm limiting resistor.  I have my LED plugged into the lab board at GPIO12, on pin(32); however, I'm driving the output with sysfs using Pine GPIO68 !

The following code is a bash script that will blink the Pine GPIO68 [ pin 32, GPIO12 ] line seven times:

Put the script in a file, chmod it with 0754, and run with sudo ./blink.sh

blink.sh
Code:
#!/bin/sh

echo 68  > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio68/direction

for i in `seq 1 7`
do
   echo 1 > /sys/class/gpio/gpio68/value
   sleep .35
   echo 0 > /sys/class/gpio/gpio68/value
   sleep .65
done

echo 68  > /sys/class/gpio/unexport


hope this helps you
marcushh777    Cool

please join us for a chat @  irc.pine64.xyz:6667   or ssl  irc.pine64.xyz:6697

( I regret that I am not able to respond to personal messages;  let's meet on irc! )
  Reply
#14
(08-29-2016, 05:25 AM)MarkHaysHarris777 Wrote: For the sake of this discussion, lets keep it to PC4.

... I am going to post a script below written by longsleep which converts Pine GP names to their Pine GPIO number. There are three ways to number the pins on the PI bus (let's just keep the discussion there for now).

Board numbers:  the actual physical number of the pin on the pcb... 

BCM numbers:  the broadcom GPIO numbering scheme

Pine GPIO:  the numbers of the GPIO pins from the Pine perspective.

The following script will convert the name of the pin (in this case PC4) to its Pine GPIO number.  Place the code in a script called sysfs_gpio.sh   chmod it with 0754,  and run it with  ./sysfs_gpio.sh PC4   ... it will return 68.

sysfs_gpio.sh
Code:
#!/usr/bin/python3

import sys
import string

def convert(value):
    value = value.upper()
    alp = value[1]
    idx = string.ascii_uppercase.index(alp)
    num = int(value[2:], 10)
    res = idx * 32 + num
    return res

if __name__ == "__main__":
    args = sys.argv[1:]
    if not args:
        print("Usage: %s <pin>" % sys.argv[0])
        sys.exit(1)

    print("%d" % convert(args[0]))

Try activating the pin(32) , GPIO(12), PineGPIO(68) using sysfs, or using RPi.GPIO-PineA64.

If it works you know that the hardware is not at fault.  If not, there may be something wrong on your board. If it works with sysfs, then try again with your C coding.  Thank you for sharing;  I have not used C to access the GPIO on the PineA64-- very interesting.  Hopefully you will get enough of a hint about the PineA64 numbering with pin 68, PC4, GPIO(12),  pin(32)....

edit:  try using 0x44   which is the hex for 68


Hello Mark

First thank you for your help Smile

However what is the problem? I already know about the possibility to access GPIOs via sysfs. I know when I export pin 68 via gpio class I can then set its functionality and control its output value and this works well.

Event this laberling is in this link I use for refering pins on PI 2 connector

http://joey.hazlett.us/pine64/pine64_pins.html

Even on the bottom is recalculation of pins and even link to some forum's thread about this issue. Wink

However, 1 thing I did not understand that pin labeling. I get the point pin(32) is actual physical pin on PI 2 connector of PINE64 board, PineGPIO(68) is gpio used by sysfs when we access it via gpio class. But what is GPIO(12) labeling?

Right now I am going to my actual issue I want to solve.

I want to control GPIOs through my program written in C code or any other programming languages.
What I want to test is direct memory access when I map /dev/mem file image to virtual memory then I would able to directly write/read GPIO registers

For this I open /dev/mem

fd = open("/dev/mem", O_RDWR | O_SYNC);

then I use given file descriptor "fd" in map function and map it to the address "p_mem" in virtual memory

p_mem = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR);

I use BASE_ADDR which is this value 0x01C20000 and it points to CCU register. I cannot directly start mapping from the address 0x01C20800 which is starting address of PIO registers, because this one is not aligned to page sizes and I get error.

Thus, after mapping it and getting back void pointer p_mem I recast it to unsigned long pointer as we use 64bit architecture and assign it to unsigned long pointer variable named "gpio"

gpio = (volatile unsigned long *) p_mem;

In turn, I use this address and add to it offset GPIO_REG_OFFSET which value is 0x800 and this along with gpio pointer should give me the starting address of PIO register 0x01C20800. Then I also add offset 0x48 which should give me the address of PC configure register 0 (0x01C20848) where the configuration of pin PC4 is located.

*(gpio + GPIO_REG_OFFSET + 0x48) &= ~(7 << 16);
*(gpio + GPIO_REG_OFFSET + 0x48) |= (1 << 16);

By default all data values in register are set to 1 what means all pins have disabled functionality. That is the reason that in code above I first shift 3 zeros starting from position 16, thus, 16-18 are set to zeros after this line. Because for PC4 there are 3 configuration bits and if we want to configure it to the output function we have to set it to 001 value. See manual page 377

http://dl.linux-sunxi.org/A64/Allwinner%...20v1.0.pdf

In the second line I already set bit 16th to 1 what finally gives me value 001 for PC4 pin what in turn should set it to output function. Wink

Next I write to PC Data register (above manual reference page 380) by adding its offset 0x58 to PIO address, actually the same way as described in code above. Wink. And then write into this register value 0xff what should set first 8 pins and with it also pin PC4.

*(gpio + GPIO_REG_OFFSET + 0x58) |= 0xff;

In this case LED connected to PC4 (pin 32 on PI 2 connector of the board) should light. Unfortunately, it does not. So I am not sure where I actually do mistakes. Maybe that manual is not for this release of Allwinner A64 chip or I access pins incorrectly. I also tried to figure out, how I could utilize the value 68 (used for sysfs) in my code.

Any help in this way would be very appreciated. Big Grin

Thank you Mark and also to others.                                           Martin.
  Reply
#15
Martin, I want to thank you too. You have answered many questions I have had about the /dev/mem and about the manual; really, thanks !

It may turn out that there is something over-riding your /dev/mem writes with C (I don't know, I'm just suspicious because I have seen this type of behavior on the Pine board in other areas. (other dts|dtb definitions, and other drivers)

It may also be, and unfortunately probably is, that the manual is out-of-date. We know in fact that the schematic is out-of-date... and we are still waiting to see the schematic that matches the 2G PineA64+ , and we are still waiting for the updated manual. So, we might just have to keep waiting, or keep experimenting. If you know that your GPIO68 works (by using sysfs) then we know this is not a hardware problem! ... and, that the manual you are attempting to follow is probably not correct for this board.

edit: PS... the GPIO12 number is the Raspberry PI Broadcom GPIO pin numbering scheme. It means absolutely 'nothing' for your C code. It is only important for codes library like RPi.GPIO-PineA64 , which is a Raspberry PI GPIO emulator... and can be coded with either BOARD numbering or BCM numbering.

Sysfs must use Pine GPIO numbering. I suspect your C code must use the offsets that match the Pine GPIO numbering scheme.
marcushh777    Cool

please join us for a chat @  irc.pine64.xyz:6667   or ssl  irc.pine64.xyz:6697

( I regret that I am not able to respond to personal messages;  let's meet on irc! )
  Reply
#16
(08-31-2016, 03:47 AM)martind1983 Wrote: However, 1 thing I did not understand that pin labeling. I get the point pin(32) is actual physical pin on PI 2 connector of PINE64 board, PineGPIO(68) is gpio used by sysfs when we access it via gpio class. But what is GPIO(12) labeling?

Right now I am going to my actual issue I want to solve.

I want to control GPIOs through my program written in C code or any other programming languages.
What I want to test is direct memory access when I map /dev/mem file image to virtual memory then I would able to directly write/read GPIO registers

What Mark was saying (and it looks like we were both writing this at the same time, and he beat me in hitting reply Wink) was the pin number, the GPIO number that that pin would be mapped to on a Raspberry Pi, and the GPIO it is mapped to on the Pine64. i.e., if you read across the table from Joey's pinout table, you can see it says

Quote:32 - GPIO 12 - GPIO 68 PC4

That's Pin - PI GPIO - PINE GPIO - Pin Name (from the datasheet)

So if you wanted to control the 32nd pin on the RPi connector, you would be wanting to maniplulate GPIO68 on the pine64 (or GPIO12 on the Raspberry Pi).

Now, since it can be toggled from using sysfs calls from the command line... can you not use System calls in your program to manipulate the GPIOs? Is DMA access a must? If not, depending on how sophisticated you want to make the code, you could probably base it off this Raspberry Pi example, or simplify it down since at it's simplest you really only need to send the export, direction and value commands to control the LED.

I don't know enough about the direct memory access interface to comment on that, but I noticed there was an example for that further up that page I just linked, so maybe that will be of some help or give some ideas?
  Reply
#17
(08-31-2016, 04:14 AM)pfeerick Wrote:
(08-31-2016, 03:47 AM)martind1983 Wrote: However, 1 thing I did not understand that pin labeling. I get the point pin(32) is actual physical pin on PI 2 connector of PINE64 board, PineGPIO(68) is gpio used by sysfs when we access it via gpio class. But what is GPIO(12) labeling?

Right now I am going to my actual issue I want to solve.

I want to control GPIOs through my program written in C code or any other programming languages.
What I want to test is direct memory access when I map /dev/mem file image to virtual memory then I would able to directly write/read GPIO registers

What Mark was saying (and it looks like we were both writing this at the same time, and he beat me in hitting reply Wink) was the pin number, the GPIO number that that pin would be mapped to on a Raspberry Pi, and the GPIO it is mapped to on the Pine64. i.e., if you read across the table from Joey's pinout table, you can see it says

Quote:32 - GPIO 12 - GPIO 68 PC4

That's Pin - PI GPIO - PINE GPIO  - Pin Name (from the datasheet)

So if you wanted to control the 32nd pin on the RPi connector, you would be wanting to maniplulate GPIO68 on the pine64 (or  GPIO12 on the Raspberry Pi).

Now, since it can be toggled from using sysfs calls from the command line... can you not use System calls in your program to manipulate the GPIOs? Is DMA access a must? If not, depending on how sophisticated you want to make the code, you could probably base it off this Raspberry Pi example, or simplify it down since at it's simplest you really only need to send the export, direction and value commands to control the LED.

I don't know enough about the direct memory access interface to comment on that, but I noticed there was an example for that further up that page I just linked, so maybe that will be of some help or give some ideas?

Pfeerick

Thanks for your quick response. Wink

Currently, It does not matter for me which way I use for the purpose of GPIO controlling. It is just going about I want to learn this stuff.

I already did direct memory access GPIOs control for RPi2 I have and it worked. However, I had there also some kind of similar issue. Because first I found some manual for mapping register of previous version of raspberry PI which actually used BCM2835 chip (ARMv6) and RPi2 already uses (ARMv7). If I do not mistake ;Wink

However, between ARMv6 and v7 is one big distinction that is at v7 the base register address starts with different value. Although the rest register's address are not changed, you cannot actually access registers exactly because of that distinction at base address. Fortunately and finally I found it and it worked for me at RPi2. Unfortunately, guys from production somehow have issue to release current and precise manuals for those chips. This is the same for PINE.

I also like the fact that PINE64 has uncompetitive price. However, I am a bit upset of that there are not any good and precise manuals for those chips. I want to do development without constraints. THat is the reason I buy the board Smile

Nevertheless thank you for help Big Grin
  Reply
#18
Not sure if this worked yet for you, but I do see one thing here that looks to me like it could be the reason why your /dev/mem -related gpio access doesn't work: the registers in which the various bits are changed in order to control gpio items are 32-bits, while the pointer-arithmetic that is shown here looks like they deal with 64-bit data sizes.

Looking at the documentation in the linked user-manual, page 373. we see how the addresses for the  PB thru PH gpio control space is organized. The base address is 0x1c20800, which as it isn't page aligned means we will have to pass the masked address to mmap() and then add the offset to the returned pointer afterwards.

Next we see that each letter-block of ports has a group of 9 registers each of which are 32 bits or 4 bytes, so the first (non-existent) PA series would have been from 0x00 to 0x23, then PB continues at 0x24-0x47, then PC goes from 0x48--0x6b and so on.  So far so good.

The problems begin with this:
---------------------
gpio = (volatile unsigned long *) p_mem;
------------------------
The type of the pointer variable gpio isn't shown but the cast suggests it is a volatile unsigned long *gpio; Though the numerical value of this (if we were to use printf("%p") to display it) isn't necessarily the original address 0x01c20000 that we used, it is still effectively pointing at this hardware location, which is 0x800 bytes before the gpios.

Now when we add offsets to such a pointer, these offsets get multiplied by 8, since the size of the unsigned long type in the PineA64 is 8, and thus, when performing the access call:

*(gpio + GPIO_REG_OFFSET + 0x48) &= ~(7 << 16);

being equivalent to

gpio[GPIO_REG_OFFSET+0x48] &= ~(7 << 16);

it is like we are changing some bits in an 8-byte variable located at:
(*0x01c20000+8 * (0x800 + 0x48)) = 0x01c24090

which is far beyond the area where these GPIO control registers actually are.  The arithmetic shown seems to expect that the gpio pointers are to 1-byte data however.

Thus to make this work right, the pointer through which we access the GPIOs have to be defined as pointing to some 32-bit integers, while the arithmetic used for adding the offsets and registers will have to be done as if the pointers are aligned at byte boundaries, so the arithmetic I use here treats it as char *, or we can cast them back and forth from unsigned integers of the appropriate size.

To be sure how big things are, in places like this when we do care, the standard types in stdint.h are nice to have.  I got the following C program working, flashing an LED connected to pin 32 on the Pi-2-bus (P32 as it is labeled on the development POT), which is PC4.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define BASE_ADDR 0x01c20000
#define GPIO_REG_OFFSET 0x800

int main()
{
   int fd;
   void *p_mem;
   volatile uint32_t *gpio;    /* The registers in gpio-space are 32-bits wide. */
   unsigned int offset;        /* offsets from 0x800, so need not be that big */
   unsigned int page_size;     /* Page-size from system, it reports 0x1000 here. */
   int j;

   page_size = sysconf(_SC_PAGESIZE);

   fd = open("/dev/mem", O_RDWR | O_SYNC);
   if(fd == -1)
   {
       /* Very likely if you forget to run this as root ... */
       perror("/dev/mem");
       return(0);
   }

   p_mem = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR);
   if(p_mem == NULL)
   {
       perror("mmap");
       close(fd);
       return(0);
   }

   close(fd);

   offset = GPIO_REG_OFFSET + 0x48;  /* Will aim at the first of the PC control registers, which controls PC7-PC0 */
                                       /* Page 377 in the manual */

   gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset);
   printf("GPIOs at %p\n", gpio);

   *(gpio) &= ~(7 << 16);  /* Set SELECT to 000 for enable or input */
   *(gpio) |= (1 << 16);   /* Set SELECT to 001 for output */

   offset = GPIO_REG_OFFSET + 0x58;  /* Will aim at the the PC data register, which controls state of PC18-PC0 wires */
                                       /* Page 380 in the manual. */
   gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset);
   printf("GPIOs at %p\n", gpio);

   /* flash on and off 20 times */
   for(j = 0; j<20; j++)
   {
       *(gpio) &= ~(0x10);  /* Set bit 4 for PC4 to 0 */
       usleep(500000);
       *(gpio) |= (0x10);   /* Set bit 4 for PC4 to 1 */
       usleep(500000);
   }

   munmap(p_mem, page_size*2);

   return(0);
}

The key thing here is the additions here:

gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset);

where the un-specific pointer p_mem gets cast to a pointer-to-char which has alignment 1, then the offset gets added, and the resulting value is cast to the pointer-to-uint32_t through which we will access the selected 32-bit control or data register.
  Reply
#19
(08-31-2016, 07:27 AM)KnReLe Wrote: Not sure if this worked yet for you, but I do see one thing here that looks to me like it could be the reason why your /dev/mem -related gpio access doesn't work: the registers in which the various bits are changed in order to control gpio items are 32-bits, while the pointer-arithmetic that is shown here looks like they deal with 64-bit data sizes.

Looking at the documentation in the linked user-manual, page 373. we see how the addresses for the  PB thru PH gpio control space is organized. The base address is 0x1c20800, which as it isn't page aligned means we will have to pass the masked address to mmap() and then add the offset to the returned pointer afterwards.

Next we see that each letter-block of ports has a group of 9 registers each of which are 32 bits or 4 bytes, so the first (non-existent) PA series would have been from 0x00 to 0x23, then PB continues at 0x24-0x47, then PC goes from 0x48--0x6b and so on.  So far so good.

The problems begin with this:
---------------------
gpio = (volatile unsigned long *) p_mem;
------------------------
The type of the pointer variable gpio isn't shown but the cast suggests it is a volatile unsigned long *gpio; Though the numerical value of this (if we were to use printf("%p") to display it) isn't necessarily the original address 0x01c20000 that we used, it is still effectively pointing at this hardware location, which is 0x800 bytes before the gpios.

Now when we add offsets to such a pointer, these offsets get multiplied by 8, since the size of the unsigned long type in the PineA64 is 8, and thus, when performing the access call:

*(gpio + GPIO_REG_OFFSET + 0x48) &= ~(7 << 16);

being equivalent to

gpio[GPIO_REG_OFFSET+0x48] &= ~(7 << 16);

it is like we are changing some bits in an 8-byte variable located at:
(*0x01c20000+8 * (0x800 + 0x48)) = 0x01c24090

which is far beyond the area where these GPIO control registers actually are.  The arithmetic shown seems to expect that the gpio pointers are to 1-byte data however.

Thus to make this work right, the pointer through which we access the GPIOs have to be defined as pointing to some 32-bit integers, while the arithmetic used for adding the offsets and registers will have to be done as if the pointers are aligned at byte boundaries, so the arithmetic I use here treats it as char *, or we can cast them back and forth from unsigned integers of the appropriate size.

To be sure how big things are, in places like this when we do care, the standard types in stdint.h are nice to have.  I got the following C program working, flashing an LED connected to pin 32 on the Pi-2-bus (P32 as it is labeled on the development POT), which is PC4.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define BASE_ADDR 0x01c20000
#define GPIO_REG_OFFSET 0x800

int main()
{
   int fd;
   void *p_mem;
   volatile uint32_t *gpio;    /* The registers in gpio-space are 32-bits wide. */
   unsigned int offset;        /* offsets from 0x800, so need not be that big */
   unsigned int page_size;     /* Page-size from system, it reports 0x1000 here. */
   int j;

   page_size = sysconf(_SC_PAGESIZE);

   fd = open("/dev/mem", O_RDWR | O_SYNC);
   if(fd == -1)
   {
       /* Very likely if you forget to run this as root ... */
       perror("/dev/mem");
       return(0);
   }

   p_mem = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADDR);
   if(p_mem == NULL)
   {
       perror("mmap");
       close(fd);
       return(0);
   }

   close(fd);

   offset = GPIO_REG_OFFSET + 0x48;  /* Will aim at the first of the PC control registers, which controls PC7-PC0 */
                                       /* Page 377 in the manual */

   gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset);
   printf("GPIOs at %p\n", gpio);

   *(gpio) &= ~(7 << 16);  /* Set SELECT to 000 for enable or input */
   *(gpio) |= (1 << 16);   /* Set SELECT to 001 for output */

   offset = GPIO_REG_OFFSET + 0x58;  /* Will aim at the the PC data register, which controls state of PC18-PC0 wires */
                                       /* Page 380 in the manual. */
   gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset);
   printf("GPIOs at %p\n", gpio);

   /* flash on and off 20 times */
   for(j = 0; j<20; j++)
   {
       *(gpio) &= ~(0x10);  /* Set bit 4 for PC4 to 0 */
       usleep(500000);
       *(gpio) |= (0x10);   /* Set bit 4 for PC4 to 1 */
       usleep(500000);
   }

   munmap(p_mem, page_size*2);

   return(0);
}

The key thing here is the additions here:

gpio = (volatile uint32_t *) ( (char *) (p_mem) + offset);

where the un-specific pointer p_mem gets cast to a pointer-to-char which has alignment 1, then the offset gets added, and the resulting value is cast to the pointer-to-uint32_t through which we will access the selected 32-bit control or data register.

Hi KnReLe

Thank you for your help man. Very nice and comprehensively answered and also works as you know.

I was also figuring out that one possible way would be immediately after mapping cast void pointer to unsigned int pointer and then to add order number of either of those GPIOs registers. Like normal pointer arithmetic

Problem is there is a hole in manual between the address 0x01c20000 we can map and actual base PIO address. I cannot check how many registers are there. Wink

I saw such a solution for RPI.

However, thank you man Big Grin
  Reply
#20
(09-01-2016, 05:08 AM)martind1983 Wrote:  Very nice and comprehensively answered and also works as you know.
However, thank you man Big Grin

hi,  just for clarification, in your judgement then, is the current manual correct in what it states ( in regard to this thread ) or does it have omissions that we could document more throughly so that others don't have this issue.

In other words, is the above comprehensive explanation in the manual necessary to make sense of what the current manual states, or is the current manual complete as it stands ( in your opinion )?   Thanks.
marcushh777    Cool

please join us for a chat @  irc.pine64.xyz:6667   or ssl  irc.pine64.xyz:6697

( I regret that I am not able to respond to personal messages;  let's meet on irc! )
  Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  RPi.GPIO python module for Pine A64/A64+ aquilegia 98 99,847 07-06-2022, 10:13 AM
Last Post: Zerext
  fm transmitter with gpio weasel18 2 3,599 09-10-2019, 04:28 AM
Last Post: desai_amogh
  How to use dts or other setup to declare gpio pin Interrupt (e.g. a button)? dkebler 1 2,784 06-12-2019, 10:37 AM
Last Post: dkebler
Lightbulb Sample GPIO codes highlighting RPi.GPIO-PineA64 and the PI bus MarkHaysHarris777 6 8,662 06-07-2019, 12:37 AM
Last Post: tllim
Star GPIO, SPI and I2C C++ Lib databit 7 8,783 02-04-2019, 05:45 AM
Last Post: Jeff R
Information Howto: Controlling Pine64 GPIO via the filesystem (sysfs) on linux pfeerick 4 9,955 01-24-2019, 03:36 AM
Last Post: Fifth
  GPIO and SPI SamR1 20 25,008 03-15-2018, 10:32 AM
Last Post: jomoengineer
Question GPIO shockr 7 11,892 03-11-2018, 01:52 AM
Last Post: jomoengineer
  Read GPIO problem shworker 14 16,205 08-17-2017, 01:21 PM
Last Post: martinayotte
  GPIO fiq capability joseph 3 4,720 11-10-2016, 06:07 PM
Last Post: joseph

Forum Jump:


Users browsing this thread: 3 Guest(s)