SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
User avatar
By jugglerY2K
#207491
I need some help finding the pin mapping for interrupts on the Artemis ATP. It appears from the non-sequential pin labels on the Artemis boards (e.g not D0-D13 like a Mega) that these trace directly to the Apollo3 pads -- true?

I looked at the summary pinout you provided here, but it does not indicate the interrupt locations. https://cdn.sparkfun.com/assets/8/2/3/3 ... apping.pdf

I also searched through the full Apollo3 Blue data sheet, but could not decode interupt-t-pin/pad map from there.
https://ambiqmicro.com/static/mcu/files ... 349yoT.pdf

I'd appreciate some help. Thanks!
User avatar
By liquid.soulder
#207509
Your intuition is good - indeed the numbers on the ATP correspond to Apollo3 pads. As for interrupt mapping... the Apollo3 is interrupt capable on all its GPIO. Are you trying to use interrupts in Arduino or in the AmbiqSuite SDK?

In Arduino it is as simple as
Code: Select all
attachInterrupt(digitalPinToInterrupt( pin, isr, mode);
attachInterruptArg(digitalPinToInterrupt( pin, isrArg, arg, mode);
(isr is a function with signature void void, isrArg has a signature void void* and arg is a void* pointer that gets passed to isrArg when it is called)

In the SDK you will need to perform these steps:
- ensure that the pin configuration has interrupts enabled
- enable GPIO peripheral interrupts in the NVIC
- enable master interrupts

I guess that's all to say that there is no interrupt mapping like there may be on other microcontrollers - all GPIO interrupts get routed to
Code: Select all
void am_gpio_isr(void)
at which point you can determine which flags are set by
Code: Select all
    uint64_t gpio_int_mask = 0x00;
    am_hal_gpio_interrupt_status_get(true, &gpio_int_mask);
and clear flags once they are handled with
Code: Select all
am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(gpio_int_mask );
Does that help answer your question?
User avatar
By jugglerY2K
#207537
Great - thanks! That's the answer I was hoping for.

In the past, there have boards (different vendor) that said "any GPIO can be an interrupt" but then under the hood several pins share the same underlying IRQ, many multiple pins trip the same interrupt... This took a long time to determine and in the meantime led to much insanity.

I'm just using vanilla Arduino to code this, BTW. Thanks for the code snippets.
User avatar
By jugglerY2K
#207557
Hmm... looking further at the full Apollo3 data sheet, I'm confused again.

It seems to indicate 32 interrupts (see snipped below). But you mentioned that all 48 GPIO pins can be used as interrupts. That doesn't seem to agree. Or, perhaps I poorly worded what I want. I'll try again: What pins on the Artemis ATP can I utilize to get 20 unique (independent) interrupts? I plan to use with 10 hall-effect encoders, each of which require 2 interrupt channels.

From the Apollo3 datasheet (https://cdn.sparkfun.com/assets/learn_t ... v0_9_1.pdf):
"High-performance ARM Cortex-M4 Processor
- 48 MHz nominal clock frequency, with 96 MHz high performance “TurboSPOT” Burst Mode
- Floating point unit
- Memory protection unit
- Wake-up interrupt controller with 32 interrupts"
User avatar
By VA3SU
#207603
Ambiq has a real sense of humor when it comes to pin numbers. Starting pads at pad zero. Hardware people at Ambiq must be gritting their teeth.
User avatar
By davidmdj
#207850
I believe that all GPIO pins are available for interrupts. When a GPIO interrupt occurs on any of those pins, it will generate an IRQ13 (one of the 32 interrupt sources, per the data sheet). You would then have to read the GPIO interrupt status registers to determine the specific GPIO pin associated with the interrupt (see the data sheet, Sec 11.7.2). Then, you can execute the appropriate ISR handler for that pin. I assume that you need to check all necessary status register bits to service all outstanding interrupts (based on your design). I've left out some details, that's just a very top level perspective based on my previous experience.
User avatar
By jugglerY2K
#208123
Thanks for the insights. Everything checks out. I was able to get 20 pins using interrupts without any cross-talk.

In case it helps someone else, I'm sharing my ugly brute-force sketch that creates an interrupt routine for each of 20 pins. I tested by using a jumper wire from ground to each of these pins one-by-one to ensure only the counter for the respective pin is incrementing. Previously (on a Metro M0 Express board), pins shared underlying ISR's, causing PinA's toggle to increment Pin B's counter. That wasn't fun -- for the longest time I thought I had a hardware short or brownout issue from encoders.
Code: Select all
/*
 Brute force check to ensure hardware interrupts aren't cross-talking.  Tested with a jumper from ground, then going one-by one down the pins.  
 
 Listed here in order they are phyisically on the board. Starting nearest the usb plug and moving down, but skipping pins w/o numbers.  Then a few on the left (I needed 20).
 Going down the list twice and watching the counts, I confirmed no Pin's count was being incremented by another pin (a problem I had with Metro M0 boards).
*/

int count_13=0;
int count_12=0;
int count_32=0;
int count_28=0;
int count_27=0;

int count_23=0;
int count_22=0;
int count_04=0;
int count_35=0;
int count_14=0;

int count_08=0;
int count_10=0;
int count_09=0;
int count_26=0;
int count_15=0;

int count_19=0;
int count_18=0;
int count_17=0;
int count_41=0;
int count_45=0;



// defines pin number on the board (not the pin's current value)
int Pin_13=13;
int Pin_12=12;
int Pin_32=32;
int Pin_28=28;
int Pin_27=27;
            
int Pin_23=23;
int Pin_22=22;
int Pin_04=4;
int Pin_35=35;
int Pin_14=14;
            
int Pin_08=8;
int Pin_10=10;
int Pin_09=9;
int Pin_26=26;
int Pin_15=15;
            
int Pin_19=19;
int Pin_18=18;
int Pin_17=17;
int Pin_41=41;
int Pin_45=45;




void setup() {
  //start serial connection
  Serial.begin(9600);
  //configure as an input and enable the internal pull-up resistor
  pinMode(13, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(32, INPUT_PULLUP);
  pinMode(28, INPUT_PULLUP);
  pinMode(27, INPUT_PULLUP);
          
  pinMode(23, INPUT_PULLUP);
  pinMode(22, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(35, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
          
  pinMode(8, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
          
  pinMode(19, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(41, INPUT_PULLUP);
  pinMode(45, INPUT_PULLUP);
  pinMode(5, OUTPUT);

attachInterrupt(digitalPinToInterrupt(Pin_13), myIntRoutine_13, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_12), myIntRoutine_12, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_32), myIntRoutine_32, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_28), myIntRoutine_28, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_27), myIntRoutine_27, RISING);
                                                             
attachInterrupt(digitalPinToInterrupt(Pin_23), myIntRoutine_23, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_22), myIntRoutine_22, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_04), myIntRoutine_04, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_35), myIntRoutine_35, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_14), myIntRoutine_14, RISING);
                                                             
attachInterrupt(digitalPinToInterrupt(Pin_08), myIntRoutine_08, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_10), myIntRoutine_10, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_09), myIntRoutine_09, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_26), myIntRoutine_26, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_15), myIntRoutine_15, RISING);
                                                             
attachInterrupt(digitalPinToInterrupt(Pin_19), myIntRoutine_19, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_18), myIntRoutine_18, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_17), myIntRoutine_17, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_41), myIntRoutine_41, RISING);
attachInterrupt(digitalPinToInterrupt(Pin_45), myIntRoutine_45, RISING);
}

void loop() {
 
Serial.println("I still exist...");
delay(2000);
}
////////////////////
// Create interrupt routine for each pin...

void   myIntRoutine_13(){
              count_13++;
      Serial.print("_13 Within the ISR; count value ->");
Serial.println(count_13);
}                    
                     
void   myIntRoutine_12(){
              count_12++;
      Serial.print("_12 Within the ISR; count value ->");
Serial.println(count_12);
}                    
                     
void   myIntRoutine_32(){
              count_32++;
      Serial.print("_32 Within the ISR; count value ->");
Serial.println(count_32);
}                    
                     
void   myIntRoutine_28(){
              count_28++;
      Serial.print("_28 Within the ISR; count value ->");
Serial.println(count_28);
}                    
                     
void   myIntRoutine_27(){
              count_27++;
      Serial.print("_27 Within the ISR; count value ->");
Serial.println(count_27);
}                      
                       
void   myIntRoutine_23(){
              count_23++;
      Serial.print("_23 Within the ISR; count value ->");
Serial.println(count_23);
}                    
                     
void   myIntRoutine_22(){
              count_22++;
      Serial.print("_22 Within the ISR; count value ->");
Serial.println(count_22);
}                    
                     
void   myIntRoutine_04(){
              count_04++;
      Serial.print("_04 Within the ISR; count value ->");
Serial.println(count_04);
}                    
                     
void   myIntRoutine_35(){
              count_35++;
      Serial.print("_35 Within the ISR; count value ->");
Serial.println(count_35);
}                    
                     
void   myIntRoutine_14(){
              count_14++;
      Serial.print("_14 Within the ISR; count value ->");
Serial.println(count_14);
}                    
                     
void   myIntRoutine_08(){
              count_08++;
      Serial.print("_08 Within the ISR; count value ->");
Serial.println(count_08);
}                    
                     
void   myIntRoutine_10(){
              count_10++;
      Serial.print("_10 Within the ISR; count value ->");
Serial.println(count_10);
}                    
                     
void   myIntRoutine_09(){
              count_09++;
      Serial.print("_09 Within the ISR; count value ->");
Serial.println(count_09);
}                    
                     
void   myIntRoutine_26(){
              count_26++;
      Serial.print("_26 Within the ISR; count value ->");
Serial.println(count_26);
}                    
                     
void   myIntRoutine_15(){
              count_15++;
      Serial.print("_15 Within the ISR; count value ->");
Serial.println(count_15);
}                    
                       
void   myIntRoutine_19(){
              count_19++;
      Serial.print("_19 Within the ISR; count value ->");
Serial.println(count_19);
}                    
                     
void   myIntRoutine_18(){
              count_18++;
      Serial.print("_18 Within the ISR; count value ->");
Serial.println(count_18);
}                    
                     
void   myIntRoutine_17(){
              count_17++;
      Serial.print("_17 Within the ISR; count value ->");
Serial.println(count_17);
}                    
                     
void   myIntRoutine_41(){
              count_41++;
      Serial.print("_41 Within the ISR; count value ->");
Serial.println(count_41);
}                    
                     
void   myIntRoutine_45(){
              count_45++;
      Serial.print("_45 Within the ISR; count value ->");
Serial.println(count_45);
}
User avatar
By E.HP.S
#244642
Is there a way to clear the interrupts manually in the Arduino core? I'm running into (an apparently classic) error where the Artemis "Remembers" a falling edge occurring *before* I attached the interrupt to the pin but after I declared the pin as an INPUT or an INPUT_PULLUP (or maybe because if it, going from floating to input pullup?), and acts on that "original falling edge" before I provide the intended falling edge
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum