ubbctl/: also support decoding and setting of interrupts and alternate functions

This commit is contained in:
Werner Almesberger 2014-03-06 11:34:28 -03:00
parent 3f5c052288
commit 9e223f77e6
2 changed files with 88 additions and 11 deletions

View File

@ -30,7 +30,15 @@ respectively.
pull-up is enabled.
"F0" and "F1" indicate that the pin configured as a function (i.e.,
for the MMC controller) and does not operate as GPIO.
for the MMC controller) and does not operate as GPIO. If the second
function of the pin is selected, "Fb..." is shown instead of "F...".
"I..." indicates that the pin is configured as an interrupt. The
next letter defines the type of interrupt, "r" for rising edge,
"f" for falling edge, "h" for high level, and "l" for low level. If
the pull-up is enabled, ubbctl adds an "R". Finally, it shows the
pin status. E.g., "IfR1" would be an interrupt triggering on the
falling edge, with pull-up enabled, and currently inactive.
ubbctl can run in continuous mode, in which it updates the status
regularly (currently every 200 ms):

View File

@ -1,8 +1,8 @@
/*
* ubbctl.c - Set and query UBB signals
*
* Written 2013 by Werner Almesberger
* Copyright 2013 Werner Almesberger
* Written 2013-2014 by Werner Almesberger
* Copyright 2013-2014 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -46,6 +46,23 @@ static void show_pins(void)
pin = PIN(p->mask);
if (PDFUN & p->mask) {
putchar('F');
if (PDSEL & p->mask)
putchar('b');
} else if (PDSEL & p->mask) {
putchar('I');
if (PDTRG & p->mask) {
if (PDDIR & p->mask)
putchar('r');
else
putchar('f');
} else {
if (PDDIR & p->mask)
putchar('h');
else
putchar('l');
}
if (!(PDPULL & p->mask))
putchar('R');
} else if (PDDIR & p->mask) {
set = !!(PDDAT & p->mask);
if (pin != set)
@ -65,8 +82,10 @@ static void show_pins(void)
static int setup_pin(const char *s, int doit)
{
static const char trigger[] = "lhfrLHFR";
const struct pin *p;
const char *eq;
const char *eq, *t;
uint8_t trig;
if (!strcasecmp(s, "on"))
s = "nPWR=0";
@ -83,36 +102,86 @@ static int setup_pin(const char *s, int doit)
if (!p->name)
return 0;
if (!strcasecmp(eq+1, "f")) {
if (doit)
if (!strcasecmp(eq+1, "f") || !strcasecmp(eq+1, "fa")) {
if (doit) {
PDFUNS = p->mask;
} else if (!strcmp(eq+1, "0")) {
PDSELC = p->mask;
}
return 1;
}
if (!strcasecmp(eq+1, "fb")) {
if (doit) {
PDFUNS = p->mask;
PDSELS = p->mask;
}
return 1;
}
if (!strcmp(eq+1, "0")) {
if (doit) {
PDDATC = p->mask;
PDDIRS = p->mask;
PDFUNC = p->mask;
}
} else if (!strcmp(eq+1, "1")) {
return 1;
}
if (!strcmp(eq+1, "1")) {
if (doit) {
PDDATS = p->mask;
PDDIRS = p->mask;
PDFUNC = p->mask;
}
} else if (!strcasecmp(eq+1, "r")) {
return 1;
}
if (!strcasecmp(eq+1, "r")) {
if (doit) {
PDPULLC = p->mask;
PDDIRC = p->mask;
PDFUNC = p->mask;
PDSELC = p->mask;
}
} else if (!strcasecmp(eq+1, "z")) {
return 1;
}
if (!strcasecmp(eq+1, "z")) {
if (doit) {
PDPULLS = p->mask;
PDDIRC = p->mask;
PDFUNC = p->mask;
PDSELC = p->mask;
}
return 1;
}
if (eq[1] != 'i' && eq[1] != 'I')
return 0;
t = strchr(trigger, eq[2]);
if (!t || !*t)
return 0;
if (!eq[3] || eq[3] == 'z' || eq[3] == 'Z') {
if (doit)
PDPULLS = p->mask;
} else if (eq[3] == 'r' || eq[3] == 'R') {
if (doit)
PDPULLC = p->mask;
} else {
return 0;
}
if (!doit)
return 1;
PDFUNC = p->mask;
PDSELS = p->mask;
trig = (t-trigger) & 3;
if (trig & 1)
PDDIRS = p->mask;
else
PDDIRC = p->mask;
if (trig & 2)
PDTRGS = p->mask;
else
PDTRGC = p->mask;
return 1;
}
@ -124,7 +193,7 @@ static void usage(const char *name)
" %s name=value|action ...\n\n"
" -c continously update the pin status (until user interrupts)\n\n"
"Names: nPWR, CMD, CLK, DAT0, DAT1, DAT2, DAT3\n"
"Values: F, 0, 1, Z, R\n"
"Values: F, Fa, Fb, 0, 1, Z, R, Ir[R|Z], If[R|Z], Ih[R|Z], Il[R|Z]\n"
"Actions: ON, OFF\n"
, name, name);
exit(1);