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.

66AK2E05: Memory Mapping of GPIOS

Expert 1010 points
Other Parts Discussed in Thread: 66AK2E05

Hi,


I tested GPIOs on a board with a Soc 66AK2E05 on it. When using sysfs to change GPIO registers, I have no problem (see code below).

Since I have performance in mind, I wanted to use memory mapped GPIO but it seems not to work and it returns me always EINVAL after calling mmap from user space.


Here is my current code:

/*
 * main.c
 */

#include <stdio.h>
#include "csl_gpio.h"
#include "csl_gpioAux.h"
#include "cslr_device.h"
#include "tisocgpio.h"

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


#define GPIO_FIRST      (16)
#define GPIO_LAST       (GPIO_FIRST + 15)

//CSL_GPIO_CFG_REGS = 0x0260BF00
#define GPIO_START_ADDR 0x0260BF00
#define GPIO_END_ADDR   0x0260BFFF
#define GPIO_MAP_SIZE (GPIO_END_ADDR - GPIO_START_ADDR)
#define GPIO_SETDATAOUT 0x18
#define GPIO_CLEARDATAOUT 0x1C

#define USE_MEMORY_MAP
//#define USE_SYSFS

int main(void)
{
   //unsigned int gpio = GPIO_FIRST;
    unsigned int gpio = ACK;
#ifdef USE_SYSFS
	printf("Sysfs version\n");

	gpio_export(gpio);
	gpio_set_dir(gpio, OUTPUT_PIN);
	int nLoop=0;
	while(nLoop<10)
	{
		gpio_set_value(gpio, HIGH);
		usleep(1000000);
		gpio_set_value(gpio, LOW);
		usleep(1000000);
		nLoop++;
	}

	gpio_unexport(gpio);
#endif

#ifdef USE_MEMORY_MAP
	printf("Memory mapping version\n");
	static void *mmap_base = NULL;
	volatile unsigned int *gpio_setdataout_addr;
	volatile unsigned int *gpio_cleardataout_addr;
	int fd_mem = open("/dev/mem", O_RDWR | O_SYNC);

	if (fd_mem < 1)
	{
		printf("Cannot open /dev/mem\n");
		return -1;
	}

	int page_size = getpagesize();
	printf("page size = %d\n",page_size);

	mmap_base = mmap(
	NULL,						// Start addr,let kernel choose
	GPIO_MAP_SIZE,				// The IO space
	PROT_READ | PROT_WRITE,		// Allow read and write (rw)
	MAP_SHARED,					// Share with all processes
	fd_mem,						// Device is /dev/mem
	GPIO_START_ADDR);			// IO memory region base

	if(mmap_base == MAP_FAILED)
	{
		printf("Memory Mapping Error: %s\n",strerror(errno));
		return -1;
	}

	gpio_setdataout_addr   = mmap_base + GPIO_SETDATAOUT;
	gpio_cleardataout_addr = mmap_base + GPIO_CLEARDATAOUT;

	int nLoop=0;
	while(nLoop<10)
	{
		*gpio_setdataout_addr = (1<<gpio);
		usleep(1000000);
		*gpio_cleardataout_addr = (1<<gpio);
		usleep(1000000);
		nLoop++;
	}

	munmap(mmap_base, GPIO_MAP_SIZE);
	close(fd_mem);

#endif

	printf("App exiting\n");

	return 0;
}

Is memory mapping somehow protected? Is there an alternative to boost performance for this purpose: already available kernel drivers?