From: Gordon Henderson Date: Tue, 24 Jun 2014 18:23:31 +0000 (+0100) Subject: Updates for the Raspnerry Pi Compute Module - changes to the gpio program X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=wiringPi.git;a=commitdiff_plain;h=6fba403b2f749ae0ea64019037fc692f2de1483d Updates for the Raspnerry Pi Compute Module - changes to the gpio program to produce a nicer 'readall' output too. It also understands new pins 53,54,55 and 56 in wiringPiSetupPhys() mode to represent the pins on the P5 connector on the Rev 2 Pi's Changes to pinMode() to allow new modes SOFT_PWM and SOFT_TONE. --- diff --git a/gpio/gpio.c b/gpio/gpio.c index d941db5..c6021d4 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -79,6 +79,7 @@ char *usage = "Usage: gpio -v\n" " gpio gbw " ; // No trailing newline needed here. +#ifdef NOT_FOR_NOW /* * decodePin: * Decode a pin "number" which can actually be a pin name to represent @@ -96,6 +97,7 @@ static int decodePin (const char *str) return 0 ; } +#endif /* @@ -1042,6 +1044,8 @@ static void doPwmClock (int argc, char *argv []) int main (int argc, char *argv []) { int i ; + int model, rev, mem ; + char *maker ; if (getenv ("WIRINGPI_DEBUG") != NULL) { @@ -1086,7 +1090,10 @@ int main (int argc, char *argv []) printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("For details type: %s -warranty\n", argv [0]) ; printf ("\n") ; - printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ; + piBoardId (&model, &rev, &mem, &maker) ; + printf ("Raspberry Pi Details:\n") ; + printf (" Type: %s, Revision: %s, Memory: %dMB, Maker: %s\n", + piModelNames [model], piRevisionNames [rev], mem, maker) ; return 0 ; } diff --git a/gpio/pins.c b/gpio/pins.c index 6df3cb2..457922d 100644 --- a/gpio/pins.c +++ b/gpio/pins.c @@ -39,6 +39,17 @@ extern int wpMode ; void doPins (void) { + int model, rev, mem ; + char *maker ; + + piBoardId (&model, &rev, &mem, &maker) ; + if (model == PI_MODEL_CM) + { + printf ("This Raspberry Pi is a Compute Module.\n") ; + printf (" (who knows what's been done to the pins!)\n") ; + return ; + } + printf ("This Raspberry Pi is a revision %d board.\n", piBoardRev ()) ; printf ( diff --git a/gpio/readall.c b/gpio/readall.c index 8fc9f88..b363d3b 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -37,6 +37,11 @@ extern int wpMode ; +#ifndef TRUE +# define TRUE (1==1) +# define FALSE (1==2) +#endif + /* * doReadallExternal: * A relatively crude way to read the pins on an external device. @@ -90,7 +95,7 @@ static int wpiToPhys [64] = 3, 5, // 8...9 24, 26, 19, 21, 23, // 10..14 8, 10, // 15..16 - 3, 4, 5, 6, // 17..20 + 53, 54, 55, 56, // 17..20 0,0,0,0,0,0,0,0,0,0,0, // 20..31 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 32..47 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 47..63 @@ -115,11 +120,11 @@ static int physToWpi [64] = 14, 10, -1, 11, // 25, 26 -// Padding: - -1, -1, -1, -1, -1, // ... 31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 + -1, -1, -1, -1, -1, // ... 52 + 28, 29, 30, 31, // ... 53, 54, 55, 56 - P5 + -1, -1, -1, -1, -1, -1, -1, // ... 63 } ; static char *physNames [64] = @@ -140,9 +145,11 @@ static char *physNames [64] = "SCLK", "CE0", "0v", "CE1", - NULL,NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL, // ... 31 + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, // ... 47 + NULL,NULL,NULL,NULL,NULL, // ... 52 + "GPIO8", "GPIO9", "GPIO10", "GPIO11", // ... 53, 54, 55, 56 - P5 + NULL,NULL,NULL,NULL,NULL,NULL, // ... 63 } ; static void readallPhys (int physPin) @@ -225,6 +232,38 @@ static void readallPhys (int physPin) } +int cmReadall (void) +{ + int model, rev, mem ; + int pin ; + char *maker ; + + piBoardId (&model, &rev, &mem, &maker) ; + if (model != PI_MODEL_CM) + return FALSE ; + + printf ("+-----+------+-------+ +-----+------+-------+\n") ; + printf ("| Pin | Mode | Value | | Pin | Mode | Value |\n") ; + printf ("+-----+------+-------+ +-----+------+-------+\n") ; + + for (pin = 0 ; pin < 28 ; ++pin) + { + printf ("| %3d ", pin) ; + printf ("| %-4s ", alts [getAlt (pin)]) ; + printf ("| %s ", digitalRead (pin) == HIGH ? "High" : "Low ") ; + printf ("| ") ; + printf ("| %3d ", pin + 28) ; + printf ("| %-4s ", alts [getAlt (pin + 28)]) ; + printf ("| %s ", digitalRead (pin + 28) == HIGH ? "High" : "Low ") ; + printf ("|\n") ; + } + + printf ("+-----+------+-------+ +-----+------+-------+\n") ; + + return TRUE ; +} + + void doReadall (void) { int pin ; @@ -235,6 +274,9 @@ void doReadall (void) return ; } + if (cmReadall ()) + return ; + /**/ if (wpMode == WPI_MODE_GPIO) { printf (" +-----+-------+------+----+-Rev%d-----+----+------+-------+-----+\n", piBoardRev ()) ; @@ -275,6 +317,9 @@ void doReadallOld (void) return ; } + if (cmReadall ()) + return ; + printf ("+----------+-Rev%d-+------+--------+------+-------+\n", piBoardRev ()) ; printf ("| wiringPi | GPIO | Phys | Name | Mode | Value |\n") ; printf ("+----------+------+------+--------+------+-------+\n") ; diff --git a/wiringPi/softPwm.c b/wiringPi/softPwm.c index 0bde180..3c79ba7 100644 --- a/wiringPi/softPwm.c +++ b/wiringPi/softPwm.c @@ -67,11 +67,15 @@ int newPin = -1 ; static PI_THREAD (softPwmThread) { int pin, mark, space ; + struct sched_param param ; + + param.sched_priority = sched_get_priority_max (SCHED_RR) ; + pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; pin = newPin ; newPin = -1 ; - piHiPri (50) ; + piHiPri (90) ; for (;;) { @@ -159,5 +163,5 @@ void softPwmStop (int pin) pthread_join (threads [pin], NULL) ; range [pin] = 0 ; digitalWrite (pin, LOW) ; -} + } } diff --git a/wiringPi/softTone.c b/wiringPi/softTone.c index b4a89f8..e2fb737 100644 --- a/wiringPi/softTone.c +++ b/wiringPi/softTone.c @@ -36,7 +36,8 @@ #define PULSE_TIME 100 -static int freqs [MAX_PINS] ; +static int freqs [MAX_PINS] ; +static pthread_t threads [MAX_PINS] ; static int newPin = -1 ; @@ -50,6 +51,10 @@ static int newPin = -1 ; static PI_THREAD (softToneThread) { int pin, freq, halfPeriod ; + struct sched_param param ; + + param.sched_priority = sched_get_priority_max (SCHED_RR) ; + pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; pin = newPin ; newPin = -1 ; @@ -105,17 +110,41 @@ void softToneWrite (int pin, int freq) int softToneCreate (int pin) { int res ; + pthread_t myThread ; pinMode (pin, OUTPUT) ; digitalWrite (pin, LOW) ; + if (threads [pin] != 0) + return -1 ; + freqs [pin] = 0 ; newPin = pin ; - res = piThreadCreate (softToneThread) ; + res = pthread_create (&myThread, NULL, softToneThread, NULL) ; while (newPin != -1) delay (1) ; + threads [pin] = myThread ; + return res ; } + + +/* + * softToneStop: + * Stop an existing softTone thread + ********************************************************************************* + */ + +void softToneStop (int pin) +{ + if (threads [pin] != 0) + { + pthread_cancel (threads [pin]) ; + pthread_join (threads [pin], NULL) ; + threads [pin] = 0 ; + digitalWrite (pin, LOW) ; + } +} diff --git a/wiringPi/softTone.h b/wiringPi/softTone.h index d8b4e54..a93c5af 100644 --- a/wiringPi/softTone.h +++ b/wiringPi/softTone.h @@ -31,6 +31,7 @@ extern "C" { #endif extern int softToneCreate (int pin) ; +extern void softToneStop (int pin) ; extern void softToneWrite (int pin, int freq) ; #ifdef __cplusplus diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 4660a67..63a8946 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -71,6 +71,7 @@ #include #include "softPwm.h" +#include "softTone.h" #include "wiringPi.h" @@ -272,6 +273,7 @@ static int pinToGpioR2 [64] = // physToGpio: // Take a physical pin (1 through 26) and re-map it to the BCM_GPIO pin // Cope for 2 different board revisions here. +// Also add in the P5 connector, so the P5 pins are 3,4,5,6, so 53,54,55,56 static int *physToGpio ; @@ -292,8 +294,6 @@ static int physToGpioR1 [64] = 11, 8, -1, 7, // 25, 26 -// Padding: - -1, -1, -1, -1, -1, // ... 31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 @@ -316,11 +316,13 @@ static int physToGpioR2 [64] = 11, 8, -1, 7, // 25, 26 -// Padding: +// the P5 connector on the Rev 2 boards: -1, -1, -1, -1, -1, // ... 31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63 + -1, -1, -1, -1, -1, // ... 52 + 28, 29, 30, 31, // ... 53, 54, 55, 56 - P5 + -1, -1, -1, -1, -1, -1, -1, // ... 63 } ; @@ -547,22 +549,30 @@ int wiringPiFailure (int fatal, const char *message, ...) * * Much confusion here )-: * Seems there are some boards with 0000 in them (mistake in manufacture) - * and some board with 0005 in them (another mistake in manufacture?) * So the distinction between boards that I can see is: * 0000 - Error - * 0001 - Not used - * 0002 - Rev 1 - * 0003 - Rev 1 - * 0004 - Rev 2 (Early reports? - * 0005 - Rev 2 (but error?) - * 0006 - Rev 2 - * 0008 - Rev 2 - Model A - * 000e - Rev 2 + 512MB - * 000f - Rev 2 + 512MB + * 0001 - Not used (Compute - default to Rev 2) + * 0002 - Model B, Rev 1, 256MB + * 0003 - Model B, Rev 1.1, 256MB, Fuses/D14 removed. + * 0004 - Model B, Rev 2, 256MB, Sony + * 0005 - Model B, Rev 2, 256MB, Qisda + * 0006 - Model B, Rev 2, 256MB, Egoman + * 0007 - Model A, Rev 2, 256MB, Egoman + * 0008 - Model A, Rev 2, 256MB, Sony + * 0009 - Model A, Rev 2, 256MB, Qisda + * 000d - Model B, Rev 2, 512MB, Egoman + * 000e - Model B, Rev 2, 512MB, Sony + * 000f - Model B, Rev 2, 512MB, Qisda + * 0011 - Pi compute Module * * A small thorn is the olde style overvolting - that will add in * 1000000 * + * The Pi compute module has an revision of 0011 - since we only check the + * last digit, then it's 1, therefore it'll default to not 2 or 3 for a + * Rev 1, so will appear as a Rev 2. This is fine for the most part, but + * we'll properly detect the Compute Module later and adjust accordingly. + * ********************************************************************************* */ @@ -634,6 +644,89 @@ int piBoardRev (void) } +/* + * piBoardId: + * Do more digging into the board revision string as above, but return + * as much details as we can. + ********************************************************************************* + */ + +const char *piModelNames [] = +{ + "Model A", + "Model B", + "Compute Module", +} ; + +const char *piRevisionNames[] = +{ + "1", + "1.1", + "2", +} ; + +void piBoardId (int *model, int *rev, int *mem, char **maker) +{ + FILE *cpuFd ; + char line [120] ; + char *c ; + + piBoardRev () ; // Call this first to make sure all's OK. Don't care about the result. + + if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) + piBoardRevOops ("Unable to open /proc/cpuinfo") ; + + while (fgets (line, 120, cpuFd) != NULL) + if (strncmp (line, "Revision", 8) == 0) + break ; + + fclose (cpuFd) ; + + if (strncmp (line, "Revision", 8) != 0) + piBoardRevOops ("No \"Revision\" line") ; + +// Chomp trailing CR/NL + + for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c) + *c = 0 ; + + if (wiringPiDebug) + printf ("piboardId: Revision string: %s\n", line) ; + +// Scan to first digit + + for (c = line ; *c ; ++c) + if (isdigit (*c)) + break ; + +// Make sure its long enough + + if (strlen (c) < 4) + piBoardRevOops ("Bogus \"Revision\" line") ; + +// Extract last 4 characters: + + c = c + strlen (c) - 4 ; + +// Fill out the replys as appropriate + + /**/ if (strcmp (c, "0002") == 0) { *model = 1 ; *rev = 0 ; *mem = 256 ; *maker = "China" ; } + else if (strcmp (c, "0003") == 0) { *model = 1 ; *rev = 1 ; *mem = 256 ; *maker = "China" ; } + else if (strcmp (c, "0004") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Sony" ; } + else if (strcmp (c, "0005") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Qisda" ; } + else if (strcmp (c, "0006") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Egoman" ; } + else if (strcmp (c, "0007") == 0) { *model = 0 ; *rev = 2 ; *mem = 256 ; *maker = "Egoman" ; } + else if (strcmp (c, "0008") == 0) { *model = 0 ; *rev = 2 ; *mem = 256 ; *maker = "Sony" ; } + else if (strcmp (c, "0009") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Qisda" ; } + else if (strcmp (c, "000d") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Egoman" ; } + else if (strcmp (c, "000e") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Sony" ; } + else if (strcmp (c, "000f") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Egoman" ; } + else if (strcmp (c, "0011") == 0) { *model = 2 ; *rev = 1 ; *mem = 512 ; *maker = "Sony" ; } + else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = "Unkn" ; } +} + + + /* * wpiPinToGpio: * Translate a wiringPi Pin number to native GPIO pin number. @@ -974,7 +1067,8 @@ void pinMode (int pin, int mode) else if (wiringPiMode != WPI_MODE_GPIO) return ; - softPwmStop (origPin) ; + softPwmStop (origPin) ; + softToneStop (origPin) ; fSel = gpioToGPFSEL [pin] ; shift = gpioToShift [pin] ; @@ -985,6 +1079,8 @@ void pinMode (int pin, int mode) *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ; else if (mode == SOFT_PWM_OUTPUT) softPwmCreate (origPin, 0, 100) ; + else if (mode == SOFT_TONE_OUTPUT) + softToneCreate (origPin) ; else if (mode == PWM_OUTPUT) { if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin @@ -1376,8 +1472,18 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) if (pid == 0) // Child, exec { - execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; - return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; + if (access ("/usr/local/bin/gpio", X_OK)) + { + execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; + return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; + } + else if (access ("/usr/bin/gpio", X_OK)) + { + execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ; + return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ; + } + else + return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ; } else // Parent, wait wait (NULL) ; @@ -1538,13 +1644,17 @@ unsigned int micros (void) * * Default setup: Initialises the system into wiringPi Pin mode and uses the * memory mapped hardware directly. + * + * Changed now to revert to "gpio" mode if we're running on a Compute Module. ********************************************************************************* */ int wiringPiSetup (void) { - int fd ; - int boardRev ; + int fd ; + int boardRev ; + int model, rev, mem ; + char *maker ; if (getenv (ENV_DEBUG) != NULL) wiringPiDebug = TRUE ; @@ -1618,7 +1728,13 @@ int wiringPiSetup (void) initialiseEpoch () ; - wiringPiMode = WPI_MODE_PINS ; +// If we're running on a compute module, then wiringPi pin numbers don't really many anything... + + piBoardId (&model, &rev, &mem, &maker) ; + if (model == PI_MODEL_CM) + wiringPiMode = WPI_MODE_GPIO ; + else + wiringPiMode = WPI_MODE_PINS ; return 0 ; } diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 4eea3e5..5117cc9 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -43,6 +43,7 @@ #define PWM_OUTPUT 2 #define GPIO_CLOCK 3 #define SOFT_PWM_OUTPUT 4 +#define SOFT_TONE_OUTPUT 5 #define LOW 0 #define HIGH 1 @@ -65,6 +66,13 @@ #define INT_EDGE_RISING 2 #define INT_EDGE_BOTH 3 +// Pi model types + +#define PI_MODEL_A 0 +#define PI_MODEL_B 1 +#define PI_MODEL_CM 2 + + // Threads #define PI_THREAD(X) void *X (void *dummy) @@ -116,6 +124,12 @@ extern struct wiringPiNodeStruct *wiringPiNodes ; extern "C" { #endif +// Data + +extern const char *piModelNames [] ; +extern const char *piRevisionNames[] ; +extern const char *piComputeRevisionNames[] ; + // Internal extern int wiringPiFailure (int fatal, const char *message, ...) ; @@ -148,6 +162,7 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio // On-Board Raspberry Pi hardware specific stuff extern int piBoardRev (void) ; +extern void piBoardId (int *model, int *rev, int *mem, char **maker) ; extern int wpiPinToGpio (int wpiPin) ; extern int physPinToGpio (int physPin) ; extern void setPadDrive (int group, int value) ;