Quick answer/example for T_3.6 after : pinMode(LED_BUILTIN, OUTPUT);
Either of these will toggle the current state of LED Pin #13:
#define qBlink() {GPIOC_PTOR=32;}
#define qBlink() (digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) ))
void setup() {
pinMode(5, OUTPUT);
}
void loop() {
while (1) {
GPIO9_DR_TOGGLE = 1 << 8;
delayMicroseconds(1);
}
}
void setup() {
pinMode(5, OUTPUT);
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_08 = 0xFF;
noInterrupts();
}
void loop() {
while (1) {
GPIO9_DR_TOGGLE = 1 << 8;
}
}
void setup() {
pinMode(5, OUTPUT);
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_08 = 0xFF;
noInterrupts();
}
void loop() {
while (1) {
digitalWriteFast(5, HIGH);
digitalWriteFast(5, LOW);
}
}
Hello Paul,
I got the 150Mhz output, but got one more question.
I'm using the Pit lifetime timer for counting, in the document I see snibbets for setting the pit. I see in one example PIT at 50mhz and an other one PIT is 100mhz, how can I set this?
I'm using a state machine and this counter to generate on different pins different duty cycle outputs, but they have to start all at the same time.
hanz
The hardware register you seek is documented on page 1037 of the IMXRT1060 reference manual (rev 1, 12/2018).
https://www.pjrc.com/teensy/IMXRT1060RM_rev1.pdf
For the mapping, first check out the schematic to get the pad name.
https://www.pjrc.com/teensy/schematic.html
For example, if you choose pin 5, the pad name is EMC_08. Then to figure out which GPIO unit controls it, look up that pin in the IOMUX chapter. For the case of EMC_08, it's on page 434.
...
Thank you all for the answers it helps me a lot.
If I may, I try to find in the T4 environment the isr routines for the PIT. In 3.6 I had this running but do not get it how to do it in 4.
Thanks hanz
See this and its following posts https://forum.pjrc.com/threads/54711-Teensy-4-0-First-Beta-Test?p=195605&viewfull=1#post195605
Unfortunately GPIO4_IO08 is not the end of the story. Each pin can be controlled by either of 2 different GPIO units. GPIO 1 to 5 are accessed through a (slow) peripheral bridge. GPIO 6 to 9 are accessed by the fast AHB bus. By default (due to the startup code), we use the fast ones on Teensy 4.0.
This detail is buried in the reference manual, on pages 371-372.
View attachment 17697
GPIO9 is actually used.
...
But if you *really* want to mess with direct register access to the toggle register, there's all the info you'll need.
@Paul or other... I noticed the register you mentioned that changed using GPIO1->GPIO6
But What I have not noticed is anything in manual that describes the differences between the two. Or really for example describes GPIO6-9?
I am probably missing it, but ...
FASTRUN static inline __attribute__((always_inline))
inline void irq_anyport(volatile uint32_t *gpio, voidFuncPtr *table)
{
uint32_t status = gpio[ISR] & gpio[IMR];
if (status) {
gpio[ISR] = status;
while (status) {
uint32_t index = __builtin_ctz(status);
table[index]();
status = status & ~(1 << index);
//status = status & (status - 1);
}
}
}
FASTRUN
void irq_gpio6789(void)
{
irq_anyport(&GPIO6_DR, isr_table_gpio1);
irq_anyport(&GPIO7_DR, isr_table_gpio2);
irq_anyport(&GPIO8_DR, isr_table_gpio3);
irq_anyport(&GPIO9_DR, isr_table_gpio4);
}
#define IRQ_PIN 0
#define ECHO_PIN 1
#define TRIGGER_PIN 2
#define IRQ2_PIN 3
#define ECHO2_PIN 4
#define TRIGGER2_PIN 5
#define CORE_PIN0_PINREG_SLOW GPIO1_PSR
#define readFastIRQPin() ((CORE_PIN0_PINREG_SLOW & CORE_PIN0_BITMASK) ? 1 : 0)
uint32_t cycles_per_second = 100; //
void setup() {
while (!Serial && millis() < 5000) ;
Serial.begin(115200);
pinMode(IRQ_PIN, INPUT);
pinMode(ECHO_PIN, OUTPUT);
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW);
Serial.printf("Test IRQ timing:\n Pins IRQ:%d ECHO:%d TRIGGER: %d\n", IRQ_PIN, ECHO_PIN, TRIGGER_PIN);
pinMode(IRQ2_PIN, INPUT);
pinMode(ECHO2_PIN, OUTPUT);
pinMode(TRIGGER2_PIN, OUTPUT);
digitalWrite(TRIGGER2_PIN, LOW);
Serial.printf(" Normal pins: IRQ:%d ECHO:%d TRIGGER: %d\n", IRQ2_PIN, ECHO2_PIN, TRIGGER2_PIN);
delay(500);
//---------------------------------------------
// First lets setup pin 0 to slow mode and direct ISR...
CCM_CCGR1 |= CCM_CCGR1_GPIO1(CCM_CCGR_ON);
attachInterruptVector(IRQ_GPIO1_0_15, &pin_isr);
NVIC_ENABLE_IRQ(IRQ_GPIO1_0_15);
Serial.println("After Attach"); Serial.flush();
// I think this will have GPIO1 handle its pin 3
IOMUXC_GPR_GPR26 = 0xFFFFFFFF;
Serial.println("After set IOMUXC"); Serial.flush();
GPIO1_ICR1 = 0x00; // set to 0
Serial.println("After set ICR1"); Serial.flush();
GPIO1_GDIR &= ~0x08; // Make sure set as input in GPIO1
GPIO1_EDGE_SEL = 0x08; // set to 0
GPIO1_ISR = 0xffff;
Serial.println("After set ISR1"); Serial.flush();
GPIO1_IMR = 0x08;
Serial.println("After set GPIO"); Serial.flush();
//---------------------------------------------
// Next setup pin 3 to use attach interrupt in normal mode
attachInterrupt(IRQ2_PIN, &pin2_isr, CHANGE);
}
volatile uint32_t irq_count = 0;
void pin_isr(void) {
digitalWriteFast(ECHO_PIN, digitalReadFast(IRQ_PIN));
irq_count++;
GPIO1_ISR = 0x08; // clear the IRQ
asm("dsb");
}
void pin2_isr(void) {
digitalWriteFast(ECHO2_PIN, digitalReadFast(IRQ2_PIN));
irq_count++;
}
void loop() {
// put your main code here, to run repeatedly:
Serial.printf("Enter cycles per second default(%d):", cycles_per_second);
while (!Serial.available()) ;
uint32_t cps = 0;
int ch;
while ((ch = Serial.read()) != -1) {
if ((ch >= '0') && (ch <= '9')) cps = cps * 10 + ch - '0';
}
if (cps) {
cycles_per_second = cps;
}
uint32_t delay_per_cycle = 1000000 / (cycles_per_second * 2);
irq_count = 0;
elapsedMicros em = 0;
for (uint32_t i = 0; i < cycles_per_second; i++) {
digitalWriteFast(TRIGGER_PIN, HIGH);
delayMicroseconds(delay_per_cycle);
digitalWriteFast(TRIGGER_PIN, LOW);
delayMicroseconds(delay_per_cycle);
}
uint32_t delta_time = em;
Serial.printf("\nDirect IRQs processed: %u dt: %d calc:%d\n", irq_count,
delta_time, delay_per_cycle * 2 * cycles_per_second);
// Now do normal way
irq_count = 0;
em = 0;
for (uint32_t i = 0; i < cycles_per_second; i++) {
digitalWriteFast(TRIGGER2_PIN, HIGH);
delayMicroseconds(delay_per_cycle);
digitalWriteFast(TRIGGER2_PIN, LOW);
delayMicroseconds(delay_per_cycle);
}
delta_time = em;
Serial.printf("Normal IRQs processed: %u dt: %d calc:%d\n", irq_count,
delta_time, delay_per_cycle * 2 * cycles_per_second);
}
Test IRQ timing:
Pins IRQ:0 ECHO:1 TRIGGER: 2
Normal pins: IRQ:3 ECHO:4 TRIGGER: 5
After Attach
After set IOMUXC
After set ICR1
After set ISR1
After set GPIO
Enter cycles per second default(100):
Direct IRQs processed: 200 dt: 1000004 calc:1000000
Normal IRQs processed: 200 dt: 1000005 calc:1000000
Enter cycles per second default(100):
Direct IRQs processed: 200 dt: 1000004 calc:1000000
Normal IRQs processed: 200 dt: 1000005 calc:1000000
Enter cycles per second default(100):
Direct IRQs processed: 2000 dt: 1000040 calc:1000000
Normal IRQs processed: 2000 dt: 1000043 calc:1000000
Enter cycles per second default(1000):