GPIO ports and related control register

TRNPep

Member
Good morning all, i recently bought a T4.1 and by looking at this page https://www.pjrc.com/teensy/pins.html i tried to control all of the output pin using DDR and PORT registers, just like I was working whit arduino, Yet, i found out running this simple program and checking the pins with a logic probe, that there were a lot of pin not covered by any PORT or DDR register.

byte state = 0x00;

void setup() {
DDRC= 0xFF;
PORTC = 0x0000;
}

void loop(){
state = 0xFF - state;
PORTC = state;
delay(150);
}

In this example i periodically toggle all PORTC, which turned out to be linked to pins 14 to 19. I did the same with PORTC and PORTD. Apparently PORTA doesn't exist since Teensyduino refuses to compile. Anyway, the only gpio ports that i found was B, C, D, yet i wasn't able to cover all of the digital pins. I took a look at the reference manual of the uC and i found that apparently all of those registers are 32 bits wide, so maybe i just wasn't toggling them. But as i tried a 32 bits version of the simple program nothing changed. Does any of you have any info on how to address digital pins using DDR and PORT register? Thanks guys!
 
Best to use native ARM register access rather than the ported attempt to support the old way.

Made a GPIO summary note here to recent info maybe it helps:
Code:
[URL="https://forum.pjrc.com/threads/64226-Teensy-4-1-Digital-I-O-pin-map?p=258026&viewfull=1#post258026"]pjrc.com/threads/64226-Teensy-4-1-Digital-I-O-pin-map?p=258026&viewfull=1#post258026[/URL]

[URL="https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf"]pjrc.com/teensy/IMXRT1060RM_rev2.pdf[/URL]

The port names to GPIO register mapping is documented in the reference manual

[url]https://www.pjrc.com/teensy/datasheets.html[/url]

Look on page 304-307 for the mapping info. On those pages you'll see the ports as GPIO1 to GPIO4.

Each port has 2 copies, a fast version and a DMA-accessible version. On Teensy you would normally access the pins on GPIO6 to GPIO9, which are the fast ones. So when you see the documentation say GPIO2, plan on actually using GPIO7.

The actual GPIO registers are documented in chapter 12. The registers are listed on page 962.

But the really important detail which is true is the GPIO registers do not support 8 bit access. You can't do any 8 bit access and expect to write to just those 8 bit and leave the other 24 untouched. The 32 bit GPIO registers in Teensy 3.x do support that sort of 8 bit access, but on Teensy 4.x the GPIO registers are strictly 32 bits.

There are more than a few other posts around with examples as well
 
ARM does not have these registers, they are emulated only.
Best is to use the native registers - defragster gave the links.
 
Thanks for your answers guys, i saw the reference manual, i read all of chapter 12 and i am aware that each GPIO has those 8 registers. My problem is really how to address them in coding (using teensyduino) do i need to define a pointer to those address and name it like the register (or whatever name)? I used to do something similar with a nucleo64 board a while ago. I really couldn't lay my eyes on any of the posts you are talking about tho, would you link them? I assume that when you talk about native registers you mean all of those 8 registers for each gpio. I apologize if my questions seems a little naif, yet I really appreciate your help. Anyway, i keep looking for more infos, thanks again
 
With some forum searching example will show usage. All the registers are already named and pointed to in TeensyDuino installed header files. Bing and google can find forum stuff as well or better sometimes.

For T_4.x check out the couple thousand lines in :: (arduino}\hardware\teensy\avr\cores\teensy4\core_pins.h

If you get stuck post for help if that doesn't lead to the needed info.

That file also has the Single Pin I/O functions for examples like:
Code:
uint8_t digitalRead(uint8_t pin);
static inline uint8_t digitalReadFast(uint8_t pin) __attribute__((always_inline, unused));
static inline uint8_t digitalReadFast(uint8_t pin)
{
	if (__builtin_constant_p(pin)) {
		if (pin == 0) {
			return (CORE_PIN0_PINREG & CORE_PIN0_BITMASK) ? 1 : 0;
 
TO SUM UP: i managed to latch each pin to his gpio port, yet some of those still refuses to cooperate. I think alternate functions is responsable for this. IOMUXC is a mess (?).

I am close. Thanks to core_pins.h i finally found out that i can address to the registers using for example GPIO3_DR, and so on for all of the GPIOs. Here is a list of all gpio with the latched pins:

Code:
GPIO6 ---> 0, 1, 14 to 27
GPIO7 ---> 6 to 13, 32
GPIO8 ---> 28 to 31, 34 to 39
GPIO9---> 2 to 5, 29 to 33

for reference, here's the original code 

/ Fast GPIO
#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

Now, i tried again the toggling code just to be sure, and some pins (a lot of them actually) are still not responding. This led me to think that some alternate function register was preventing those pins to be used as GPIO. So here comes the IOMUX control register. In page 304 there is a list of how gpio are linked to this register, and i find it really confusing. How come there are only GPIO1 to 5? Diving deeper in the IOMUXC specs literally makes me crazy, there are tons and tons of registers (35 actually). So, core_pins.h seems to have a list of defines to take care of those, but i really don't know how to properly use all this informations.
Code:
// mux config registers control which peripheral uses the pin
#define CORE_PIN0_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03
#define CORE_PIN1_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02
#define CORE_PIN2_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04
#define CORE_PIN3_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_05
#define CORE_PIN4_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06
#define CORE_PIN5_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_08
#define CORE_PIN6_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_10
#define CORE_PIN7_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01
#define CORE_PIN8_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00
#define CORE_PIN9_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11
#define CORE_PIN10_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00
#define CORE_PIN11_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02
#define CORE_PIN12_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01
#define CORE_PIN13_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03
#define CORE_PIN14_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02
#define CORE_PIN15_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03
#define CORE_PIN16_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07
#define CORE_PIN17_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06
#define CORE_PIN18_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_01
#define CORE_PIN19_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_00
#define CORE_PIN20_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10
#define CORE_PIN21_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11
#define CORE_PIN22_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08
#define CORE_PIN23_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09
#define CORE_PIN24_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12
#define CORE_PIN25_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13
#define CORE_PIN26_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_14
#define CORE_PIN27_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_15
#define CORE_PIN28_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32
#define CORE_PIN29_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31
#define CORE_PIN30_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_37
#define CORE_PIN31_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_36
#define CORE_PIN32_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_12
#define CORE_PIN33_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_07
#define CORE_PIN34_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03
#define CORE_PIN35_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_02
#define CORE_PIN36_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_01
#define CORE_PIN37_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00
#define CORE_PIN38_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_05
#define CORE_PIN39_CONFIG	IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_04

for reference, here's the testing code

Code:
int state = 0xFFFF;

void setup() {
  GPIO8_GDIR = 0xFFFF;
  Serial.begin(9600);
}

void loop() {
  state = 0xFFFF - state;
  GPIO8_DR = state;
  delay(200);
}
 
Post #2 here linked to Paul's post #4 on the other thread. There is more info in the rest of that thread - post #2 has a mapping of the pins doc courtesy of @KurtE - and indicates the swap 1-4 goes to 5-9 - but documented as 1-4

Also to use the pins as output they need to be set as output something like in: ...\hardware\teensy\avr\cores\teensy4\digital.c
Code:
void pinMode(uint8_t pin, uint8_t mode)
{
	const struct digital_pin_bitband_and_config_table_struct *p;

	if (pin >= CORE_NUM_DIGITAL) return;
	p = digital_pin_to_info_PGM + pin;
	if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
		*(p->reg + 1) |= p->mask; // TODO: atomic
		if (mode == OUTPUT) {
			*(p->pad) = IOMUXC_PAD_DSE(7);
		} else { // OUTPUT_OPENDRAIN
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
		}
	} else {
		*(p->reg + 1) &= ~(p->mask); // TODO: atomic
		if (mode == INPUT) {
			*(p->pad) = IOMUXC_PAD_DSE(7);
		} else if (mode == INPUT_PULLUP) {
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
		} else if (mode == INPUT_PULLDOWN) {
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
		} else { // INPUT_DISABLE
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_HYS;
		}
	}
	*(p->mux) = 5 | 0x10;
}
 
As mentioned, when we were doing the T4 and then the T4.1 betas, I created an excel spreadsheet which is up on github in the project:
https://github.com/KurtE/TeensyDocuments

It has several pages I believe 3 of them for the T4.1 (one is the original page of all of the pins data, another is a copy of it sorted in GPIO pin order, and another one which I mostly use is sort of an extended CARD with more data. That looks like:
T4.1-Cardlike.jpg

Most all of this information comes from the core pins header file as mentioned. As mentioned my document shows the IO pins using the GPIO1-5 numbering whereas in most cases the system uses GPIO6-9 for them. That pins on GPIO1 are also on GPIO6, where 6 is a faster buss, but it for example does not allow DMA. Also there are some more granular GPIO change interrupts that can be setup for GPIO1-5 (2 per port and some additional ones on GPIO1), where as for GPIO6-9 there is one IRQ...

When working with IO pins there are several things you need to be aware of, which the underlying system takes care of for you.

Each pin may have multiple different things it can do. For example Teensy pin 0
Can be GPIO1-3, but in addition it can be configures as an RX pin for CAN, can be setup as hardware CS pin for SPI1, it can be setup to be the RX pin for Serial1, or for PWM or as an XBar IO pin.

Only when it is configured to be a GPIO pin does the GPIO registers mention mean anything.

How a pin is configured is controlled by the IOMUXC system.

In the case of pin0 which is the native pin AD_B0_03, The mode the pin is in is controlled by the register: IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03
Which from Page 477 of my version of Imxrt pdf, that pin can be configured:
Code:
000 ALT0 — Select mux mode: ALT0 mux port: FLEXCAN2_RX of instance: flexcan2
001 ALT1 — Select mux mode: ALT1 mux port: XBAR1_INOUT17 of instance: xbar1
010 ALT2 — Select mux mode: ALT2 mux port: LPUART6_RX of instance: lpuart6
011 ALT3 — Select mux mode: ALT3 mux port: USB_OTG1_OC of instance: usb
100 ALT4 — Select mux mode: ALT4 mux port: FLEXPWM1_PWMX01 of instance: flexpwm1
101 ALT5 — Select mux mode: ALT5 mux port: GPIO1_IO03 of instance: gpio1
110 ALT6 — Select mux mode: ALT6 mux port: REF_CLK_24M of instance: anatop
111 ALT7 — Select mux mode: ALT7 mux port: LPSPI3_PCS0 of instance: lpspi3
So for GPIO it needs that field to be set to a 5...

So that configures the pin to which mode. But then there is additional stuff that needs to be configured for the logical PAD of the pin. Like on output how strong of a signal do you want, how fast should it be, Do you want Open Drain? For input, do you want Pull up or Pull down Resistors? This is all controlled by the IOMUXC Pad register for this pin. In this case:
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_03 which again in my PDF starts on page 636.

Now if you are wanting to use other subsystems - there are other interesting IOMUX registers you may need to set, for example if there is some logical function that can be configured to be on more than one IO pin, than there will likely be another register that controls which of those pins is the one for the function...

Simplest thing to do is simply use the Arduino functions, especially for initialization. That is you could do something like:
Code:
for(int i=0; i < 42; i++) pinMode(i, INPUT);
where INPUT could be OUTPUT, or INPUT_PULLUP or ...

Then if your goal is to read in multiple pins at same time, you can do that using the port registers.

Good luck
 
Thank you guys for all of you precious infos. I came to a solution, which is using pinMode to initialize the pins and then addressing the ports as GPIOn_DR. So basically I am now able to work as i wanted. Yet i still have some curiosity. Here is the pin to GPIO latching:

Code:
PIN   GPIOn-BITm  |  GPIOn-BITm    PIN
------------------|-------------------
00  -> GPIO6-03   |   GPIO6-02  ->  01
01  -> GPIO6-02   |   GPIO6-03  ->  00
02  -> GPIO9-04   |   GPIO6-12  ->  24
03  -> GPIO9-05   |   GPIO6-13  ->  25
04  -> GPIO9-06   |   GPIO6-16  ->  19
05  -> GPIO9-08   |   GPIO6-17  ->  18
06  -> GPIO7-10   |   GPIO6-18  ->  14
07  -> GPIO7-17   |   GPIO6-19  ->  15
08  -> GPIO7-16   |   GPIO6-20  ->  40
09  -> GPIO7-11   |   GPIO6-21  ->  41
10  -> GPIO7-00   |   GPIO6-22  ->  17
11  -> GPIO7-02   |   GPIO6-23  ->  16
12  -> GPIO7-01   |   GPIO6-24  ->  22
13  -> GPIO7-03   |   GPIO6-25  ->  23
14  -> GPIO6-18   |   GPIO6-26  ->  20
15  -> GPIO6-19   |   GPIO6-27  ->  21
16  -> GPIO6-23   |   GPIO6-28  ->  38
17  -> GPIO6-22   |   GPIO6-29  ->  39
18  -> GPIO6-17   |   GPIO6-30  ->  26
19  -> GPIO6-16   |   GPIO6-31  ->  27
20  -> GPIO6-26   |   GPIO7-00  ->  10
21  -> GPIO6-27   |   GPIO7-01  ->  12
22  -> GPIO6-24   |   GPIO7-02  ->  11
23  -> GPIO6-25   |   GPIO7-03  ->  13
24  -> GPIO6-12   |   GPIO7-10  ->  06
25  -> GPIO6-13   |   GPIO7-11  ->  09
26  -> GPIO6-30   |   GPIO7-12  ->  32
27  -> GPIO6-31   |   GPIO7-16  ->  08
28  -> GPIO8-18   |   GPIO7-17  ->  07
29  -> GPIO9-31   |   GPIO7-18  ->  36
30  -> GPIO8-23   |   GPIO7-19  ->  37
31  -> GPIO8-22   |   GPIO7-28  ->  35
32  -> GPIO7-12   |   GPIO7-29  ->  34
33  -> GPIO9-07   |   GPIO8-12  ->  45
34  -> GPIO7-29   |   GPIO8-13  ->  44
35  -> GPIO7-28   |   GPIO8-14  ->  43
36  -> GPIO7-18   |   GPIO8-15  ->  42
37  -> GPIO7-19   |   GPIO8-16  ->  47
38  -> GPIO6-28   |   GPIO8-17  ->  46
39  -> GPIO6-29   |   GPIO8-18  ->  28
40  -> GPIO6-20   |   GPIO8-22  ->  31
41  -> GPIO6-21   |   GPIO8-23  ->  30
42  -> GPIO8-15   |   GPIO9-04  ->  02
43  -> GPIO8-14   |   GPIO9-05  ->  03
44  -> GPIO8-13   |   GPIO9-06  ->  04
45  -> GPIO8-12   |   GPIO9-07  ->  33
46  -> GPIO8-17   |   GPIO9-08  ->  05
47  -> GPIO8-16   |   GPIO9-22  ->  51
48  -> GPIO9-24   |   GPIO9-24  ->  48
49  -> GPIO9-27   |   GPIO9-25  ->  53
50  -> GPIO9-28   |   GPIO9-26  ->  52
51  -> GPIO9-22   |   GPIO9-27  ->  49
52  -> GPIO9-26   |   GPIO9-28  ->  50
53  -> GPIO9-25   |   GPIO9-29  ->  54
54  -> GPIO9-29   |   GPIO9-31  ->  29

why does many GPIOs arenìt continous? I mean, why in GPIO6 not all 32 bit are defined and most importantly, why does the defined one are not in successive order? From my point of view this can be really annoying. For example, i cannot have an incrementing Byte. Sure i can work with any consecutive 8 pins, but i would need to "rescale" the resoult. So... any idea why?

really thanks again guys, you really made my start-off much much easier.
 
As you know a Teensy only has a limited number of pins available, however the processor has more pins than the Teensy form factor allows. The pins made available to the end user are carefully selected to offer the most amount of diversity for what people may need. That being said, GPIO6 has up to 16 continuous pins from bit 16-31, you can have an incrementing byte and just bit shift it 16 places to the left when you write it to the register. Bit shifts don’t put any kind of strain on the processor so there isn’t much down side besides one extra cpu cycle.
 
why does many GPIOs arenìt continous? I mean, why in GPIO6 not all 32 bit are defined and most importantly, why does the defined one are not in successive order? From my point of view this can be really annoying. For example, i cannot have an incrementing Byte. Sure i can work with any consecutive 8 pins, but i would need to "rescale" the resoult. So... any idea why?

really thanks again guys, you really made my start-off much much easier.

I'm using the upper 16 bits of GPIO6 on Teensy 4.1 to drive parallel TFT displays (ILI9488 480x320 and NT35510 800x480) in 8 and 16 bit modes, and just because the Teeny pinouts aren't consecutive doesn't really mean much - the pin numbers on the Teensy are arbitrary in this case, doesn't really matter much that I have to wire the TFT D0-D7 to pins 19,18,14,15,40,41,17,16 vs pin 1,2,3,4,5,6,7,8, etc? It's just 8 or 16 wires to 8 or 16 Teensy pins. Not sure what you refer to as an "incrementing byte" or "rescale" the readout, but I basically just push color data like this:

GPIO6_DR = (uint32_t)((d << 16)

where d contains the 8 or 16 bit color or command data. Of course, this is a 32 bit write and Teensy pins 0,1,24,25 are also on GPIO6 but as these are either unused or set to input in my application, I don't see any side effects.

Here are a few code snippets I have for setting up GPIO6, with the TFT 8 bit input wired to Teensy pins 19,18,14,15,40,41,17,16 (add in pins 22,23,20,21,38,39,26,27 for 16 bit):

Code:
volatile uint32_t *_writePort; 
volatile uint32_t *_readPort;
volatile uint32_t *_portDir;
uint32_t _portDirMask;
int8_t  _d0 = 19;

...

_writePort = portOutputRegister(_d0);
_readPort = portInputRegister(_d0);

_portDirMask = 0x00FF0000; //8 bit, for 16 bit I use 0xFFFF0000

...

//To write (data and commands):
*_portDir |= _portDirMask;  //Switch to output mode
*_writePort = (uint32_t)(d << 16);

...

//To read (mostly used to read the TFT GRAM to take a screenshot):
*_portDir &= ~_portDirMask;  //Switch to input mode
uint8_t ret = (uint8_t)(*_readPort >> 16); //8 bit
 
Port mapping GPIO 1-4 goes to 5-9

What in that pinMode function causes the mapping to the higher GPIO's?
I'm trying to use Paul's teensy core library from GitHub for the 4.1 in the Segger EmbOS environment with code that Segger provided. They however use the lower GPIO's.
I am suspecting it is this line
Code:
*(p->mux) = 5 | 0x10;

Post #2 here linked to Paul's post #4 on the other thread. There is more info in the rest of that thread - post #2 has a mapping of the pins doc courtesy of @KurtE - and indicates the swap 1-4 goes to 5-9 - but documented as 1-4

Also to use the pins as output they need to be set as output something like in: ...\hardware\teensy\avr\cores\teensy4\digital.c
Code:
void pinMode(uint8_t pin, uint8_t mode)
{
	const struct digital_pin_bitband_and_config_table_struct *p;

	if (pin >= CORE_NUM_DIGITAL) return;
	p = digital_pin_to_info_PGM + pin;
	if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
		*(p->reg + 1) |= p->mask; // TODO: atomic
		if (mode == OUTPUT) {
			*(p->pad) = IOMUXC_PAD_DSE(7);
		} else { // OUTPUT_OPENDRAIN
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
		}
	} else {
		*(p->reg + 1) &= ~(p->mask); // TODO: atomic
		if (mode == INPUT) {
			*(p->pad) = IOMUXC_PAD_DSE(7);
		} else if (mode == INPUT_PULLUP) {
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
		} else if (mode == INPUT_PULLDOWN) {
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
		} else { // INPUT_DISABLE
			*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_HYS;
		}
	}
	*(p->mux) = 5 | 0x10;
}
 
Back
Top