Teensy 3.x Global Pin Control (Low~High) Register; PORTx_GPCLR ~ PORTx_GPCHR How-to

Chris O.

Well-known member
PORTx_GPCLR --- PORTx_GPCHR example:)
So I'm looking for Teensy 3.x example; yes I've been on the interwebs Google blah blah blah.
Basically I need to Tri-State (MUX(0) pin disable) several pins on Port D in one go (direct port manipulation).
I've seen plenty of this:
Code:
     PORTD_PCR7 = PORT_PCR_MUX(0); // DISABLE
     PORTD_PCR6 = PORT_PCR_MUX(0);
     PORTD_PCR5 = PORT_PCR_MUX(0);
     PORTD_PCR4 = PORT_PCR_MUX(0);
     PORTD_PCR3 = PORT_PCR_MUX(0);
     PORTD_PCR2 = PORT_PCR_MUX(0);
     PORTD_PCR1 = PORT_PCR_MUX(0);
     PORTD_PCR0 = PORT_PCR_MUX(0);
but I think we can do all this with Global Pin Control Low Register (PORTx_GPCLR) in one go, yet I am having difficulties reading the data sheets.

Can anyone point me in the right direction:D
 
Well I've been messing with this some more and I think I know how this works finally.
To set my D0 to D8 (8-bit) pins on Port D with 3-state logic which are defined as this:
Code:
#define D7  5   //PTD 07,           PORTD_PCR7
#define D6  21  //PTD 06,           PORTD_PCR6
#define D5  20  //PTD 05,           PORTD_PCR5
#define D4  6   //PTD 04,           PORTD_PCR4
#define D3  8   //PTD 03,           PORTD_PCR3
#define D2  7   //PTD 02,           PORTD_PCR2
#define D1  14  //PTD 01,           PORTD_PCR1
#define D0  2   //PTD 00,           PORTD_PCR0
All I need to do is this: PORTD_GPCLR = 0b00000000111111110000000000000000; // set pin D0 to D7 ~ PCRn all 0 disabled. 0x00FF0000 (tri-state)

I guess I need to come up with some type of example probably tomorrow.
 
As I was promising yesterday I came up with 8bit PORT D [D0 : D7] Global Pin Control Low Register (PORTx_GPCLR) Example. ;)
Code:
/* PORTD [D0:D7] Global Pin Control Low Register (PORTx_GPCLR) Example.
   Global pin control
  The two (PORTx_GPCLR - PORTx_GPCHR) global pin control registers allow a single register write to update the lower half
  of the pin control register on up to 16 pins, all with the same value.
  Registers that are locked cannot be written using the global pin control registers.
  The global pin control registers are designed to enable software to quickly configure
  multiple pins within the one port for the same peripheral function.
  However, the interrupt functions cannot be configured using the global pin control registers.
  The global pin control registers are write-only registers, that always read as 0.
*/

//  This way, data pins are all connected to T3.5, T3.6 Port D
//#define D15 54  //PTD 14,           PORTD_PCR15 // T3.5, T3.6 Port D [0:15] -- except port 10 --
//#define D14 51  //PTD 14,           PORTD_PCR14
//#define D13 52  //PTD 13,           PORTD_PCR13
//#define D12 53  //PTD 12,           PORTD_PCR12
//#define D11 55  //PTD 11,           PORTD_PCR11
//#define D10 -- Uunavailable on T3.5, T3.6 --
//#define D9  48  //PTD 09,           PORTD_PCR9
//#define D8  47  //PTD 08,           PORTD_PCR8
#define D7  5   //PTD 07,           PORTD_PCR7 // all T3.x Port D [0:7]
#define D6  21  //PTD 06,           PORTD_PCR6
#define D5  20  //PTD 05,           PORTD_PCR5
#define D4  6   //PTD 04,           PORTD_PCR4
#define D3  8   //PTD 03,           PORTD_PCR3
#define D2  7   //PTD 02,           PORTD_PCR2
#define D1  14  //PTD 01,           PORTD_PCR1
#define D0  2   //PTD 00,           PORTD_PCR0

int led = LED_BUILTIN; // Just to see something going on ):

void setup() {
  // put your setup code here, to run once:
  while (!Serial && millis() < 3000) {}  // wait for Serial Monitor 3 second timeout.
  pinMode(led, OUTPUT);
  digitalWriteFast(led, HIGH);    // turn the LED on
  delay(1000);                    // wait for a second
}

void loop() {
  // put your main code here, to run repeatedly:

  Write_Data(0); // Set all [D0:D7] LOW.
  Serial.println("Set all [D0:D7] LOW. Wait for a second.");
  digitalWriteFast(led, LOW);     // turn the LED off.
  delay(1000);                    // wait for a second.

  AcquireDataBus(); //[D0:D7]
  Serial.println("acquireDataBus() Set data pins [D0:D7] as output and set MUX0 = 1 Alt.1 GPIO. Wait for a second.");
  delay(1000);                    // wait for a second.

  Write_Data(0xFF); // Set all [D0:D7] HIGH.
  Serial.println("Set all [D0:D7] HIGH. Wait for a second.");
  digitalWriteFast(led, HIGH);    // turn the LED on
  delay(1000);                    // wait for a second.

  ReleaseDataBus();
  Serial.println("releaseDataBus() Release data pins by putting them back to Pin disabled (Tri-State) Mux Alt.0 and input. Wait 5 seconds.");
  delay(5000);                    // wait 5 seconds.
}

// Write a byte to the data pins PORT D [D0:D7]
static inline void Write_Data(uint8_t byte_) {
  // Port Data Output Register (GPIOx_PDOR)
  // This register configures the logic levels that are driven on each general-purpose output pins.
  GPIOD_PDOR = byte_; // Write to Port D [D0:D7] at a time.
  Serial.print("Write_Data(uint8_t) ");
  Serial.println(byte_, BIN); // display in binary format.
}

// Release data pins by putting them back to Pin disabled (tri-state) Mux Alt.0 and input.
static inline void ReleaseDataBus() {
  // Global Pin Control Low Register (PORTx_GPCLR) Only 32-bit writes are supported to this register (read returns 0).
  //                    GPWE 31–16      | GPWD 15–0
  // Selects Pin(15:0)Control Registers | Write PCRn value to selected pins in GPWE
  //                   PORTx_PCR(15:0)  ~ PORTx_PCRn ------- field descriptions
  //                  7654321076543210  7654321076543210
  //                  ||||||||||||||||  |---------------->15 LK   -Lock Register        ;0 PCRn fields [15:0]not locked        ;1 locked cannot be updated until system reset
  //                  ||||||||||||||||  ||--------------->14 Res. -This field is reserved
  //                  ||||||||||||||||  |||-------------->13 Res. -This field is reserved
  //                  ||||||||||||||||  ||||------------->12 Res. -This field is reserved
  //                  ||||||||||||||||  |||||------------>11 Res. -This field is reserved
  //                  ||||||||||||||||  ||||||----------->10 MUX2 -Pin Mux Control       ;000 Pin disabled (analog)             ;001 Alt. 1 ((GPIO) Teensy 3.x)
  //                  ||||||||||||||||  |||||||---------->9  MUX1 -Pin Mux Control       ;010 Alt. 2                            ;011 Alt. 3 (chip-specific).
  //                  ||||||||||||||||  ||||||||--------->8  MUX0 -Pin Mux Control       ; see Datasheets for the chips used on the Teensy*
  //                  ||||||||||||||||  |||||||||-------->7  Res. -This field is reserved
  //                  ||||||||||||||||  ||||||||||------->6  DSE  -Drive Strength Enable ;0 Low drive strength                  ;1 High drive strength.
  //                  ||||||||||||||||  |||||||||||------>5  ODE  -Open Drain Enable     ;0 Open drain output is disabled       ;1 enabled.
  //                  ||||||||||||||||  ||||||||||||----->4  PFE  -Passive Filter Enable ;0 disabled                            ;1 enabled.
  //                  ||||||||||||||||  |||||||||||||---->3  Res. -This field is reserved
  //                   \\\\\\\\\\\\\\\\ ||||||||||||||--->2  SRE  -Slew Rate Enable      ;0 Fast slew rate                      ;1 Slow slew rate.
  //                    \\\\\\\\\\\\\\\\|||||||||||||||-->1  PE   -Pull Enable           ;0 Int. pullup or pulldown not enabled ;1 enabled.
  //                    ||||||||||||||||||||||||||||||||->0  PS   -Pull Select           ;0 Internal pulldown                   ;1 Internal pullup.
  // (PORTx_GPCLR) GPWE | 15:8 |  7:0  |  15:8 |  7:0  | GPWD
  //                    76543210765432107654321076543210
  PORTD_GPCLR =       0b00000000111111110000000000000000; // set pin [D0:D7] ~ PCRn all 0 disabled. 0x00FF0000 (tri-state)

  /*
     PORTD_PCR7 = PORT_PCR_MUX(0); // DISABLE
     PORTD_PCR6 = PORT_PCR_MUX(0);
     PORTD_PCR5 = PORT_PCR_MUX(0);
     PORTD_PCR4 = PORT_PCR_MUX(0);
     PORTD_PCR3 = PORT_PCR_MUX(0);
     PORTD_PCR2 = PORT_PCR_MUX(0);
     PORTD_PCR1 = PORT_PCR_MUX(0);
     PORTD_PCR0 = PORT_PCR_MUX(0);
  */

  // Port Data Direction Register (GPIOx_PDDR)
  // The PDDR configures the individual port pins for input or output.
  // 0 Pin is configured as general-purpose input
  // 1 Pin is configured as general-purpose output,
  // The GPIO registers support 8-bit, 16-bit or 32-bit accesses.
  GPIOD_PDDR = 0b00000000; // Set PORTD[0:7] to input
}

// Set data pins as output and set MUX0 = 1 Alt.1 GPIO
static inline void AcquireDataBus() {
  // Port Data Direction Register (GPIOx_PDDR)
  // The PDDR configures the individual port pins for input or output.
  // 0 Pin is configured as general-purpose input
  // 1 Pin is configured as general-purpose output,
  // The GPIO registers support 8-bit, 16-bit or 32-bit accesses.
  GPIOD_PDDR = 0b11111111; // Set PORTD[0:7] to push-pull output

  // Global Pin Control Low Register (PORTx_GPCLR) Only 32-bit writes are supported to this register (read returns 0).
  //                    GPWE 31–16      | GPWD 15–0
  // Selects Pin(15:0)Control Registers | Write PCRn value to selected pins in GPWE
  //                   PORTx_PCR(15:0)  ~ PORTx_PCRn ------- field descriptions
  //                  7654321076543210  7654321076543210
  //                  ||||||||||||||||  |---------------->15 LK   -Lock Register        ;0 PCRn fields [15:0]not locked        ;1 locked cannot be updated until system reset
  //                  ||||||||||||||||  ||--------------->14 Res. -This field is reserved
  //                  ||||||||||||||||  |||-------------->13 Res. -This field is reserved
  //                  ||||||||||||||||  ||||------------->12 Res. -This field is reserved
  //                  ||||||||||||||||  |||||------------>11 Res. -This field is reserved
  //                  ||||||||||||||||  ||||||----------->10 MUX2 -Pin Mux Control       ;000 Pin disabled (analog)             ;001 Alt. 1 ((GPIO) Teensy 3.x)
  //                  ||||||||||||||||  |||||||---------->9  MUX1 -Pin Mux Control       ;010 Alt. 2                            ;011 Alt. 3 (chip-specific).
  //                  ||||||||||||||||  ||||||||--------->8  MUX0 -Pin Mux Control       ; see Datasheets for the chips used on the Teensy*
  //                  ||||||||||||||||  |||||||||-------->7  Res. -This field is reserved
  //                  ||||||||||||||||  ||||||||||------->6  DSE  -Drive Strength Enable ;0 Low drive strength                  ;1 High drive strength.
  //                  ||||||||||||||||  |||||||||||------>5  ODE  -Open Drain Enable     ;0 Open drain output is disabled       ;1 enabled.
  //                  ||||||||||||||||  ||||||||||||----->4  PFE  -Passive Filter Enable ;0 disabled                            ;1 enabled.
  //                  ||||||||||||||||  |||||||||||||---->3  Res. -This field is reserved
  //                   \\\\\\\\\\\\\\\\ ||||||||||||||--->2  SRE  -Slew Rate Enable      ;0 Fast slew rate                      ;1 Slow slew rate.
  //                    \\\\\\\\\\\\\\\\|||||||||||||||-->1  PE   -Pull Enable           ;0 Int. pullup or pulldown not enabled ;1 enabled.
  //                    ||||||||||||||||||||||||||||||||->0  PS   -Pull Select           ;0 Internal pulldown                   ;1 Internal pullup.
  // (PORTx_GPCLR) GPWE | 15:8 |  7:0  |  15:8 |  7:0  | GPWD
  //                    76543210765432107654321076543210
  PORTD_GPCLR =       0b00000000111111110000000101000000; // set pin [D0:D7] ~ PCRn (bit6 DSE= 1 High drive strength) ~ (bit8:10 MUX 0 1 2)= 001 Alt. 1 GPIO Teensy 3.x)

  /*
    PORTD_PCR7 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR6 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR5 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR4 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR3 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR2 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR1 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
    PORTD_PCR0 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
  */
}

// Teensy Schematic https://www.pjrc.com/teensy/schematic.html
// *This datasheets are the official technical reference for the chips used on the Teensy.       https://www.pjrc.com/teensy/datasheets.html
// MK20DX256 Manual (8.0M PDF), for Teensy 3.1 & 3.2 (All the useful peripheral programing info) https://www.pjrc.com/teensy/K20P64M72SF1RM.pdf
// MK64FX512 Manual (14.0M PDF), for Teensy 3.5 (All the useful peripheral programing info)      https://www.pjrc.com/teensy/K64P144M120SF5RM.pdf
// MK66FX1M0 Manual (19.1M PDF), for Teensy 3.6 (All the useful peripheral programing info)      https://www.pjrc.com/teensy/K66P144M180SF5RMV2.pdf
 
Back
Top