AnsweredAssumed Answered

[i.MX RT1060] Segmentation fault occurs when GPIO registers access

Question asked by Byoungseon Kim on Jun 8, 2020

Hello everyone!
We are going to connect RGB LED to GPIO_SD_B1_00(GPIO #64) coupled with i.MX RT1060 processor.

This LED basically requires 1- and 0-level output signals with very short cycles from MCU.

For this reason, we intend to control the LED by directly accessing the GPIO3 registers using mmap() function.

 

We first checked the basic operation of GPIO #64 on the Linux shell with a few commands listed below:
# echo 64 > /sys/class/gpio/export
# echo out > /sys/class/gpio/gpio64/direction
# cat /sys/class/gpio/gpio64/value
# echo 1 > /sys/class/gpio/gpio64/value

 

Then, we implemented a simple linux-based application that just outputs the GPIO DR(Data Register) value. 

#include <stdio.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdlib.h>

#define LED_PIN (64)

 

#define GPIO3_START_ADDR    (0x401c0000)
#define GPIO3_END_ADDR      (0x401c3fff)
#define GPIO3_SIZE          (GPIO3_END_ADDR - GPIO3_START_ADDR)

/* Memroy map (see "12.5 GPIO Register Description", p.961) */ 
#define OFFSET_DR           (0x0)   // Dec 0, Data register (RW)
#define OFFSET_GDIR         (0x4)   // Dec 4, GPIO direction register (RW)
#define OFFSET_PSR          (0x8)   // Dec 8,Pad sample register (RO)
#define OFFSET_ICR1         (0xC)   // Dec 12, Interrupt control registers 1 (RW)
#define OFFSET_ICR2         (0x10)  // Dec 16, Interrupt control registers 2 (RW)
#define OFFSET_IMR          (0x14)  // Dec 20, Interrupt mask register (RW)
#define OFFSET_ISR          (0x18)  // Dec 24, Interrupt status register (W1C)
#define OFFSET_EDGE_SEL     (0x1C)  // Dec 28, Edge select register (RO)
#define OFFSET_DR_SET       (0x84)  // Dec 132, Data set register (WO)
#define OFFSET_DR_CLEAR     (0x88)  // Dec 136, Data clear register (WO)
#define OFFSET_DR_TOGGLE    (0x8C)  // Dec 140, Data toggle register (WO)

int main() {
    int     nFd;
    unsigned long            *pGpio3BaseAddr = NULL;
    volatile unsigned long   *pGpio3DrRegi   = NULL;
    //volatile unsigned long   *pGpio3GdirRegi = NULL;
    
    nFd = open("/dev/mem", O_RDWR | O_SYNC);
    if( nFd < 0) {
        printf("/dev/mem open error.\n");
        return 1;
    }

    pGpio3BaseAddr = (unsigned long *)mmap(NULL, GPIO3_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, nFd, GPIO3_START_ADDR);
    if( pGpio3BaseAddr == MAP_FAILED ) {
        printf("mmap() error.\n");
        return 1;
    }
    printf("mmap() success.\n");

    pGpio3DrRegi = (volatile unsigned long *)(pGpio3BaseAddr + OFFSET_DR);
    //pGpio3GdirRegi = (volatile unsigned long *)(pGpio3BaseAddr + OFFSET_GDIR);

    printf("pGpio3DrRegi Address: %08x\n", pGpio3DrRegi);
    printf("pGpio3DrRegi Value  : %08x\n", *pGpio3DrRegi); // <--- SEGV occurs

    munmap( pGpio3BaseAddr, GPIO3_SIZE );
    close( nFd );

    return 0;
}

 

But, when the application accesses the memory address, it issues a SEGV message and terminates.

 

 

We are trying to identify the cause for SEGV, but still haven't solved.
Does anyone know the cause and solution for this issue? *-*??

Outcomes