This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I am interested in the context switching time of the TMS570 if an IRQ is triggered.
Kind regards,
C.W.
Hello C.W.,
We have received your post. Let me just ask a point for clarification, are you looking for the time from external interrupt triggered to the time that an ISR is entered (return address push to stack assumed)? Or are you looking or something more than that (return with POP)? We can assume that you are not concerned about RTOS or application context saving, correct?
As far as I understand if an external interrupt has been triggered, all registers have to be stored as well as return address. And this will consume CPU cycles. I am interested in the number of these CPU cycles. Kind regards,
C.W.
C.W.
The CPU can handle 2 kind of interrupts. IRQ and FIQ.
All peripheral module able to generate interrupt request are able via the VIM module to generate IRQ or FIQ.
Using IRQ type exception, the IRQ_Handler will have to store in the stack only the register used in the IRQ_Handler.
Our compiler is taking care of that.
In opposition, the FIQ type exception has a dedicated set of CPU register (R8-R14). Our compiler will take advantage of these banked register so there is no need to save them in the stack.
Please let me know if I've answered your question.
No this does not answer my question.
As the headline mentioned, I am interested in the time which is needed to make a context switch from normal operation to interrupt routine.
Kind regards,
C.W.
C.W.
The following information assumes the CPU is using Hardware vector mode. The VIM module will provide the address of the Interrupt handler directly to the CPU.
CPU running at 180Mhz (HCLK) Peripheral module running at 90Mhz (VCLK)
From Interrupt request at the peripheral module boundary to CPU fetching the first instruction of corresponding interrupt handler: 105.56ns (19 HCLK cycles)
In case of external interrupt (using GIO module) there is an additional 2 VCLK (4 HCLK) cycles to synchronize the interrupt. The total time/cycle will be: 127.7ns (23 HCLK cycles)
Jaen - Marc,
I guess you meant nanoseconds and not microseconds. In what document can we find these numbers for the latency?
I made a simple test for an RM48 (HCLK = 200 MHz) to measure the latency between an external signal and the interrupt service code. I put the external signal at GIOA0, which triggered an IRQ on falling edge. Inside the interrupt service routine "gioLowLevelInterrupt" I just toggled GIOA1 (gioToggleBit(gioPORTA,1)). With an oscilloscope I could measure the time between GIOA0 and GIOA1. The measured time difference is 820ns, which would correspond to 820ns/5ns = 164 clock cycles.
Do you have an idea, where this difference between your numbers (23) and the measured delay (164) can be caused?
Regards
Frank
Frank,
Thank you for catching the ns/us in my reply. I've fixed this mistake.
Concerning your question, the measurement (23 cycles) is from an internal request (RTI in this case) to the entry point of the ISR.
In your case, the interrupt is GIO. Using Halcogen, the ISR is:
void gioLowLevelInterrupt(void) // This is the point I'm doing the measurement.
{
sint32 offset = gioREG->OFF2 - 1U;
/* USER CODE BEGIN (17) */
/* USER CODE END */
if (offset >= 8)
{
gioNotification_low(gioPORTB, offset - 8U);
}
else
{
gioNotification_low(gioPORTA, offset);
}
/* USER CODE BEGIN (18) */
/* USER CODE END */
}
This ISR will call:
#pragma WEAK(gioNotification_low)
void gioNotification_low(gioPORT_t *port, sint32 bit)
{
/* enter user code between the USER CODE BEGIN and USER CODE END. */
/* USER CODE BEGIN (21) */
/* enter user code and remove the while loop... */
gioSetBit(gioPORTA,bit,0); // Generate a falling edge on GIO_A7
/* USER CODE END */
}
The notification routine will call:
void gioSetBit(gioPORT_t *port, uint32 bit, uint32 value)
{
/* USER CODE BEGIN (5) */
/* USER CODE END */
if (value != 0U)
{
port->DSET = 1U << bit; // It's after this write that you are doing your measurement.
}
else
{
port->DCLR = 1U << bit;
}
}
So the time (cycles) you are measuring is totally different.
Jean - Marc,
As mentioned in my first post, I placed the toggle - instruction for GIOA1 directly at the beginning of gioLowLevelInterrupt(), just after the USER CODE BEGIN(17) - line, so the difference between our two test setups is quite small.
The only differency is my call of function gioToggle, but this cannot be accounted for the difference 23 Cycles to 164 Cycles.
Regards
Frank
Sorry to pop this topic up again,
but I need a solution.
In what document (TRM, data sheet) can I find clock numbers about the Interrupt Timing Response of the RM4x?
Regards
Frank
Frank,
I'm working on a simulation to answer your question.
I will need couple of days.
Thanks for your understanding.
Frank,
I did a similar test and here are my results.
The first instruction in the gioLowLevelInterrupt is a call to the gioSetBit function used to clear the gio pin.
The GIO pin is set in the main function. This creates the interrupt and in the ISR I clear this pin immediately.
The following screen shoot is a view of the code. In this example I didn't optimize the code.
Also, in Halcogen I specified to enable the VFP (Floating Point Unit)
As you can see in the dis-assembly window, because the VFP is enabled, the compiler generates code to save some of the VFP registers in the stack. If your application doesn’t use the VFP, you have to disable it in HalCogen. Remember in this case to use the correct library to link your code. (Library without VFP support)
Even if gioSetBit is a small routine, without optimization, the compiler generates a call to this function.
The run time measure on the scope is 610ns. In my case, I'm running at 160Mhz (6.25ns) for HCLK and 80Mhz for VCLK.
At that speed, the Flash is configured with 3 Data Wait States and 1 Address Wait State.
The corresponding cycle count is ~98 cycles.
Here is the same test, with the following optimization and the VFP disable.
-O4 --opt_for_speed=5
As you can see in the dis-assembly window, there is no more context saving for the VFP, and the gioSetBit is now in-lined.
In this configuration, the total time is now 400ns (64 cycles)
As said in previous post, from the GIO request (on the GIO boundary) to the CPU fetching the first instruction of the ISR, we have 23 cycles. These 23 cycles are part of the total 64 cycles.
As final test, I configured the PLL to 48Mhz (20.83ns) for HCLK and VCLK.
In this configuration, the Flash can run at 0 data waitstate and 0 address waitstate.
Using the code with optimization, the run time is now 1.16us (56 Cycles)
The cycle count from GIO request to CPU fetching the first instruction is now 21 cycles (HCLK=VCLK)
During my experiments, I forgot at first to set the VIM module in “IRQ Handling via VIC Controller). This is a setup available in HalCogen/R4-MPU-PMU tab. By default this option is disabled.
We are planning to include the timing from Module Interrupt request to CPU entering the ISR. This time is code independent.
I hope these details will help your understanding.
Frank, C.W.
If your question has been answered, please can you mark my reply as verified so we can close this thread.
Thank you.
Jean-Marc,
because I did not start this thread, I don't have a button "verify". Anyway, thanks for your additional tests, which gave some additional hints to the interrupt latency. It would be very useful, if you could add some of the results to the Hercules documents.
Regards
Frank