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/AM3354: Segmentation fault

Part Number: AM3354

Tool/software: Linux

Hi!

I've been trying to access the MCSPI0-registers listed in the L4_PER peripheral memory map in the Cortex A8-section.

#include <stdint.h>
#include <stdio.h>
#include <pru_cfg.h>
#define PRU_ICSS_BASE               (*((volatile unsigned int *)(0x00026000)))
#define PRU_ICSS_SYSCFG             (*((volatile unsigned int *)(0x00026004)))
int main(void)
{   
 CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
}

Trying to access the dereferenced pointers gives segfault, trying to set STANDBY_INIT gives segfault. Why?

  • Please provide complete details of your use case: Linux version, what you are trying to do, etc...
  • You are not allowed to access these memory locations from user space. The MMU gives you a segfault.

    You should use/write a kernel driver for access of hardware registers.

  • I am currently using : BeagleBoard.org Debian Image 2018-10-07 on the BeagleBone Black Wireless, and i am trying to control the mcSPI-module by writing directly to memory from C++.
  • Following Derek Molloys example: ,

    i tried to write a loadable kernel module  access the hardware registers. This is a hello-world example where I modified two lines marked with ***own modification***

    /**
     * @file    hello.c
     * @author  Derek Molloy
     * @date    4 April 2015
     * @version 0.1
     * @brief  An introductory "Hello World!" loadable kernel module (LKM) that can display a message
     * in the /var/log/kern.log file when the module is loaded and removed. The module can accept an
     * argument when it is loaded -- the name, which appears in the kernel log files.
     * @see http://www.derekmolloy.ie/ for a full description and follow-up descriptions.
    */
    
    #include <linux/init.h>             // Macros used to mark up functions e.g., __init __exit
    #include <linux/module.h>           // Core header for loading LKMs into the kernel
    #include <linux/kernel.h>           // Contains types, macros, functions for the kernel
    
    
    MODULE_LICENSE("GPL");              ///< The license type -- this affects runtime behavior
    MODULE_AUTHOR("Derek Molloy");      ///< The author -- visible when you use modinfo
    MODULE_DESCRIPTION("A simple Linux driver for the BBB.");  ///< The description -- see modinfo
    MODULE_VERSION("0.1");              ///< The version of the module
    volatile unsigned int * McSPI0_HL_HWINFO = 0x48030004;                                                  ***own modification***
    static char *name = "world";        ///< An example LKM argument -- default value is "world"
    module_param(name, charp, S_IRUGO); ///< Param desc. charp = char ptr, S_IRUGO can be read/not changed
    MODULE_PARM_DESC(name, "The name to display in /var/log/kern.log");  ///< parameter description
    
    /** @brief The LKM initialization function
     *  The static keyword restricts the visibility of the function to within this C file. The __init
     *  macro means that for a built-in driver (not a LKM) the function is only used at initialization
     *  time and that it can be discarded and its memory freed up after that point.
     *  @return returns 0 if successful
     */
    static int __init helloBBB_init(void){
       printk(KERN_INFO "EBB: Hello %s from the BBB LKM!\n", name);
       printk(KERN_INFO "HWINFO for mcSPI: %d\n", *McSPI0_HL_HWINFO);                                   **own modification**
       return 0;
    }
    
    /** @brief The LKM cleanup function
     *  Similar to the initialization function, it is static. The __exit macro notifies that if this
     *  code is used for a built-in driver (not a LKM) that this function is not required.
     */
    static void __exit helloBBB_exit(void){
       printk(KERN_INFO "EBB: Goodbye %s from the BBB LKM!\n", name);
    }
    
    /** @brief A module must use the module_init() module_exit() macros from linux/init.h, which
     *  identify the initialization function at insertion time and the cleanup function (as
     *  listed above)
     */
    module_init(helloBBB_init);
    module_exit(helloBBB_exit);

    This gives the following error when tailing /var/log/kern.log:

    Apr 21 14:56:50 beaglebone kernel: [ 477.507930] Unable to handle kernel paging request at virtual address 48030004
    Apr 21 14:56:50 beaglebone kernel: [ 477.524656] pgd = d38c0000
    Apr 21 14:56:50 beaglebone kernel: [ 477.527398] [48030004] *pgd=00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.533875] Internal error: Oops: 5 [#1] PREEMPT SMP ARM

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.654330] Process insmod (pid: 2215, stack limit = 0xdb2aa218)

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.660363] Stack: (0xdb2abd78 to 0xdb2ac000)

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.664740] bd60: c1504dc8 bf4bc000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.672958] bd80: db2abe04 db2abd90 c0101d28 bf4bc00c db2aa000 dfd3255c c02cb254 db25fc80

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.681175] bda0: db2aa000 dc001e40 db2abdc0 c02e19f0 db2aa000 dc001e40 db2abe04 db2abdc8

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.689393] bdc0: c02e19f0 c02ee9cc 00000001 00000002 dc4e2800 c01e7978 00000001 77533b88

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.697610] bde0: bf4b9040 00000001 bf4b9040 dc4e2f80 00000001 e0921000 db2abe2c db2abe08

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.705828] be00: c01e79b4 c0101cd0 db2abe2c db2abe18 db2abf3c 00000001 bf4b9040 db25fc00

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.714045] be20: db2abf14 db2abe30 c01e65e0 c01e794c bf4b904c 00007fff bf4b9040 c01e3628

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.722263] be40: dad830c0 c11e27ac bf4b923c c10eec30 c11e0b7c bf4b9170 c0e0811c bf4b9140

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.730480] be60: db2abf3c bf4b9154 d389fcc4 bf4b9040 bf4b9088 c1504dc8 db2abea8 c1205fdc

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.738697] be80: db2abf2c db2abf30 db2abee4 db2abe98 00000000 00000000 00000000 00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.746914] bea0: 00000000 00000000 6e72656b 00006c65 00000000 00000000 00000000 00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.755131] bec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.763349] bee0: 00000000 77533b88 7fffffff c1504dc8 00000000 00000003 00469294 c01090e4

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.771567] bf00: db2aa000 00000000 db2abfa4 db2abf18 c01e6fc8 c01e43f4 7fffffff 00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.779784] bf20: 00000003 db2abf38 db2abf3c e0921000 00001368 00000000 00000000 e09211c6

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.788002] bf40: e0921000 00001368 e0921e68 e0921d28 e0921aa0 00003000 00003160 00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.796219] bf60: 00000000 00000000 000015c8 0000001d 0000001e 00000015 00000012 0000000e

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.804437] bf80: 00000000 77533b88 d7250400 00000000 0047ae1c 0000017b 00000000 db2abfa8

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.812654] bfa0: c0108f00 c01e6ef8 d7250400 00000000 00000003 00469294 00000000 bec15a70

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.820871] bfc0: d7250400 00000000 0047ae1c 0000017b 00000000 00000000 0047a770 00000000

    Message from syslogd@beaglebone at Apr 21 14:56:51 ...
    kernel:[ 477.829089] bfe0: bec15a18 bec15a08 004605bb b6e36fc2 60030030 00000003 00000000 00000000

    Is there any way to list drivers associated with  the memory address? I have tried rrmodding the spidev module, which did not have any effect

  • I found a list of registers used in /proc/iomem, and when grepping "spi" this came as results:
    48030000-480303ff : /ocp/spi@48030000
    481a0000-481a03ff : /ocp/spi@481a0000
  • Jonas Hjulstad said:
    I am currently using : BeagleBoard.org Debian Image 2018-10-07 on the BeagleBone Black Wireless, and i am trying to control the mcSPI-module by writing directly to memory from C++.

    In the past I have used a userspace I/O system (UIO) driver to give user space access to memory mapped device registers.

    See The Userspace I/O HOWTO for an introduction to UIO

    https://github.com/Chester-Gillon/nvram_uio is a UIO example, but was written for a PCIe device in a x86_64 PC running a 2.6 series Kernel so not sure how much code can be re-used for Linux running on ARM.

  • Read about ioremap(). There is an online book at www.oreilly.com/.../
  • 
    

    Thanks for the response!

    When trying to use the ioremap-function, i receive an error from one of the includes:

    root@beaglebone:~/projects# make
    make -C /lib/modules/4.14.71-ti-r80/build/ M=/root/projects modules
    make[1]: Entering directory '/usr/src/linux-headers-4.14.71-ti-r80'
      CC [M]  /root/projects/test.o
    In file included from /root/projects/test.c:16:0:
    /root/projects/test.c: In function ‘helloBBB_init’:
    ./arch/arm/include/asm/io.h:400:17: error: initializer element is not constant
     #define ioremap ioremap
                     ^
    /root/projects/test.c:33:30: note: in expansion of macro ‘ioremap’
      static void __iomem *regs = ioremap(0x48030004, 0xFFF);
                                  ^~~~~~~
    

    with code:

    #include <linux/init.h>             // Macros used to mark up functions e.g., __init __exit
    #include <linux/module.h>           // Core header for loading LKMs into the kernel
    #include <linux/kernel.h>           // Contains types, macros, functions for the kernel
    #include <linux/version.h>
    #include <asm/io.h>
    MODULE_LICENSE("GPL");              ///< The license type -- this affects runtime behavior
    MODULE_AUTHOR("Derek Molloy");      ///< The author -- visible when you use modinfo
    MODULE_DESCRIPTION("A simple Linux driver for the BBB.");  ///< The description -- see modinfo
    MODULE_VERSION("0.1");              ///< The version of the module
    //volatile unsigned int * McSPI0_HL_HWINFO = 0x48030004;
    static char *name = "world";        ///< An example LKM argument -- default value is "world"
    module_param(name, charp, S_IRUGO); ///< Param desc. charp = char ptr, S_IRUGO can be read/not changed
    MODULE_PARM_DESC(name, "The name to display in /var/log/kern.log");  ///< parameter description
    
     */
    static int __init helloBBB_init(void){
            printk(KERN_INFO "EBB: Hello %s from the BBB LKM!\n", name);
            static void __iomem *regs = ioremap(0x48030004, 0xFFF);
    
      // printk(KERN_INFO "HWINFO for mcSPI: %d\n", *McSPI0_HL_HWINFO);
       return 0;
    }
    
    
    static void __exit helloBBB_exit(void){
       printk(KERN_INFO "EBB: Goodbye %s from the BBB LKM!\n", name);
    }
    
    module_init(helloBBB_init);
    module_exit(helloBBB_exit);
    
    

  • Splitting the void*-declaration from the ioremap() and placing it by the static char declaration solved the issue