A bit of a STM32F429/Cortex-M4/Ada Runtime question, I am attempting to measure how long (in clock cycles) some procedure takes when running on the mentioned board by directly using the SysTick timer registers and am faced with a couple of issues.
More specifically, I am using the following procedure to capture the total cycles:
function Measure_Proc_Cycles(Iterations: Natural;
Overflow: out Boolean) return Natural is
Start_Time: Natural := 0;
Stop_Time: Natural := 0;
begin
STCSR_Reg.Enable := Off;
STRVR_Reg.Value := 16#FFFFFF# - 1; -- set reload value to the maximum possible
STCVR_Reg.Value := 0; -- set current value to zero (also clears the STCSR_Reg.Count_Flag)
STCSR_Reg.Clk_Source := On; -- use processor clock (i.e. not an external reference one)
STCSR_Reg.Enable := On; -- turn timer on
STCSR_Reg.TickInt := Off; -- don't generate any SysTick interrupts
loop
exit when STCSR_Reg.Count_Flag = On;
end loop;
Start_Time := Natural(STCVR_Reg.Value);
-- Start timer
STCSR_Reg.Enable := On;
Burn_Cycles(Iterations);
-- Stop timer
STCSR_Reg.Enable := Off;
if STCSR_Reg.Count_Flag = On then
Overflow := True;
end if;
Stop_Time := Natural(STCVR_Reg.Value);
-- SysTick is a decrement counter so Start_Time > Stop_Time
return Start_Time - Stop_Time;
end Measure_Proc_Cycles;
with Burn_Cycles
merely being:
procedure Burn_Cycles(Iterations: Natural) is
Acc: Natural := 1;
begin
for I in 1 .. Iterations loop
Acc := Acc + 1;
end loop;
end Burn_Cycles;
(with all SysTick registers appropriately mapped)
Firstly, my gut instinct tells me this is a bad idea as changing the SysTick Reload Value might interfere with the runtime and completely invalidate any timing assumptions made by it. Or would that only be relevant if there were any delay statements involved? Or would that also maybe interfere with the environment task which is running the code under test? I do however get a larger value every time I increase the number of iterations in Burn_Cycles
.
The second issue I’m having is that if a subprogram takes more than 2**24 cycles to run (the SysTick reload value register is 24 bits and includes zero in the counting) then the only way to count its time is by enabling the triggering of the SysTick interrupt every time the counter counts down and then incrementing a counter in the handler (so, effectively the total running time is Counter_Value*(2**24) + cycles measured in the last counting). However, registering a handler for the SysTick interrupt traps instantly when the application starts with gdb reporting:
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0800a782 in system.semihosting.put()
Is that because a handler is already registered for SysTick? (I believe the logic for this is in s-bbcppr.adb
?)
However, registering a handler for an MCU-specific interrupt works fine. To prove that, I mapped the NVIC registers and then software-triggered the first non-Cortex interrupt (which based on the handler.s
file corresponds to WWDG_Interrupt
in the a-intnam.ads
file) and had the handler increase a counter which I then printed in gdb.
Any input would be appreciated. - Thank you.
(In case that makes any difference, I’m using the runtime that comes under the 2021-arm-elf directory of the GNAT installation)