This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux: AM335x mmap for GPIO control



Tool/software: Linux

I used ti-processor sdk -linux-am335x v04.02 for beaglebone black, I have used mmap for io control but nothing happened.

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

#define GPIO0_START_ADDR 0x44e07000
#define GPIO0_END_ADDR 0x44e08000
#define GPIO0_SIZE (GPIO0_END_ADDR - GPIO0_START_ADDR)

#define GPIO_07 (1<<7)
#define GPIO_31 (1<<31)

// Global variables
int keepgoing = 1; // Set to 0 when Ctrl-c is pressed
// Callback called when SIGINT is sent to the process (Ctrl-C)
void signal_handler(int sig) {
printf( "\nCtrl-C pressed, cleaning up and exiting...\n" );
keepgoing = 0;
}

int main(int argc, char *argv[]) {
   volatile void *gpio_addr;
   volatile unsigned int *gpio_datain;
   volatile unsigned int *gpio_setdataout_addr;
   volatile unsigned int *gpio_cleardataout_addr;


    signal(SIGINT, signal_handler);
    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    printf("Mapping %X - %X (size: %X)\n", GPIO0_START_ADDR, GPIO0_END_ADDR,GPIO0_SIZE);
    gpio_addr = mmap(0, GPIO0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,GPIO0_START_ADDR);
    gpio_datain = gpio_addr + GPIO_DATAIN;
    gpio_setdataout_addr = gpio_addr + GPIO_SETDATAOUT;
    gpio_cleardataout_addr = gpio_addr + GPIO_CLEARDATAOUT;  

   if(gpio_addr == MAP_FAILED) {
      printf("Unable to map GPIO\n");
      exit(1);
    }

   printf("GPIO mapped to %p\n", gpio_addr); 
    printf("GPIO SETDATAOUTADDR mapped to %p\n", gpio_setdataout_addr);
    printf("GPIO CLEARDATAOUT mapped to %p\n", gpio_cleardataout_addr);
    printf("Start copying GPIO_07 to GPIO_31\n");

    while(keepgoing) {

    *gpio_setdataout_addr= GPIO_31;
     usleep(1);
     *gpio_cleardataout_addr = GPIO_31;
    }
    munmap((void *)gpio_addr, GPIO0_SIZE);
    close(fd);
    return 0;
}

  • Hello somkiatup,

    You memory mapping is bad, please refer to this good example.

    Best regards,
    Kemal

  • hi Kemal,

    I got file from other guy that you send the link to me to apply with my project but it still not work.

    SOURCE FILE

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    
    // See page 155 of SPRUH73H (AM335X) October 2011
    // Base address of GPIO0
    #define AM335X_GPIO0_BASE           0x44E07000
    // Base address of GPIO1
    #define AM335X_GPIO1_BASE           0x4804C000
    // Base address of GPIO2
    #define AM335X_GPIO2_BASE           0x481AC000
    // Base address of GPIO3
    #define AM335X_GPIO3_BASE           0x481AE000
    // GPIO register size
    #define AM335X_GPIO_SIZE            0x1000
    // This register is used to enable the pins output capabilities.
    #define AM335X_GPIO_OE              0x134
    //This register is used to register the data that is read from the GPIO pins.
    #define AM335X_GPIO_DATAIN          0x138
    // This register is used for setting the value of the GPIO output pins
    #define AM335X_GPIO_DATAOUT         0x13C
    // This register is used to register the data that is read from the GPIO pins.
    #define AM335X_GPIO_SETDATAOUT      0x190
    // This register is used for setting the value of the GPIO output pins
    #define AM335X_GPIO_CLEARDATAOUT    0x194
    
    #define MAX_NO_OF_GPIO_BANKS        (4)
    #define GPIO_MODULE0                (0)
    #define GPIO_MODULE1                (1)
    #define GPIO_MODULE2                (2)
    #define GPIO_MODULE3                (3)
    
    #define USR0_LED_D1 (4)
    #define USR1_LED_D2 (5)
    #define USR2_LED_D3 (7)
    #define USR3_LED_D4 (6)
    
    #define GPIO_03 (1<<3)
    #define GPIO_07 (1<<7)
    #define GPIO_31 (1<<31)
    #define GPIO_60 (1<<28)
    
    #define USR0_KEY_SW1 (3)
    #define USR1_KEY_SW2 (2)
    #define USR2_KEY_SW3 (30)
    #define USR3_KEY_SW4 (5)
    
    #define OUT          (0)
    #define IN           (1)
    
    uint32_t gpio_base[] = {
        AM335X_GPIO0_BASE,
        AM335X_GPIO1_BASE,
        AM335X_GPIO2_BASE,
        AM335X_GPIO3_BASE,
        0/*NULL*/
    };
    
    void *gpio_addr[MAX_NO_OF_GPIO_BANKS] = { NULL };
    unsigned int *gpio_oe_addr = NULL;
    unsigned int *gpio_dataout_addr = NULL;
    unsigned int *gpio_datain_addr = NULL;
    unsigned int *gpio_setdataout_addr = NULL;
    unsigned int *gpio_cleardataout_addr = NULL;
    
    void *pinmux_addr = NULL;
    unsigned int *used_pinmux_addr = NULL;
    
    int  mem_fd;
    int gpio_module = -1;
    
    
    
    
    void gpio_set(int gpio_module_no, int pin)
    {
        unsigned int reg;
        gpio_dataout_addr = gpio_addr[gpio_module_no] + AM335X_GPIO_DATAOUT;
        reg = *gpio_dataout_addr;
        reg = reg | (1 << pin);
        *gpio_dataout_addr = reg;
        printf("gpio_set: pin value = %d\treg value = 0x%X\n",pin, reg);
    }
    
    void gpio_reset(int gpio_module_no, int pin)
    {
        unsigned int reg;
        gpio_dataout_addr = gpio_addr[gpio_module_no] + AM335X_GPIO_DATAOUT;
        reg = *gpio_dataout_addr;
        reg = reg & ~(1 << pin);
        *gpio_dataout_addr = reg;
        printf("gpio_reset: pin value = %d\treg value = 0x%X\n",pin, reg);
    }
    
    int gpio_read(int gpio_module_no, int direction, int pin)
    {
        int pin_value = 0;
        unsigned int reg;
        if (direction == 0) {
            gpio_dataout_addr = gpio_addr[gpio_module_no] + AM335X_GPIO_DATAOUT;
            reg = *gpio_dataout_addr;
            if (reg & (1 << pin)) {
                pin_value = 1;
            }
        }
        else if (direction == 1) {
            gpio_datain_addr = gpio_addr[gpio_module_no] + AM335X_GPIO_DATAIN;
            reg = *gpio_datain_addr;
            if (reg & (1 << pin)) {
                pin_value = 1;
            }
        }
        else{
            pin_value = -1;
        }
        if (pin_value == 1)
            printf("gpio_read: pin value = %d\n",pin_value);
        return pin_value;
    }
    
    void gpio_set_direction(int gpio_module_no, int direction, int pin)
    {
        unsigned int reg;
        gpio_oe_addr = gpio_addr[gpio_module_no] + AM335X_GPIO_OE;
        reg = *gpio_oe_addr;
        printf("gpio_set_direction: reg initial = 0x%X\n",reg);
        if (direction == 0) {
            reg = reg & ~(1 << pin);
            *gpio_oe_addr = reg;
        } else {
            reg = reg | (1 << pin);
            *gpio_oe_addr = reg;
        }
        printf("gpio_set_direction: reg after setting dir = 0x%X\n",reg);
    }
    
    /*
     * Set up a memory regions to access GPIO
     */
    void setup_io()
    {
        int i = 0;
        /* open /dev/mem */
        if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
            printf("main: can't open /dev/mem \n");
            exit(-1);
        }
        printf("main: mem_fd = %d\n",mem_fd);
        /* mmap GPIO Bank1 */
        gpio_addr[GPIO_MODULE0]
            = mmap(
                    NULL,                   //Any adddress in our space will do
                    AM335X_GPIO_SIZE,       //Map length
                    PROT_READ|PROT_WRITE,   // Enable reading & writting to mapped memory
                    MAP_SHARED,             //Shared with other processes
                    mem_fd,                 //File to map
                    gpio_base[GPIO_MODULE0] //Offset to GPIO peripheral
                  );
        /* mmap GPIO Bank2*/
        gpio_addr[GPIO_MODULE1]
            = mmap(
                    NULL,                   //Any adddress in our space will do
                    AM335X_GPIO_SIZE,       //Map length
                    PROT_READ|PROT_WRITE,   // Enable reading & writting to mapped memory
                    MAP_SHARED,             //Shared with other processes
                    mem_fd,                 //File to map
                    gpio_base[GPIO_MODULE1] //Offset to GPIO peripheral
                  );
        /* mmap GPIO Bank3*/
        gpio_addr[GPIO_MODULE2]
            = mmap(
                    NULL,                   //Any adddress in our space will do
                    AM335X_GPIO_SIZE,       //Map length
                    PROT_READ|PROT_WRITE,   // Enable reading & writting to mapped memory
                    MAP_SHARED,             //Shared with other processes
                    mem_fd,                 //File to map
                    gpio_base[GPIO_MODULE2] //Offset to GPIO peripheral
                  );
        /* mmap GPIO Bank4*/
        gpio_addr[GPIO_MODULE3]
            = mmap(
                    NULL,                   //Any adddress in our space will do
                    AM335X_GPIO_SIZE,       //Map length
                    PROT_READ|PROT_WRITE,   // Enable reading & writting to mapped memory
                    MAP_SHARED,             //Shared with other processes
                    mem_fd,                 //File to map
                    gpio_base[GPIO_MODULE3] //Offset to GPIO peripheral
                  );
        //printf("main: gpio_base[%d] = 0x%X\n", gpio_module, gpio_base[gpio_module]);
        close(mem_fd); //No need to keep mem_fd open after mmap
        for ( i = 0; i < MAX_NO_OF_GPIO_BANKS; i++ ) {
            if (gpio_addr[i] == MAP_FAILED) {
                printf("mmap error %d\n", (int)gpio_addr[i]);//errno also set!
                exit(-1);
            }
        }
    } // setup_io
    
    
    
    int main (int argc, char *argv[])
    {
        int i = 0;
        setup_io();
    
    
        /* Set LEDs as output */
        gpio_set_direction(GPIO_MODULE0, GPIO_31, OUT);
        printf("main: GPIO_31 set as outputs successfully\n");
    
        while (1) {
            gpio_set(GPIO_MODULE0, GPIO_31);
            usleep(1000000);
            gpio_reset(GPIO_MODULE0, GPIO_31);
            usleep(1000000);
    
        }
        for ( i = 0; i < MAX_NO_OF_GPIO_BANKS; i++ ) {
            munmap((void *)gpio_addr[i], AM335X_GPIO_SIZE);
        }
        return 0;
    }
    

    Best regards,

    somkiat