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.

SIGBUS(SIG 7) on accessing registers from userspace.

Hi All,

I get below error, what is the solution?

/dev/mem opened.
Memory mapped at address 0xb6f6c[ 2194.194754] Unhandled fault: external abort on non-linefetch (0x1018) at 0xb6f6c000
000.
Bus error

code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>

#define DCAN0_REG_BASE     0x481CC000
#define DCAN0_CTRL_REG_OFFSET 0
#define MAP_SIZE 8192UL
#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char **argv) {
    int fd;
    void *map_base, *virt_addr;
    volatile unsigned long read_result;

    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
        printf("/dev/mem could not be opened.\n");
        exit(1);
    } else {
        printf("/dev/mem opened.\n");
    }  
    fflush(stdout);

    /* Map one page */
    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, DCAN0_REG_BASE);
    if(map_base == (void *) -1) {
        printf("Memory map failed.\n");
    } else {
        printf("Memory mapped at address %p.\n", map_base);
    }  
    fflush(stdout);

    virt_addr = map_base ;

    /* acess remapped region here */
    /* read dcan0 ctrl reg */
    read_result = *((volatile unsigned long *) virt_addr);   
    printf("DCAN0 CTRL = 0x%x\n", read_result);
    if(munmap(map_base, MAP_SIZE) == -1) {
        printf("Memory unmap failed.\n");
    }

    close(fd);
}

Regards,

Gangadhar

  • Your fault is that you don't use a kernel driver. Accessing Hardware from userspace is asking for trouble.

    Theerror in your example is THW missing clock for the dcan module.

    Regards

    Wolfgang

  • Thanks Wolfgang. In uboot, I'm doing clk config using below code and able to do CAN internal loopback in linux.

    And in uboot able to read registers properly.What else am I missing? What is that THW clock? What is the fix for SIG 7 error? Accessing registers from userspace is my custome r requirement.

    void DCANModuleClkConfig(void)
    {
        HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) =
                                 CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) &
         CM_PER_L3S_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

        HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) =
                                 CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) &
         CM_PER_L3_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

        HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) =
                                 CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) &
                                   CM_PER_L3_INSTR_CLKCTRL_MODULEMODE) !=
                                       CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE);

        HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) =
                                 CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) &
            CM_PER_L3_CLKCTRL_MODULEMODE) != CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE);

        HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) =
                                 CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
                                  CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL) !=
                                    CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

        HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) =
                                 CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
                                 CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL) !=
                                   CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

        HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKCTRL) =
                                 CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKCTRL) &

     CM_PER_L4LS_CLKCTRL_MODULEMODE) != CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE);

        HWREG(SOC_CM_PER_REGS + CM_PER_DCAN1_CLKCTRL) =
                                      CM_PER_DCAN1_CLKCTRL_MODULEMODE_ENABLE;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_DCAN1_CLKCTRL) &
                             CM_PER_DCAN1_CLKCTRL_MODULEMODE) !=
                             CM_PER_DCAN1_CLKCTRL_MODULEMODE_ENABLE);

        HWREG(SOC_CM_PER_REGS + CM_PER_DCAN0_CLKCTRL) =
                                      CM_PER_DCAN0_CLKCTRL_MODULEMODE_ENABLE;

        while((HWREG(SOC_CM_PER_REGS + CM_PER_DCAN0_CLKCTRL) &
                             CM_PER_DCAN0_CLKCTRL_MODULEMODE) !=
                             CM_PER_DCAN0_CLKCTRL_MODULEMODE_ENABLE);

        while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) &
                CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK));

        while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) &
                CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK));

        while(!(HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
               (CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK |
                CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_GCLK)));

        while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
               (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |
                CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_CAN_CLK)));
    }


    Regards,

    Gangadhar

  • Maybe Linux turns the clock off again?

    In general I don't see any objection to doing device I/O from userspace, but you do need to make sure the kernel keeps its hands off.

     

    BTW, reading back MODULEMODE or CLKTRCTRL is completely pointless.  Checking CLKACTIVITY is also rarely needed.  Typically you just write to CLKTRCTRL to wake up the domain, to MODULEMODE to enable the module, release local reset when applicable (aforementioned steps in any order), then poll the CLKCTRL register until IDLEST is zero.

    I recommend using byte writes rather than 32-bit writes since some CLKCTRL registers have additional config in their upper half which you do not want to clobber (this is particularly true with the DebugSS CLKCTRL register: at least on the DM814x the whole thing crashes hard if you overwrite it, I found out the hard way).

  • THW = The. Sorry for the typo.

    Doing Hardware IO in userspace is pointless. In userspace, there is a lack of methods to to IO.

    For clocking, it's not possible to access the clock tree from userspace. You can't do interrupts in userspace.

    You can't do DMA in userspace.

    Writing device drivers in the kernel (as a loadable kernel module) is easy. In userspace, it's near to impossible.

    You have to educate your customer about this. Doing IO in userspace is not professional.

    Writing device drivers has the additional benefit that you can add a layer of abstraction, so that the userspace can abstract from the device, and make it possible to change the hardware without a need to change the userspace program.

    regards

    Wolfgang

  • Wolfgang Muees1 said:
    Doing IO in userspace is not professional.

    Wow, don't let microkernel enthausiasts hear that...

    Doing IO in userspace can be a very reasonable choice for system stability reasons and easy of prototyping.

    If interrupt handling is a requirement, there's the UIO framework.  It still requires a tiny bit of kernel code (just whatever is needed get the interrupt line to clear), but most of the driver can remain in userspace.

    Wolfgang Muees1 said:
    Writing device drivers has the additional benefit that you can add a layer of abstraction, so that the userspace can abstract from the device, and make it possible to change the hardware without a need to change the userspace program.

    A library or daemon/service can do the same.

  • Thankyou all. Uboot used to enable the clk for CAN. But linux used to disable it. This was the cause of this error.

    Enabled the clock by writing, 0x2 to CM_PER_DCAN0_CLKCTRL.

    Now I want to know why linux disables the clock.

    Regards,

    Gangadhar