Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Strange GPIO Port Behaviour

Threaded View

  1. #1
    Junior Member
    Join Date
    Jun 2019
    Posts
    10

    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/17532...PIO_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 KurtE; 09-10-2020 at 06:04 PM. Reason: code tag

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •