Hello. We are creating a program for LPC4370 that collects samples from HSADC in the RAM buffer using DMA. The program uses the HSADC threshold functionality, which, when triggered, calls the ADCHS_IRQHandler interrupt handler. This ISR handler is located in RAM to speed up processing. Immediately at start, the handler saves the current position in the memory at which the recording from DMA is going.
The problem is that the delay between the triggering of the HSADC threshold and the call of the interrupt handler is about 1.5 μs, which is quite a lot at a sample frequency of 80 MHz. Tell us, please, what is the reason for such a big delay and how to fix it?
Solved! Go to Solution.
Hello. We inform that we solved the problem by moving the ISR vector table to RAM. Thanks to everyone who tried to help.
Hello. We inform that we solved the problem by moving the ISR vector table to RAM. Thanks to everyone who tried to help.
Hi, Vitaliy,
I do not think any debugger tools can provide the function to calculate the time from the instant that interrupt is triggered to the instant that the first instruction is executed in ISR, because we can not capture the instant that interrupt is triggered from processor itself.
BR
Xiangjun Rong
Hi, xiangjun.rong
And what preparatory operations does the processor carry out from the instance the interrupt is triggered until the interrupt handler is called?
Hi, Vitaliy,
I think the phenomenon is strange, maybe the root cause is complicated, this is my guess, I do not make sure it is correct.
I checked your ADC ISR
__RAM_FUNC void ADCHS_IRQHandler(void) { /* Toggle debug pin */ LPC_GPIO_PORT->B[3][7] = 1; LPC_GPIO_PORT->B[3][7] = 0; /* Get threshold interrupt status on group 1 */ uint32_t status = Chip_HSADC_GetIntStatus(LPC_ADCHS, 1) & Chip_HSADC_GetEnabledInts(LPC_ADCHS, 1); /* Clear threshold interrupts statuses */ Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, status); }
You use the status variable, and theADCHS_IRQHandler(void)
code is located at RAM, pls check if thestatus variable,ADCHS_IRQHandler(void) code location and DMA destination address where you save the ADC samples are located at the same RAM block, if it is, there is issue, pls allocate them to different RAM blocks so that DMA and core can work in parallel. Hope it can help you BR Xiangjun Rong
Hi, xiangjun.rong
Thank you for your offer. We moved the DMA destination buffer to RAM2, and left the ADCHS_IRQHandler in RAM alias. Also, the status stack variable has been made global in RAM. However, this did not bring any result.
Tell us, please, is it possible to perform debugging, or at least see the assembler code from the moment the interrupt from the HSADC is generated and until the ADCHS_IRQHandler function is called to understand how many CPU clock cycles are required for this path?
Hi, Vitaliy,
I read your description carefully, but I do not know the timing of the delay. Can you draw a timing diagram and clarify what the synchronization is, what the delay is, for example delay is from an instant to another instant.
BR
XiangJun Rong
Hi, xiangjun.rong
Thanks for your reply. By synchronization, I mean a trigger on the edge of the signal, as in an oscilloscope (see attached picture). I call it synchronization so that there is no confusion with the start trigger of HSADC.
/* Set low A threshold to 50% and high A threshold to 50% */
#define TRIGGER_LEVEL_DEF (HSADC_MAX_SAMPLEVAL / 2)
Chip_HSADC_SetThrLowValue(LPC_ADCHS, 0, TRIGGER_LEVEL_DEF);
Chip_HSADC_SetThrHighValue(LPC_ADCHS, 0, TRIGGER_LEVEL_DEF);
/* Setup HSADC threshold interrupts on group 1 */
/* Input 0 upward threshold crossing detect */
Chip_HSADC_EnableInts(LPC_ADCHS, 1, (HSADC_INT1_THCMP_UCROSS(0)));
__RAM_FUNC void ADCHS_IRQHandler(void)
{
/* Toggle debug pin */
LPC_GPIO_PORT->B[3][7] = 1;
LPC_GPIO_PORT->B[3][7] = 0;
/* Get threshold interrupt status on group 1 */
uint32_t status = Chip_HSADC_GetIntStatus(LPC_ADCHS, 1) & Chip_HSADC_GetEnabledInts(LPC_ADCHS, 1);
/* Clear threshold interrupts statuses */
Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, status);
}
We connected the first channel (yellow beam) of the external oscilloscope to the input of the HSADC, and the second channel (blue beam) to the debug output of the microcontroller. You can see in the figure below a delay of about 1.5 μs between the crossing of the threshold level of the HSADC and the triggering of the interrupt.
P.S. During the check, we noticed that when we turn on code optimization (O3), the delay decreases to 250 ns (see the picture below), but this is also a lot and the code works with errors.
Hi, Vitaliy Livnov ,
As Andrea Bettati pointed out that it took 12 clock cycles to execute the first instruction in ISR after interrupt is triggered.
But assume that the LPC4357 run in 200MHz, executing 12 clock cycles takes about 0.1uS, but you said the delay is 1.5uS, it is too ling. If you do nothing in the ADC ISR but toggling a GPIO, then check the ADC triggering signal and the GPIO toggling signal, what is the result?
BR
XiangJun Rong
Hello to all.
We tested the LabTool software and also got a threshold interrupt delay of
about 1 μs. Does this mean that this is a LPC4370 hardware problem?
Hi, a_bet, xiangjun.rong
Thanks for yor answers. I apologize for forgetting to attach a screenshot, I attach it to the post above.
Also, I apparently incorrectly described the principle of our software. This is not an interrupt from the trigger that triggers the HSADC, but an interrupt that fires when the signal crosses the threshold level (THCMP_UCROSS0). I fixed this in the description of the question. We do not stop the HSADC before the synchronization is triggered or immediately after the synchronization, but only modify the DMA LLI descriptors in the HSADC threshold ISR handler. That is, our software is an oscilloscope functional with synchronization on the leading edge of the signal. And as you can see from the screenshot above, the synchronization is delayed by about 120 samples at an ADC frequency of 80 MHz.
Hi,
I'm doing something similar in my application and I think there is no way to get rid of this. The IRQ call is 12 clk cycles so you'll always have some sort of delay unfortunately.
How do you measure the delay time?
Hello, Andrea. Thanks for your reply.
We use a synchronization functionality similar to that implemented in LabTool. When ISR is triggered, the current DMA record address is stored, after which a certain number of HSADC samples are recorded and then the data is transferred to the PC. In the screenshot you can see that the interrupt triggered at position 0 on the x axis, and the HSADC trigger fired 120 samples earlier. This is about 1.5 μs of delay.
The second measurement method is to switch one of the GPIO pins immediately after the interrupt is triggered and measure the delay time using an oscilloscope. In this case, we got similar results.
Tell us, how did you manage to get a delay of 12 clk cycles?
I'm afraid you forgot to attach the image but don't worry I understood.
My application samples continuously so it's a bit different, but I never actually measured the time.
I wrote that because I learned it on this book.
It's strange that you get so much delay. Maybe it could be related with the ADC wakeup time?