Strange GPIO Port Behaviour

Status
Not open for further replies.

Jay8ee

Member
Strange GPIO Port Behaviour (Teensy 3.6)

Hi all.

I am working on some code that reads a 16 bit address using 16 of the GPIO pins. I want these reads to be fast and as close to atomic as possible, therefore I am using the GPIO ports directly. However, when I read the address bits from the ports I get different results than if I use digitalReadFast for each pin and shift the bits.

Using this great post as a guide https://forum.pjrc.com/threads/1753...PORT-DDR-D-B-registers-vs-ARM-GPIO_PDIR-_PDOR along with the code documentation in core_pins.h I have chosen GPIO port C for the first 12 bits of the address and port B for the highest 4 bits. This is nice because the bits for the ranges I mention are contiguous, and makes read/write code fairly simple.

Here is how I am testing this (currently only testing first 12 bits from port C):

Code:
// A0 - A11 maps to GPIO port C (bits 0 - 11) . A12 - A15 maps to GPIO port B (bits 0 - 3)
#define A0  15
#define A1  22
#define A2  23
#define A3  9
#define A4  10
#define A5  13
#define A6  11
#define A7  12
#define A8  28
#define A9  27
#define A10 29
#define A11 30
#define A12 16
#define A13 17
#define A14 19
#define A15 18

static inline void setAddressMode(uint8_t mode)
{
  pinMode(A0, mode);
  pinMode(A1, mode);
  // ... do this for all the pins
}

// traditional address access
static inline uint16_t getAddr()
{
  uint16_t addr = 0;
  addr |= (digitalReadFast(A0));
  addr |= (digitalReadFast(A1) << 1);
  addr |= (digitalReadFast(A2) << 2);
  addr |= (digitalReadFast(A3) << 3);
  addr |= (digitalReadFast(A4) << 4);
  addr |= (digitalReadFast(A5) << 5);
  addr |= (digitalReadFast(A6) << 6);
  addr |= (digitalReadFast(A7) << 7);
  addr |= (digitalReadFast(A8) << 8);
  addr |= (digitalReadFast(A9) << 9);
  addr |= (digitalReadFast(A10) << 10);
  addr |= (digitalReadFast(A11) << 11);

  //addr |= (digitalReadFast(A12) << 12);
  //addr |= (digitalReadFast(A13) << 13);
  //addr |= (digitalReadFast(A14) << 14);
  //addr |= (digitalReadFast(A15) << 15);

  return addr;
}

void setup()
{
  setAddressMode(INPUT);  // set A0 - A15 to INPUT
  Serial.begin(250000);
}

void loop()
{
  Serial.begin(250000);
  while (1)
  {
    // currently just testing the lower 12 bits from the c register
    uint32_t cPortInput = GPIOC_PDIR;
    uint16_t addr = getAddr();

    Serial.println(addr, BIN);
    Serial.println(cPortInput , BIN);
    Serial.println("x");
  }
  Serial.end();
}
With the above code, I get the following output:

100001101
1101
x
100011110
11110
x



I am really not sure how this can be. A8 is clearly high active when using the traditional method, but it is low when reading the C port register directly. I would expect the cPortInput to match addr exactly in this test condition.

Would love to hear thoughts and suggestions.

Thanks.
 
Last edited by a moderator:
If that is really the code you are running, I wonder about:
Code:
static inline void setAddressMode(uint8_t mode)
{
  pinMode(A0, mode);
  pinMode(A1, mode);
  // ... do this for all the pins
}
Did you do it for all the pins?
 
If that is really the code you are running, I wonder about:
Code:
static inline void setAddressMode(uint8_t mode)
{
  pinMode(A0, mode);
  pinMode(A1, mode);
  // ... do this for all the pins
}
Did you do it for all the pins?

Yep, all pins. Code omitted for brevity. I've triple checked that code and I know its all good. The fact that getAddr works as intended is proof of that.

I just don't get what I am seeing when I print the register directly.
 
The Arduino style pin names A0- map to Teensy ports in strange ways. From the schematic they appear spread across all of the GPIO ports. Certainly not all on GPIOC.
 
Thanks for the reply, but I am fully aware of this. If you look at my code you can see that I am using all pins from the c register, apart from the last 4 bit, but I am not testing those in this code.
 
The problem is your data pin numbers are WRONG...
This one works...
Code:
// A0 - A11 maps to GPIO port C (bits 0 - 11) . A12 - A15 maps to GPIO port B (bits 0 - 3)
#define A0  15  // C0
#define A1  22  // c1
#define A2  23  //c2
#define A3  9   // C3
#define A4  10  // C4
#define A5  13  // C5
#define A6  11  //C6
#define A7  12  // C7
[COLOR="#FF0000"]#define A8  35  // C8 28 A16
#define A9  36  // C9   27 A15
#define A10 37  // C10  29
#define A11 38  // C11 30[/COLOR]
#define A12 16
#define A13 17
#define A14 19
#define A15 18

static inline void setAddressMode(uint8_t mode)
{
  pinMode(A0, mode);
  pinMode(A1, mode);
  pinMode(A2, mode);
  pinMode(A3, mode);
  pinMode(A4, mode);
  pinMode(A5, mode);
  pinMode(A6, mode);
  pinMode(A7, mode);
  pinMode(A8, mode);
  pinMode(A9, mode);
  pinMode(A10, mode);
  pinMode(A11, mode);
  // ... do this for all the pins
}

// traditional address access
static inline uint16_t getAddr()
{
  uint16_t addr = 0;
  addr |= (digitalReadFast(A0));
  addr |= (digitalReadFast(A1) << 1);
  addr |= (digitalReadFast(A2) << 2);
  addr |= (digitalReadFast(A3) << 3);
  addr |= (digitalReadFast(A4) << 4);
  addr |= (digitalReadFast(A5) << 5);
  addr |= (digitalReadFast(A6) << 6);
  addr |= (digitalReadFast(A7) << 7);
  addr |= (digitalReadFast(A8) << 8);
  addr |= (digitalReadFast(A9) << 9);
  addr |= (digitalReadFast(A10) << 10);
  addr |= (digitalReadFast(A11) << 11);

  //addr |= (digitalReadFast(A12) << 12);
  //addr |= (digitalReadFast(A13) << 13);
  //addr |= (digitalReadFast(A14) << 14);
  //addr |= (digitalReadFast(A15) << 15);

  return addr;
}

void setup()
{
  setAddressMode(INPUT_PULLDOWN);  // set A0 - A15 to INPUT
  Serial.begin(250000);
}

void loop()
{
  Serial.begin(250000);
  while (1)
  {
    // currently just testing the lower 12 bits from the c register
    uint32_t cPortInput = GPIOC_PDIR;
    uint16_t addr = getAddr();

    Serial.println(addr, BIN);
    Serial.println(cPortInput , BIN);
    Serial.println("x");
    delay(100);
  }
  Serial.end();
}

Note: I used INPUT_PULLDOWN as I did not have anything attached to pins, so did not want them floating...

Here is off one of my Excel document pages:
screenshot.jpg
 
Status
Not open for further replies.
Back
Top