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.

AM3358: Beaglebone Black GPIO control via /dev/mem does not work

Part Number: AM3358

Hello,

I am trying to control GPIO via /dev/mem on Beaglebone Black but it gets SIGBUS.
However, it works fine if 'echo 117 > /sys/class/gpio/export' command executed once.
This problem seems to be happen only GPIO module 3.
Is it supposed behaviour?
Should I need any additional procedure?

Simplen reproduction program is as follows.

#define _GNU_SOURCE
#include <inttypes.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>

#define AM335x_GPIO0_BASE      ((uint32_t *)0x44E07000)
#define AM335x_GPIO1_BASE      ((uint32_t *)0x4804C000)
#define AM335x_GPIO2_BASE      ((uint32_t *)0x481AC000)
#define AM335x_GPIO3_BASE      ((uint32_t *)0x481AE000)
#define GPIO_OE_OFF         (0x134/(sizeof(uint32_t *)))
#define AM335x_GPIO_LEN        ((size_t)0x1000)


const uint32_t *Base_Addrs[] = {AM335x_GPIO0_BASE, AM335x_GPIO1_BASE, AM335x_GPIO2_BASE, AM335x_GPIO3_BASE};
uint32_t *GPIO_Addrs[4]={};

_Bool bbb_gpio_init(void){
    int dev_map;
    if((dev_map = open("/dev/mem", O_RDWR)) < 0){
        perror("open");
        return(1);
    }

    for (uint8_t i=0; i<4; i++){
        if((GPIO_Addrs[i] = mmap(0, AM335x_GPIO_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, dev_map, (off_t)Base_Addrs[i])) == MAP_FAILED){
            fprintf(stderr, "Err: %s: Can not map GPIO register %p\n",__func__, Base_Addrs[i]);
            return(1);
        }
    }
    return(0);
}

int main(void){
    // GPIO configuration
    if(bbb_gpio_init()){
        fprintf(stderr, "Can not initialize bbb_gpio lib");
        exit(EXIT_FAILURE);
    }
    // set gpio3_21 to output
    uint32_t *ptr = GPIO_Addrs[3]+GPIO_OE_OFF;
    *ptr = (*ptr & ~(1<<21));
    return(0);
}

  • Hi,

    Could you please elaborate more on the problem you had? Where in the code did you get SIGBUS?

    I tried your code on my BeagleBone Black and it worked fine. I didn't get any error. Also, please refer to this example on using /dev/mem for GPIO control. 

    Regards,

    Jianzhong

  • Hi Jianzhong,

    Thanks for the reply.
    It looks like reading *ptr gets SIGBUS.

    (gdb) run
    Starting program: /root/test/c

    Program received signal SIGBUS, Bus error.
    0x0040070e in main () at c.c:49
    49          *ptr = (*ptr & ~(1<<21));
    (gdb) print ptr
    $1 = (uint32_t *) 0xb6ff5134

    Also, I noticed following error happes on dmesg when the app gets SIGBUS.

    [ 4293.122577] Unhandled fault: external abort on non-linefetch (0x1018) at 0xb6f30134
    [ 4293.130303] pgd = 334963a0
    [ 4293.133023] [b6f30134] *pgd=9b175831, *pte=481ae103, *ppte=481aea32

    Regards,

    Yui

  • Hi Yui,

    I tried your program on BBB with latest Debian image (beagleboard.org/latest-images), and it ran well without any problem. 

    I then tried it with Processor-SDK Linux 6.3 and reproduced your problem. I'm not sure what's exactly the root cause. Let me consult internal expert on this and get back to you.

    Thanks and regards,

    Jianzhong

  • Hi Yui,

    Our internal expert on GPIO is out this week. I will be out from Friday June 11 until June 21. So further response will be delayed. Sorry about that.

    Regards,

    Jianzhong

  • Hi Jianzhong,

    OK. It is not urgent issue because there is the workaround.

  • Hi,

    Sorry that we've not been able to investigate this issue so far. I'll see if we can figure it out and try to get back to you by the end of this week. Otherwise, you may have to do the workaround.

    Regards,

    Jianzhong

  • Hi Yui,

    The issue is because the clock to GPIO Module 3 is not active, then the registers are not accessible. The Processor SDK Linux kernel will gate the clock if the module is not used, which means none of the GPIO Module 3 pins is used in your case.

    When you run command 'echo 117 > ...' which makes GPIO 3 active, then your program works.

    Just a side note: it is okay to use /dev/mem for program prototype, but it is highly not recommended to use it in production, as it would create a whole bunch of problems, such as security and kernel malfunction.

  • Hi Bin,

    I have to enable GPIO3 with GPIO_CTRL Register before use it. Right?
    Or, it syould be configure on dtbo file?

    > Just a side note: it is okay to use /dev/mem for program prototype, but it is highly not recommended to use it in production

    Thanks for the advise but sysfs GPIO driver is too slow for my application. I am planning to limit map area to minimum.
    I am also learning PRU programing in addition for more efficient processiong.

  • Hi Yui,

    Sorry for our delayed response.I've found a discussion about the same issue in the BeagleBone  community: https://groups.google.com/g/beagleboard/c/_Xxpk05npuU/m/_5noVGFSaHkJ. A solution was posted there which enables the GPIO clock in the application code.

    I tried it and it didn't give me the bus error. Please give it a try.

    Regards,

    Jianzhong