GPIO management via mem

Discussion in 'UDOO QUAD' started by patrykk, Apr 26, 2016.

  1. patrykk

    patrykk Member

    Joined:
    Dec 10, 2014
    Messages:
    52
    Likes Received:
    9
    Hi,
    I have to monitor signals on many gpios but via proc fs it takes a lot of CPU. There is a faster way but I need some help. http://www.black-swift.com/wiki/index.php?title=Working_with_GPIOs_(C/C++)

    We could have access to gpios directly via memory blocks but I dont know base address for gpios and mem block size. I have investigated topic and probably base addr is at 0x20000000 but I dont know mem block size ( probably 16K). Could you confirm the informations?

    best regards,
     
  2. patrykk

    patrykk Member

    Joined:
    Dec 10, 2014
    Messages:
    52
    Likes Received:
    9
    Hi, I resolved a problem. Please check link https://community.freescale.com/thread/381277. Use example with mmap from userland and test on pin 40th. My previous thinking has been wrong.
    Code:
    example for pin 161 with no changed comments
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <errno.h>
    #include <string.h>
    #include <stdint.h>
    #include <unistd.h>
    
    #define IOMUXC                           0x020E0000
    #define IOMUXC_SW_MUX_CTL_PAD_SD4_DATA0  0x020E031C
    #define GPIO2_DR                         0x020B0000
    //#define GPIO2_GDIR                       0x020A0004
    #define GPIO2_GDIR      (GPIO2_DR + 0x04)
    #define GPIO2_PSR                        1
    
    
    static volatile uint32_t *gpio;
    
    int main(int argc, char **argv)
    {
        int fd ;
    
        //Obtain handle to physical memory
        if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
            printf("Unable to open /dev/mem: %s\n", strerror(errno));
            return -1;
        }
    
        /**
          * Map some of the pin mux registers within the range of the
          * GPIO40 GPIO40 pin.
        **/
        gpio = (uint32_t *)mmap(0, (getpagesize() * 250), PROT_READ|PROT_WRITE, MAP_SHARED, fd, IOMUXC);
    
        // The first 3 bits are the only thing that matters here according to the
        // datasheet.
        *(gpio + ((IOMUXC_SW_MUX_CTL_PAD_SD4_DATA0 - IOMUXC) / 4)) = 0x5;
    
        //Be a good neighbor
        if((munmap((void *)gpio, (getpagesize() * 250))) < 0){
            printf("munmap failed: %s\n", strerror(errno));
            exit(1);
        }
        /** The i.MX 6 Dual and Quad Processor have 7 GPIO banks
          * Each bank amounts to 1mb of memory which is perfectly
          * aligned for a memory map. Mmap will fail if the offset
          * is not a multiple of 1mb. For this example I just want
          * the GPIO2 bank which starts at 0x020A0000. I want the
          * bank (1mb or 250 pages of memory). I could get away with
          * a single page, but I am greedy :-P.
        **/
        gpio = (uint32_t *)mmap(0, (getpagesize() * 250), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO2_DR);
    
        if ((int32_t)gpio < 0){
            printf("mmap failed: %s\n", strerror(errno));
            exit(1);
        }
    
        /**
          * Setup GPIO40 or GPIO2_IO08 as an output.
          * gpio[1] is the GPIO direction register (GPIO2_GDIR).
          * We want to only want to set bit 8 of this register
          * to a binary 1 while leaving the rest intact.
        **/
        *(gpio + ((GPIO2_GDIR - GPIO2_DR) / 4)) = *(gpio + ((GPIO2_GDIR - GPIO2_DR) / 4)) | 1<<GPIO2_PSR;
    
        /**
          * Blink GPIO40 every 500 milliseconds.
          * gpio[0] is the GPIO data register (GPIO2_DR).
          * We only want to toggle bit 8 of this register
          * while leaving the rest alone.
        **/
        while(1){
            *(gpio + ((GPIO2_DR - GPIO2_DR) / 4)) = *(gpio + ((GPIO2_DR - GPIO2_DR) / 4)) ^ 1<<GPIO2_PSR;
            usleep(250000);
            *(gpio + ((GPIO2_DR - GPIO2_DR) / 4)) = *(gpio + ((GPIO2_DR - GPIO2_DR) / 4)) ^ 1<<GPIO2_PSR;
            usleep(250000);
        }
    }
                                                                                                                                                                    
    
    
    
     
    modjo and waltervl like this.

Share This Page