RA4M1 Interrupts

Continuing the discussion from RA4M1 Interrupts:

You might also be interested in @susan-parker 's similar investigations...

https://forum.arduino.cc/t/uno-r4-schematic/1160263/21

https://github.com/TriodeGirl/Arduino__UNO_R4_CTC_Clock_Frequency_Accuracy_Measurement_Circuit

https://forum.arduino.cc/t/uno-r4-attachinterrupt/1148214/25

2 Likes

Did you figure out a way to map more than 32 simultaneous peripheral interrupts to the NVIC at the same time? This is a really strange thing that Renesas has done, given that the CM4 architecture allows for 496 external interrupts. I was hoping that there was at least a way to say "map all of the USART interrupts to this NVIC vector", but I didn't see anything in my relatively brief reading of the datasheet.

(I also find the IRQManager to be unnecessarily complex. I would have thought that a constant mapping between the "core" interrupts and the NVIC would have been sufficient, with a simpler scheme to add additional interrupts from user requests.)

(questionable code on top of questionable hardware. And both without explanations as to "WHY??" Sigh. I applaud your willingness to delve into it!)

Just stumbled across this, and now I'm a bit confused.

I was under the impression that the whole point of the event link controller is to avoid generating CPU interrupts, and instead connecting actions on peripherals directly with interrupts from other peripherals, without having the CPU run any software code.

See The Event Link Controller – Automatically Manage Low Level System Tasks on RA MCUs

As such I assumed that using IELSR to generate user callbacks is sort of missing the point, but... A glance in the RA4M1 user manual shows that actually the interrupt vector table almost entirely consists of IELSR entries, like there aren't even any "classic" interrupts in the table for any peripheral. I would have expected to find at least one entry for each peripheral in there.

That means, as far as I understand, going through the event link stuff is indeed as you say the only way to attach an ISR to a peripheral... Which means that you can actually only have up to 32 peripheral events with an ISR at any given time

Something tells me I'm missing something here. I guess 32 is "enough". But it doesn't feel "comfortably enough" - keeping in mind that many peripherals have multiple events that need to be handled...

OK. I don't think Interrupt Link Controller is an official term though.
The only 2 results I get for that on google are both authored by you, one is your github page, and the other is some thread in this forum.
According to the RA4M1 manual, the thing that fires interrupts to the NVIC is the same thing that would also enable the DTC (if applicable and if supported for the respective event).
It's just that not all events can be linked to DTC or DMA (Table 13.4 in the manual).

Where did you find the info that those are 2 separate entities?

Hello

I'm reading and studying many pages where you talk about interruptions.

I've read; That although you can use the instructions attachinterrupt() 0 and 1 just like the arduino R3
But in the arduino R4 we have a lot of inputs that can be used as interruptions....

I'm in a project reading 3 inputs of the pulse counter, mounted in (A1, A2 and A3 used as digital inputs, which I don't know if they have anything to do with 17, 18 and 19) I can put them in other inputs (2, 8 and 13)

So far so good

Now I'm trying to transfer it to your code... and I'm sorry but as much as I read your instructions... I can't figure it out.

I'm reading the code and I don't know where to adapt it and I can't find other examples.

Can you help me?

Thank you very much

It has been a while since I looked at this, but I believe the UNO R4 supports
interrupts on several different pins. Although the documentation:
attachInterrupt() - Arduino Reference
Shows it for only pins 2 and 3...

However if you look at the advanced sections of the pin outs for the two R4 boards, for example the Minima:

You will see that there are several pins marked with Interrupts. I did quick and dirty arrows to the columns that show this. I am pretty sure that many of these pins that are marked
with these numbers can be used.... However, there are compilications,
That is you will notice I highlighted 3 of them, which all 3 of which are IRQ1. So there is
only one unique interrupt for these three pins, so probably only use one of them.

Also I don't remember if using any of these pins, might interfere with other things such as
PWM.

I believe the new API that @Delta_G mentioned in post15, is for other more generic
things like example Timer interrupts, or ...

But could easily be wrong.

Good luck

AFAIK - The attachInterrupt code: (Interrupt.cpp)
Uses the function: int ch = pin2IrqChannel(pinNumber);

Which uses the g_pin_cfg[] array which has the mapping of Arduino pin numbers
to BSP pin/port plus pointer to data about each pin...

extern "C" const PinMuxCfg_t g_pin_cfg[] = { 
  { BSP_IO_PORT_03_PIN_01,    P301   }, /* (0) D0  -------------------------  DIGITAL  */
  { BSP_IO_PORT_03_PIN_02,    P302   }, /* (1) D1  */
  { BSP_IO_PORT_01_PIN_05,    P105   }, /* (2) D2  */
  { BSP_IO_PORT_01_PIN_04,    P104   }, /* (3) D3~ */
  { BSP_IO_PORT_01_PIN_03,    P103   }, /* (4) D4  */
  { BSP_IO_PORT_01_PIN_02,    P102   }, /* (5) D5~ */
  { BSP_IO_PORT_01_PIN_06,    P106   }, /* (6) D6~ */
  { BSP_IO_PORT_01_PIN_07,    P107   }, /* (7) D7  */
  { BSP_IO_PORT_03_PIN_04,    P304   }, /* (8) D8  */
  { BSP_IO_PORT_03_PIN_03,    P303   }, /* (9) D9~  */

,,,

The \variants\MINIMA\pinmux.inc: file
So for pin2 it use P105, which has:

const uint16_t P105[] = {
PIN_PWM|CHANNEL_1|PWM_CHANNEL_A|GPT_ODD_CFG,
PIN_INTERRUPT|CHANNEL_0|LAST_ITEM_GUARD
};

Which maps the pin to Interrupt Channel 0...

Likewise if you look at D8, it has P304

const uint16_t P304[] = {
PIN_PWM|CHANNEL_7|PWM_CHANNEL_A|GPT_ODD_CFG,
PIN_INTERRUPT|CHANNEL_9|LAST_ITEM_GUARD
};

So it maps to Int 9...

Thanks for your quick reply:
As far as I've read attachInterrupt only works like in the Arduino R3 (0 and 1) just like in the Arduino R3.

Delta_G, I think you've done a great job. The problem I have when trying to use your libraries is that I don't understand how to use the codes to make the libraries work, so it's impossible for me to use an interrupt in the code.

If I generate the code for my project, I understand that we should copy:

#include "IRQManager.h"

volatile bool interruptFired = false; //The variables we need

GenericIrqCfg_t cfg; //We should copy this as is to generate the cfg

void setup() {

R_ICU->IRQCR[0] = 0xB0; // Configure some peripheral for an interrupt... I understand that IRQCR[0] corresponds to interrupt group 0 and 0xB0; .... Sorry, I don't know where it comes from

cfg.irq = FSP_INVALID_VECTOR; //It is copied as is
cfg.ipl = 12; // this is what you say is the sensitivity (for now, as is)
cfg.event = ELC_EVENT_ICU_IRQ0; // Does IRQ0 refer to interrupt group 0?

What if I want to add another 2 interrupts?

Sorry, in these lines, I don't understand what you are doing: (I don't know what variables you are moving)

R_PFS->PORT[1].PIN[5].PmnPFS = (1 << R_PFS_PORT_PIN_PmnPFS_PCR_Pos) | (1 << R_PFS_PORT_PIN_PmnPFS_ISEL_Pos);

void Myirq0_callback() {
R_ICU->IELSR[cfg.irq] &= ~(R_ICU_IELSR_IR_Msk);
interruptFired = true;
}

I hope that the explanations are not only useful to me, but also to anyone who tries to program interrupts.

My assumption, is they ignore the problem. Could easily be last one wins. Or first one wins, or it faults...

I know I should try it out, but my R4s are put away right now... Playing with GIGAs... My backup Giga arrived at my mailbox today... They have a pretty good Black Friday sale going on:
SHOP THE BEST DEALS! — Arduino Online Shop
Did not see GIGA on that list, but my eyes may have skipped over them
Arduino GIGA R1 WiFi — Arduino Online Shop

Hi everyone
I've been doing some tests.
I've tried using the Delta_G code... Sorry, you're way beyond my level.

I thought of trying a code based on attachInterrupt(). According to Arduino's instructions, it only works on inputs 2 and 3.
I've tried more inputs and surprise! All the inputs marked as interrupt work. (The ones KurtE indicated in the photo)

Here's a little code for you.


const int button1 = A1;
const int button2 = A2;
const int button3 = A3;
const int threshold = 200;
int cont = 0;
volatile int ISRcont = 0;
volatile int lastTime = 0;
void setup(){
  Serial.begin(9600);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  attachInterrupt(digitalPinToInterrupt(button1), counter, CHANGE);
   attachInterrupt(digitalPinToInterrupt(button2), counter, CHANGE);
    attachInterrupt(digitalPinToInterrupt(button3), counter, CHANGE);
 delay(100);
 
}
void loop(){
  if(cont != ISRcont){
    cont = ISRcont;
    Serial.print(digitalRead(A1));Serial.print(digitalRead(A2));Serial.print(digitalRead(A3));
    Serial.print (" ");
    Serial.println(cont);
  } 
  delay(10);
 // Serial.println( digitalPinToInterrupt(button));
}
void counter(){
  if((millis()-lastTime) > threshold){
    ISRcont++;
    lastTime = millis();
  }
}

In my case, I'm trying to see what happens on the 3 inputs of the pulse counter.
As you can see, it's A1, A2 and A3 and it seems to work. (I've tried with 2,8... and it also works. It doesn't work on 5, which is not interrupt)

For my part, it seems to be solved. Thank you very much for your help.

1 Like