//------------------------------------------------------------------------------------------------------------
//
// ODROID-C1 GPIO Status Check Application.
//
// Compile : gcc -o <create excute file name> <source file name>
// Run : sudo ./<created excute file name>
//
//------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <poll.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
//------------------------------------------------------------------------------
//
// Global handle Define
//
//------------------------------------------------------------------------------
// MMAP Address for GPIO
#define GPIO_REG_MAP 0xC1108000
#define GPIO_AO_REG_MAP 0xC8100000
#define BLOCK_SIZE (4*1024)
static volatile unsigned int *gpio;
static volatile unsigned int *gpio_ao;
static volatile unsigned int *ao_in;
//------------------------------------------------------------------------------
// refer kernel/arch/arm/mach-meson8b/include/mach/gpio.h
#define GPIOAO_PIN_START 0
#define GPIOAO_PIN_END 13
#define GPIOAO_FSEL_REG_OFFSET 0x09
#define GPIOAO_OUTP_REG_OFFSET 0x09
#define GPIOAO_INP_REG_OFFSET 0x0A
#define GPIOAO_PUPD_REG_OFFSET 0x0B
#define GPIOAO_PUEN_REG_OFFSET 0x0B
//------------------------------------------------------------------------------
#define GPIODV_PIN_START 50
#define GPIODV_PIN_END 79
#define GPIODV_FSEL_REG_OFFSET 0x12
#define GPIODV_OUTP_REG_OFFSET 0x13
#define GPIODV_INP_REG_OFFSET 0x14
#define GPIODV_PUPD_REG_OFFSET 0x3A
#define GPIODV_PUEN_REG_OFFSET 0x48
//------------------------------------------------------------------------------
#define GPIOY_PIN_START 80
#define GPIOY_PIN_END 96
#define GPIOY_FSEL_REG_OFFSET 0x0F
#define GPIOY_OUTP_REG_OFFSET 0x10
#define GPIOY_INP_REG_OFFSET 0x11
#define GPIOY_PUPD_REG_OFFSET 0x3D
#define GPIOY_PUEN_REG_OFFSET 0x4B
//------------------------------------------------------------------------------
#define GPIOX_PIN_START 97
#define GPIOX_PIN_END 118
#define GPIOX_FSEL_REG_OFFSET 0x0C
#define GPIOX_OUTP_REG_OFFSET 0x0D
#define GPIOX_INP_REG_OFFSET 0x0E
#define GPIOX_PUPD_REG_OFFSET 0x3E
#define GPIOX_PUEN_REG_OFFSET 0x4C
//------------------------------------------------------------------------------
#define MUX_REG0 0x5 // MUX_AO Block
#define MUX_REG1 0x2D
#define MUX_REG2 0x2E
#define MUX_REG3 0x2F
#define MUX_REG4 0x30
#define MUX_REG5 0x31
#define MUX_REG6 0x32
#define MUX_REG7 0x33
#define MUX_REG8 0x34
#define MUX_REG9 0x35
//------------------------------------------------------------------------------
#define BIT(x) (1 << x)
//------------------------------------------------------------------------------
const char MODE_STR[8][5] = {
" - ",
"ALT1",
"ALT2",
"ALT3",
"ALT4",
"ALT5",
"IN",
"OUT",
};
//------------------------------------------------------------------------------
const char PUPD_STR[3][5] = {
" - ",
"P/U",
"P/D",
};
//------------------------------------------------------------------------------
struct header_info {
int gpio;
char name[10];
};
//------------------------------------------------------------------------------
const struct header_info header_J2[40] = {
{ -1, "3.3V" }, { -1, "5.0V" },
{ 74, "I2CA_SDA" }, { -1, "5.0V" },
{ 75, "I2CA_SCL" }, { -1, "GND" },
{ 83, "GPIOY.3" }, { 113, "GPIOX.16" },
{ -1, "GND" }, { 114, "GPIOX.17" },
{ 88, "GPIOY.8" }, { 87, "GPIOY.7" },
{ 116, "GPIOX.19" }, { -1, "GND" },
{ 115, "GPIOX.18" }, { 104, "GPIOX.7" },
{ -1, "3.3V" }, { 102, "GPIOX.5" },
{ 107, "GPIOX.10" }, { -1, "GND" },
{ 106, "GPIOX.9" }, { 103, "GPIOX.6" },
{ 105, "GPIOX.8" }, { 117, "GPIOX.20" },
{ -1, "GND" }, { 118, "GPIOX.21" },
{ 76, "I2CB_SDA" }, { 77, "I2CB_SCL" },
{ 101, "GPIOX.4" }, { -1, "GND" },
{ 100, "GPIOX.3" }, { 99, "GPIOX.2" },
{ 108, "GPIOX.11" }, { -1, "GND" },
{ 97, "GPIOX.0" }, { 98, "GPIOX.1" },
{ -1, "ADC.AIN0" }, { -1, "1.8V REF" },
{ -1, "GND" }, { -1, "ADC.AIN1" },
};
//------------------------------------------------------------------------------
const struct header_info header_J7[7] = {
{ -1, "GND" },
{ 6, "GPIOAO.6" },
{ -1, "5.0V" },
{ 8, "GPIOAO.8" },
{ 10, "GPIOAO.10" },
{ 9, "GPIOAO.9" },
{ 11, "GPIOAO.11" },
};
//------------------------------------------------------------------------------------------------------------
int get_mode_gpiox (int pin)
{
switch(pin) {
case 0:
if (*(gpio + MUX_REG8) & BIT(5)) return 1;
if (*(gpio + MUX_REG5) & BIT(14)) return 2;
break;
case 1:
if (*(gpio + MUX_REG8) & BIT(4)) return 1;
if (*(gpio + MUX_REG5) & BIT(13)) return 2;
break;
case 2:
if (*(gpio + MUX_REG8) & BIT(3)) return 1;
if (*(gpio + MUX_REG5) & BIT(13)) return 2;
break;
case 3:
if (*(gpio + MUX_REG8) & BIT(2)) return 1;
if (*(gpio + MUX_REG5) & BIT(13)) return 2;
break;
case 4:
if ((*(gpio + MUX_REG5) & BIT(29)) && (*(gpio + MUX_REG5) & BIT(12)))
return 1;
if (*(gpio + MUX_REG3) & BIT(30)) return 2;
if (*(gpio + MUX_REG4) & BIT(17)) return 3;
break;
case 5:
if ((*(gpio + MUX_REG5) & BIT(28)) && (*(gpio + MUX_REG5) & BIT(12)))
return 1;
if (*(gpio + MUX_REG3) & BIT(29)) return 2;
if (*(gpio + MUX_REG4) & BIT(16)) return 3;
break;
case 6:
if ((*(gpio + MUX_REG5) & BIT(28)) && (*(gpio + MUX_REG5) & BIT(12)))
return 1;
if (*(gpio + MUX_REG3) & BIT(27)) return 2;
if (*(gpio + MUX_REG4) & BIT(15)) return 3;
if (*(gpio + MUX_REG5) & BIT(9)) return 4;
break;
case 7:
if ((*(gpio + MUX_REG5) & BIT(28)) && (*(gpio + MUX_REG5) & BIT(12)))
return 1;
if (*(gpio + MUX_REG3) & BIT(27)) return 2;
if (*(gpio + MUX_REG4) & BIT(14)) return 3;
if (*(gpio + MUX_REG5) & BIT(8)) return 4;
break;
case 8:
if (*(gpio + MUX_REG8) & BIT(1)) return 1;
if (*(gpio + MUX_REG5) & BIT(11)) return 2;
if (*(gpio + MUX_REG6) & BIT(19)) return 3;
if (*(gpio + MUX_REG4) & BIT(22)) return 4;
if (*(gpio + MUX_REG3) & BIT(6)) return 5;
break;
case 9:
if (*(gpio + MUX_REG8) & BIT(0)) return 1;
if (*(gpio + MUX_REG5) & BIT(10)) return 2;
if (*(gpio + MUX_REG6) & BIT(18)) return 3;
if (*(gpio + MUX_REG4) & BIT(24)) return 4;
if (*(gpio + MUX_REG3) & BIT(6)) return 5;
break;
case 10:
if (*(gpio + MUX_REG3) & BIT(22)) return 1;
if ((*(gpio + MUX_REG7) & BIT(31)) && (*(gpio + MUX_REG9) & BIT(19)))
return 2;
if (*(gpio + MUX_REG6) & BIT(17)) return 3;
if (*(gpio + MUX_REG4) & BIT(23)) return 4;
if (*(gpio + MUX_REG3) & BIT(8)) return 5;
break;
case 11:
if (*(gpio + MUX_REG3) & BIT(20)) return 1;
if (*(gpio + MUX_REG7) & BIT(30)) return 2;
if (*(gpio + MUX_REG2) & BIT(3)) return 5;
break;
case 16:
if (*(gpio + MUX_REG4) & BIT(9)) return 1;
if (*(gpio + MUX_REG4) & BIT(21)) return 4;
if (*(gpio + MUX_REG4) & BIT(5)) return 5;
break;
case 17:
if (*(gpio + MUX_REG4) & BIT(8)) return 1;
if (*(gpio + MUX_REG4) & BIT(20)) return 4;
if (*(gpio + MUX_REG4) & BIT(4)) return 5;
break;
case 18:
if (*(gpio + MUX_REG4) & BIT(7)) return 1;
if (*(gpio + MUX_REG4) & BIT(19)) return 4;
break;
case 19:
if (*(gpio + MUX_REG4) & BIT(6)) return 1;
if (*(gpio + MUX_REG4) & BIT(18)) return 4;
break;
case 20:
if (*(gpio + MUX_REG6) & BIT(16)) return 3;
if (*(gpio + MUX_REG4) & BIT(25)) return 4;
if (*(gpio + MUX_REG3) & BIT(9)) return 5;
break;
case 21:
break;
default :
return 0;
}
return *(gpio + GPIOX_FSEL_REG_OFFSET) & BIT(pin) ? 6 : 7;
}
//------------------------------------------------------------------------------------------------------------
int get_mode_gpioy (int pin)
{
switch(pin) {
case 0:
if (*(gpio + MUX_REG3) & BIT(2)) return 1;
break;
case 1:
if (*(gpio + MUX_REG3) & BIT(1)) return 1;
break;
case 3:
if (*(gpio + MUX_REG1) & BIT(7)) return 2;
if (*(gpio + MUX_REG3) & BIT(18)) return 3;
break;
case 6:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
break;
case 7:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
break;
case 8:
if (*(gpio + MUX_REG3) & BIT(0)) return 1;
break;
case 9:
if (*(gpio + MUX_REG3) & BIT(4)) return 1;
break;
case 10:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
break;
case 11:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
break;
case 12:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
break;
case 13:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
if (*(gpio + MUX_REG5) & BIT(7)) return 3;
break;
case 14:
if (*(gpio + MUX_REG3) & BIT(5)) return 1;
if (*(gpio + MUX_REG5) & BIT(6)) return 3;
break;
default :
return 0;
}
return *(gpio + GPIOY_FSEL_REG_OFFSET) & BIT(pin) ? 6 : 7;
}
//------------------------------------------------------------------------------------------------------------
int get_mode_gpiodv (int pin)
{
switch(pin) {
case 24:
if (*(gpio + MUX_REG6) & BIT(23)) return 4;
if (*(gpio + MUX_REG9) & BIT(31)) return 5;
break;
case 25:
if (*(gpio + MUX_REG6) & BIT(22)) return 4;
if (*(gpio + MUX_REG9) & BIT(30)) return 5;
break;
case 26:
if (*(gpio + MUX_REG6) & BIT(21)) return 4;
if (*(gpio + MUX_REG9) & BIT(29)) return 5;
break;
case 27:
if (*(gpio + MUX_REG6) & BIT(20)) return 4;
if (*(gpio + MUX_REG9) & BIT(28)) return 5;
break;
default :
return 0;
}
return *(gpio + GPIODV_FSEL_REG_OFFSET) & BIT(pin) ? 6 : 7;
}
//------------------------------------------------------------------------------------------------------------
int get_mode_gpioao (int pin)
{
switch(pin) {
case 0:
if (*(gpio_ao + MUX_REG0) & BIT(12)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(26)) return 3;
break;
case 1:
if (*(gpio_ao + MUX_REG0) & BIT(11)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(25)) return 3;
break;
case 2:
if (*(gpio_ao + MUX_REG0) & BIT(10)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(8)) return 3;
break;
case 3:
if (*(gpio_ao + MUX_REG0) & BIT(9)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(22)) return 2;
if (*(gpio_ao + MUX_REG0) & BIT(7)) return 3;
break;
case 4:
if (*(gpio_ao + MUX_REG0) & BIT(6)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(2)) return 2;
if (*(gpio_ao + MUX_REG0) & BIT(24)) return 3;
break;
case 5:
if (*(gpio_ao + MUX_REG0) & BIT(5)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(1)) return 2;
if (*(gpio_ao + MUX_REG0) & BIT(23)) return 3;
break;
case 6:
if (*(gpio_ao + MUX_REG0) & BIT(18)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(16)) return 4;
if (*(gpio + MUX_REG1) & BIT(13)) return 5;
break;
case 7:
if (*(gpio_ao + MUX_REG0) & BIT(0)) return 1;
if (*(gpio_ao + MUX_REG0) & BIT(21)) return 2;
break;
case 8:
if (*(gpio_ao + MUX_REG0) & BIT(30)) return 2;
return 1;
case 9:
if (*(gpio_ao + MUX_REG0) & BIT(29)) return 2;
if (*(gpio + MUX_REG1) & BIT(15)) return 5;
return 1;
case 10:
if (*(gpio_ao + MUX_REG0) & BIT(28)) return 2;
if (*(gpio + MUX_REG1) & BIT(14)) return 5;
return 1;
case 11:
if (*(gpio_ao + MUX_REG0) & BIT(27)) return 2;
return 1;
case 12:
if (*(gpio_ao + MUX_REG0) & BIT(17)) return 1;
break;
case 13:
if (*(gpio_ao + MUX_REG0) & BIT(31)) return 1;
break;
default :
return 0;
}
return *(gpio_ao + GPIOAO_FSEL_REG_OFFSET) & BIT(pin) ? 6 : 7;
}
//------------------------------------------------------------------------------------------------------------
int get_mode (int pin)
{
switch (pin) {
case GPIOX_PIN_START...GPIOX_PIN_END:
return get_mode_gpiox(pin - GPIOX_PIN_START);
case GPIOY_PIN_START...GPIOY_PIN_END:
return get_mode_gpioy(pin - GPIOY_PIN_START);
case GPIODV_PIN_START...GPIODV_PIN_END:
return get_mode_gpiodv(pin - GPIODV_PIN_START);
case GPIOAO_PIN_START...GPIOAO_PIN_END:
return get_mode_gpioao(pin - GPIOAO_PIN_START);
default :
break;
}
return 0;
}
//------------------------------------------------------------------------------------------------------------
int get_pupd (int pin)
{
switch (pin) {
case GPIOX_PIN_START...GPIOX_PIN_END:
if (*(gpio + GPIOX_PUEN_REG_OFFSET) & BIT(pin - GPIOX_PIN_START)) {
return *(gpio + GPIOX_PUPD_REG_OFFSET) & BIT(pin - GPIOX_PIN_START) ?
1 : 2;
}
break;
case GPIOY_PIN_START...GPIOY_PIN_END:
if (*(gpio + GPIOY_PUEN_REG_OFFSET) & BIT(pin - GPIOY_PIN_START)) {
return *(gpio + GPIOY_PUPD_REG_OFFSET) & BIT(pin - GPIOY_PIN_START) ?
1 : 2;
}
break;
case GPIODV_PIN_START...GPIODV_PIN_END:
if (*(gpio + GPIODV_PUEN_REG_OFFSET) & BIT(pin - GPIODV_PIN_START)) {
return *(gpio + GPIODV_PUPD_REG_OFFSET) & BIT(pin - GPIODV_PIN_START) ?
1 : 2;
}
break;
case GPIOAO_PIN_START...GPIOAO_PIN_END:
if (*(gpio_ao + GPIOAO_PUEN_REG_OFFSET) & BIT(pin - GPIOAO_PIN_START)) {
return *(gpio_ao + GPIOAO_PUPD_REG_OFFSET) & BIT(pin - GPIOAO_PIN_START + 16) ?
1 : 2;
}
break;
default :
break;
}
return 0; // PU/PD disable
}
//------------------------------------------------------------------------------------------------------------
int get_status (int pin)
{
switch (pin) {
case GPIOX_PIN_START...GPIOX_PIN_END:
return *(gpio + GPIOX_INP_REG_OFFSET) & BIT(pin - GPIOX_PIN_START) ?
1 : 0;
case GPIOY_PIN_START...GPIOY_PIN_END:
return *(gpio + GPIOY_INP_REG_OFFSET) & BIT(pin - GPIOY_PIN_START) ?
1 : 0;
case GPIODV_PIN_START...GPIODV_PIN_END:
return *(gpio + GPIODV_INP_REG_OFFSET) & BIT(pin - GPIODV_PIN_START) ?
1 : 0;
case GPIOAO_PIN_START...GPIOAO_PIN_END:
return *(gpio_ao + GPIOAO_INP_REG_OFFSET) & BIT(pin - GPIOAO_PIN_START) ?
1 : 0;
default :
break;
}
return 0;
}
//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
//
// system init
//
//------------------------------------------------------------------------------------------------------------
int system_init(void)
{
int fd;
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) {
fprintf(stderr, "/dev/mem open error!\n"); fflush(stdout);
return -1;
}
gpio = (unsigned int *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_REG_MAP);
gpio_ao = (unsigned int *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_AO_REG_MAP);
if((unsigned int)gpio == -1 || (unsigned int)gpio_ao == -1) {
fprintf(stderr, "mmap error!\n"); fflush(stdout);
return -1;
}
return 0;
}
//------------------------------------------------------------------------------------------------------------
//
// Start Program
//
//------------------------------------------------------------------------------------------------------------
int main (int argc, char *argv[])
{
int i;
if (system_init() < 0)
{
fprintf (stderr, "%s: System Init failed\n", __func__); fflush(stdout);
return -1;
}
printf("+------+----------+------+---+-------+--- J2 ---+-------+---+------+----------+------+\n");
printf("| GPIO | Name | Mode | V | PU/PD | Physical | PU/PD | V | Mode | Name | GPIO |\n");
printf("+------+----------+------+---+-------+----++----+-------+---+------+----------+------+\n");
for (i = 0; i < 40; i += 2) {
if (header_J2[i].gpio != -1) {
printf("| %3d | %8s | %4s | %d | %4s | %2d |",
header_J2[i].gpio,
header_J2[i].name,
MODE_STR[get_mode(header_J2[i].gpio)],
get_status(header_J2[i].gpio),
PUPD_STR[get_pupd(header_J2[i].gpio)],
i + 1);
}
else {
printf("| - | %8s | - | - | - | %2d |",
header_J2[i].name,
i + 1);
}
if (header_J2[i+1].gpio != -1) {
printf("| %2d | %4s | %d | %4s | %8s | %3d |\n",
i + 2,
PUPD_STR[get_pupd(header_J2[i+1].gpio)],
get_status(header_J2[i+1].gpio),
MODE_STR[get_mode(header_J2[i+1].gpio)],
header_J2[i+1].name,
header_J2[i+1].gpio);
}
else {
printf("| %2d | - | - | - | %8s | - |\n",
i + 2,
header_J2[i+1].name);
}
}
printf("+------+----------+------+---+-------+----++----+-------+---+------+----------+------+\n");
printf("+------+-----------+------+---+-------+--- J7 ---+\n");
printf("| GPIO | Name | Mode | V | PU/PD | Physical |\n");
printf("+------+-----------+------+---+-------+----------+\n");
for(i = 0; i < 7; i ++) {
if (header_J7[i].gpio != -1) {
printf("| %3d | %9s | %4s | %d | %4s | %2d |\n",
header_J7[i].gpio,
header_J7[i].name,
MODE_STR[get_mode(header_J7[i].gpio)],
get_status(header_J7[i].gpio),
PUPD_STR[get_pupd(header_J7[i].gpio)],
i + 1);
}
else {
printf("| - | %9s | - | - | - | %2d |\n",
header_J7[i].name,
i + 1);
}
}
printf("+------+-----------+------+---+-------+----------+\n");
fflush(stdout);
return 0 ;
}
//------------------------------------------------------------------------------------------------------------