GPIO

A GPIO may have multiple functions. The active function can be selected using the GPFSEL register.

Base Address>: 0x7e20'0000

Can be found in the PDF on section 5.2 (Register View)

Register

RegisterAnwendungBits
GPFSELFunction selection for GPIO3
GPSETSet Value for GPIO1
GPCLRClear Value for GPIO (Set to 0x00)1
GPLEVRead Pin Level1

Access

alt text

Kommandozeilen Befehl um die GPIOChip Nummern für Zugriff über pseudo Filesystem

ls gpiochip*/device/driver

Pseudo Filesystem

GPIO can be accessed using the pseudo file system mapped at "/sys/class/gpio"

  • Requires driver for GPIO
  • Portable to other HW, works everywere
  • Less hassle with addressses

Enable GPIO

echo <gpio-pin> > /sys/class/gpio/export

Set Direction of GPIO

DirectionValue to Write
Read pinin
set pinout

XX => GPIO-PIN-Number

echo "direction" >> /sys/class/gpio/gpioXX/direction

Value of GPIO

StateValue to Write
HIGH1
LOW0

Set Value

echo "1" >> /sys/class/gpio/gpioXX/value

Read Value

cat /sys/class/gpio/gpioXX/value

C-Code

Export GPIO

FILE *fp;
fp = fopen("/sys/class/gpio/export", "w");
if (fp == NULL) {
	printf("Error opening file in gpio_init %s\n", str);
	return 1;
}
fprintf(fp, "%i", gpio);
fflush(fp);
fclose(fp);

Set Value

void fs_gpio_set (int gpio, int val)
{
	FILE *fp;
	char str[100];
	sprintf(str, "/sys/class/gpio/gpio%i/value", gpio);
	fp = fopen(str, "w");
	if (fp== NULL) {
		printf("Error opening file in gpio_set %s\n", str);
		return -1;
	}
	fprintf(fp, "%i", val);
	fflush(fp);
	fclose(fp);
}

Read Value

int fs_gpio_get (int gpio)
{
	FILE *fp;
	char str[100];
	int ret;
	sprintf(str, "/sys/class/gpio/gpio%i/value", gpio);
	fp = fopen(str, "r");
	if (fp == NULL) {
		printf("Error opening file in gpio_read %s\n", str);
		return -1;
	}
	fread(str, 101, 1, fp);
	sscanf(str, "%i", &ret);
	fclose(fp);
	return ret;
}

Memory Mapped

When using Memory Mapped / DMA (Direct Memory Access), the gpio location must be translated to the memory address.

The Physical Address is 35bit!

void *virtual_gpio_base; //define global pointer
int mmap_virtual_base()
{
	int m_mfd;
	if ((m_mfd = open("/dev/mem", O_RDWR)) < 0)
	{
		printf("FAIL by open /dev/mem\n");
		return m_mfd;
	}

	virtual_gpio_base = (void*) mmap(NULL, sysconf(_SC_PAGE_SIZE),
	PROT_READ|PROT_WRITE, MAP_SHARED, m_mfd, GPIO_BASE_ADDR);
	close(m_mfd);
	
	if (virtual_gpio_base == MAP_FAILED) {
		return errno;
	}
	return 0;
}

Setting and clearing of single gpio pins

#define GPIO_SET0 (0x0000001c) // GPIOSET0 offset
#define GPIO_CLR0 (0x00000028) // GPIOCLR0 offset
void *virtual_gpio_base; //define global pointer
static void mmap_gpio_set(int gpio, int value)
{
	uint32_t *gpio_reg;
	if (value == 1){
		gpio_reg = (uint32_t *) (virtual_gpio_base + GPIO_SET0);
	}
	else {
		gpio_reg = (uint32_t *) (virtual_gpio_base + GPIO_CLR0);
	}
	*gpio_reg = (0x1 << gpio);
	
}

I2C

Read / Write Cycle

alt text

Writing / Reading Data

alt text

  • For more details checkout CT2 I2C

  • Only one driver can open the bus

#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

int fd;
char *filename = "/dev/i2c-1";

if ((fd = open(filename, O_RDWR)) < 0) {
	/* ERROR HANDLING: you can check errno to see what went wrong */
	perror("Failed to open the i2c bus");
	exit(1);
}

// Sets up the I2C controller with I2C-bus mode and I2C slave address
int addr = 0x20;
if ( ioctl(fd, I2C_SLAVE, addr ) < 0) {
	printf("Failed to acquire I2C bus access and/or talk to slave.\n");
	exit(1);
}
// WRITE
uint8_t wr_buf[2];
wr_buf[0] = register_address;
wr_buf[1] = register_data;
if ( write(fd, wr_buf, 2) != 2 ) {
	printf("Failed to write to the i2c bus.\n");
}
//READ
uint8_t data = 0;
uint8_t wr_buf[1];
uint8_t rd_buf[1];

wr_buf[0] = register_addr;
if ( write(fd, wr_buf, 1) != 1 ) {
	printf("Failed to write to the i2c bus.\n");
}

if ( read(fd, rd_buf, 1) != 1 ) {
	printf("Failed to read from the i2c bus.\n");
} else {
	data = rd_buf[0];
}