Sorry, I will throw out a few things here, but not sure anything will help here or not.
First here is a sketch I was playing around with earlier. If I remember correctly I am not sure if it reduced the interrupt latency much if at all, but shows a few different registers...
Code:
#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);
}
Some of this test was a bust, in I did not get a specific pins interrupt to happen. I may play again at some point, to see if it is possible or not.
I see some issues in the code above, but I think it was just trying things out and left things in an inconsistent state. But to explain a little:
Suppose you wish to change one (or more pins) back from GPIO6 to GPIO1... Some of the steps needed would be:
You need to enable talking to GPIO1's registers else system will fault:
Code:
CCM_CCGR1 |= CCM_CCGR1_GPIO1(CCM_CCGR_ON);
You need tell the system to use GPIO1 instead of GPIO6 for those pins. Currently the line:
Code:
IOMUXC_GPR_GPR26 = 0xFFFFFFFF;
Says map all possible 32 GPIO pins from GPIO1 to GPIO6 (Which I currently have above... to map our Pin 0 (GPIO 1.3 or 6.3) back to GPIO1, the above line should be:
Code:
IOMUXC_GPR_GPR26 = 0xFFFFFFF7;
-----
Some of the other things I would look at include, how is the IO pin you are interested in configured. Again if you look at our logical Pin 0 you may want to look at the register:
IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_03 which is on page 652, to see things like Pull up, pull down, Speed, strength, slew rate, ... Not sure if any of these impact your timings and the like, but something to look at.
-----
And now for something completely different: Again I have not studied your requirements and the like, but wonder if you need that level of precision if the approach of grabbing timer in an ISR is the correct approach? That is I am wondering if instead you should be using a Timer using something like an input capture? That is have the timer capture the exact cycle that it detects the IO pin change values, then in your ISR, you can simply grab that value from the timers register(s)? Again I have not fully looked at the different timers to see if they can give you the resolution you require.
But you might look at some of the libraries and the like, that I believe does this. Example PulsePosition. Note: I don't think Paul has picked up the changes to support it on T4. I believe @mjs513 has the most up to date T4 version up at: https://github.com/mjs513/PulsePosition
Again not sure if any of this helps or not.