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

Thread: Raft of Teensy 4 pin\port parallel read questions

  1. #1
    Junior Member
    Join Date
    Oct 2019
    Posts
    11

    Raft of Teensy 4 pin\port parallel read questions

    [I'm rediting to get the port table below to work...I'll take any hints on how to input tables here, this is the best I could do. Spaces and tabs are your enemy.]
    I have some I\O intensive work I used a Teensy 3.6 for. I do direct reads on ports that have bits 0-7 exposed. Putting the two reads together yields the desired 16 bit input. I had had massive pin conflict problems arriving at this implementation, but I got it done. I used up every single CPU cycle and was able to sample an external ADC at 100khz on 8 simultaneous channels at 16 bits. The ADC goes to 200khz so I'm looking at Teensy 4 push that.

    With the reduced number of pins, the parallel input on Teensy 4.0 gets messier, but the added CPU speed can deal with it if the number of port reads can still be kept to 2 or less. Given the Teensy 4's CPU speed, it seems that I'd choose to execute the fewest port reads possible in favor of messier bit shuffling in the CPU. Please confirm.

    Paul mentioned Teensy 4.0 upgrades for next year. (I can't find the thread now.) Is there any advance info on how the pin-port mapping might work out? Any chance a port with a contiguous 16 bits might be exposed? That'd be sweet.

    With present Teensy4 units I'm expecting conflict mania sorting out what pins to use. I haven't tested doing port reads where unused pins in the port are configured for output, used for SPI etc. Any advice on things to look out for?

    If I understand the pinout correctly, I'll still need to make two port reads to take in a minimum of 16 bits. The obvious choices are AD_B1 and EMC. I have no idea what EMC is or what it might conflict with. Where can I read?

    If we assumed I was going to be using a Teensy 4 with SPI and an SD card, how could I hopscotch through the pins to obtain 16 bit bits with only two port reads and no conflicts? I mapped the Teensy 4 ports to bits below. I omitted the SD_B0 port assuming it would be off limits for SD card use.
    Bonus points for fewest CPU cycles to shuffle the bits into the proper order...its a pittance at 600mhz


    AD_B1_00...B0_00...B1_00
    AD_B1_01...B0_01...B1_01
    AD_B1_02...B0_02..............AD_B0_02
    AD_B1_03...B0_03..............AD_B0_03
    AD_B1_04........................................EM C_04
    .................................................. ...EMC_05
    AD_B1_06........................................EM C_06
    AD_B1_07........................................EM C_07
    AD_B1_08........................................EM C_08
    AD_B1_09
    AD_B1_10
    AD_B1_11
    ................B0_12..............AD_B0_12
    ......................................AD_B0_13
    AD_B1_14
    AD_B1_15

    .................................................. ..EMC_31
    .................................................. ..EMC_32

    .................................................. ..EMC_36
    .................................................. ..EMC_37
    Last edited by kdharbert; 10-11-2019 at 08:31 PM.

  2. #2
    Senior Member vjmuzik's Avatar
    Join Date
    Apr 2017
    Location
    Florida
    Posts
    379
    I prefer to look at the core_pins.h file to find the mappings, it seems a lot clearer to me than looking at the schematic. If you look here, there is actually a 16 bit port available with no conflict for SPI or the SD card pins, if you have the appropriate header to solder to the bottom pads then this can easily be done in one register read instead of two, saving you a little bit of time.
    Code:
    #define CORE_PIN0_PORTREG	GPIO6_DR
    #define CORE_PIN1_PORTREG	GPIO6_DR
    #define CORE_PIN2_PORTREG	GPIO9_DR
    #define CORE_PIN3_PORTREG	GPIO9_DR
    #define CORE_PIN4_PORTREG	GPIO9_DR
    #define CORE_PIN5_PORTREG	GPIO9_DR
    #define CORE_PIN6_PORTREG	GPIO7_DR
    #define CORE_PIN7_PORTREG	GPIO7_DR
    #define CORE_PIN8_PORTREG	GPIO7_DR
    #define CORE_PIN9_PORTREG	GPIO7_DR
    #define CORE_PIN10_PORTREG	GPIO7_DR
    #define CORE_PIN11_PORTREG	GPIO7_DR
    #define CORE_PIN12_PORTREG	GPIO7_DR
    #define CORE_PIN13_PORTREG	GPIO7_DR
    #define CORE_PIN14_PORTREG	GPIO6_DR
    #define CORE_PIN15_PORTREG	GPIO6_DR
    #define CORE_PIN16_PORTREG	GPIO6_DR
    #define CORE_PIN17_PORTREG	GPIO6_DR
    #define CORE_PIN18_PORTREG	GPIO6_DR
    #define CORE_PIN19_PORTREG	GPIO6_DR
    #define CORE_PIN20_PORTREG	GPIO6_DR
    #define CORE_PIN21_PORTREG	GPIO6_DR
    #define CORE_PIN22_PORTREG	GPIO6_DR
    #define CORE_PIN23_PORTREG	GPIO6_DR
    #define CORE_PIN24_PORTREG	GPIO6_DR
    #define CORE_PIN25_PORTREG	GPIO6_DR
    #define CORE_PIN26_PORTREG	GPIO6_DR
    #define CORE_PIN27_PORTREG	GPIO6_DR
    #define CORE_PIN28_PORTREG	GPIO8_DR
    #define CORE_PIN29_PORTREG	GPIO9_DR
    #define CORE_PIN30_PORTREG	GPIO8_DR
    #define CORE_PIN31_PORTREG	GPIO8_DR
    #define CORE_PIN32_PORTREG	GPIO7_DR
    #define CORE_PIN33_PORTREG	GPIO9_DR
    #define CORE_PIN34_PORTREG	GPIO8_DR
    #define CORE_PIN35_PORTREG	GPIO8_DR
    #define CORE_PIN36_PORTREG	GPIO8_DR
    #define CORE_PIN37_PORTREG	GPIO8_DR
    #define CORE_PIN38_PORTREG	GPIO8_DR
    #define CORE_PIN39_PORTREG	GPIO8_DR
    Also a simple way to shuffle the bits that makes sense to me, I'm not sure of the performance of this, there's probably a much better way to do this, but this is my take on it.
    Code:
    uint16_t busRead() {
        return  (GPIO6_DR & CORE_PIN0_BITMASK)   >> CORE_PIN0_BIT           | 
                (((GPIO6_DR & CORE_PIN1_BITMASK)   >> CORE_PIN1_BIT) << 1)  |
                (((GPIO6_DR & CORE_PIN14_BITMASK) >> CORE_PIN14_BIT) << 2)  |
                (((GPIO6_DR & CORE_PIN15_BITMASK) >> CORE_PIN15_BIT) << 3)  |
                (((GPIO6_DR & CORE_PIN16_BITMASK) >> CORE_PIN16_BIT) << 4)  |
                (((GPIO6_DR & CORE_PIN17_BITMASK) >> CORE_PIN17_BIT) << 5)  |
                (((GPIO6_DR & CORE_PIN18_BITMASK) >> CORE_PIN18_BIT) << 6)  |
                (((GPIO6_DR & CORE_PIN19_BITMASK) >> CORE_PIN19_BIT) << 7)  | 
                (((GPIO6_DR & CORE_PIN20_BITMASK) >> CORE_PIN20_BIT) << 8)  |
                (((GPIO6_DR & CORE_PIN21_BITMASK) >> CORE_PIN21_BIT) << 9)  |
                (((GPIO6_DR & CORE_PIN22_BITMASK) >> CORE_PIN22_BIT) << 10) |
                (((GPIO6_DR & CORE_PIN23_BITMASK) >> CORE_PIN23_BIT) << 11) |
                (((GPIO6_DR & CORE_PIN24_BITMASK) >> CORE_PIN24_BIT) << 12) |
                (((GPIO6_DR & CORE_PIN25_BITMASK) >> CORE_PIN25_BIT) << 13) |
                (((GPIO6_DR & CORE_PIN26_BITMASK) >> CORE_PIN26_BIT) << 14) |
                (((GPIO6_DR & CORE_PIN27_BITMASK) >> CORE_PIN27_BIT) << 15);
    }

  3. #3
    Junior Member
    Join Date
    Oct 2019
    Posts
    11
    Great post. Its clear I need help reading the schematic. CORE_PINX_PORTREG obviously maps to the Teensy pins. Per the schematic, this group of pins maps to both AD_B0 and AD_B1. Both of these groups can supply the 16 bits, but whats up with the terminology\labeling\naming? Its clear AD_B0 and AD_B1 aren't ports as I understand them...otherwise there wouldn't be pins they're both mapped to. Any help with my reasoning?

  4. #4
    Senior Member vjmuzik's Avatar
    Join Date
    Apr 2017
    Location
    Florida
    Posts
    379
    Those are the official names taken from the reference manual as far as I can tell and it looks like the very first letter is what port they are, so the 16 bit port is port A. Like I say, it's a little confusing, that's why I just prefer to look at core_pins.h it's a lot simpler for me to understand.

Posting Permissions

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