Author Topic: ARM Cortex M0 cycle counting  (Read 2435 times)

0 Members and 1 Guest are viewing this topic.

Offline amwalesTopic starter

  • Regular Contributor
  • *
  • Posts: 135
  • Country: gb
ARM Cortex M0 cycle counting
« on: March 14, 2025, 11:25:32 am »
Hi, I would like to write a piece of code in ARM assembler and would like to count the cycles it take to execute.
When I was playing with PICs this was really straight forward as the built in simulator allowed you to inspect the cycle count, start stop the stop watch.
Is there something similar available to ARM?
I have written a small piece of code in assembler, I haven't assembled or run it yet but would appreciate some eyes.

Code: [Select]
; Assume 40021000 is base address of GPIO port
; and 0x14 is offset of ODR

  ldr r1,=40021000   ; load base address of GPIO port
  ldr r2,[sp],#4     ; pop logic to be written to GPIO port

;                                                    Cycle count

.START
  str r2,[r1, #0x14] ; output value to GPIO port     1
  ldr r2,[sp],#4     ; pop logic                     1
  ldr r0,[sp],#4     ; pop delay count               1
  b INNER1           ; branch into middle of delay   2
 
.LOOP1
  mov r0,r0          ; NOP                           1  1
  mov r0,r0          ; NOP                           1  1
  mov r0,r0          ; NOP                           1  1
  mov r0,r0          ; NOP                           1  1
.INNER1
  sub r0, r0, #1     ; decrement delay count         1  1
  mov r0,r0          ; NOP                           1  1
  cbnz r0, LOOP1     ; loop if count > 0             *  *  *1 no branch or 2 if branch
.END

;                                                    START->END always completes in
;                                                    multiples of 8 cycles

 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 12494
  • Country: us
    • Personal site
Re: ARM Cortex M0 cycle counting
« Reply #1 on: March 14, 2025, 01:44:03 pm »
The easiest way to count cycles is to use SysTick timer. It runs on the core clock. Read the count value at the beginning and at the end of the timed code. A simple math will tell you a number of cycles it took.

For Cortex-Mx devices emulating the core alone is not enough for timing, since it depends on the memories (flash may have wait states and caches) and other masters on the bus (DMA, for example). And typical CM systems are way more complicated than PICs to emulate accurately.

At the same time, assuming zero wait state memory and no other masters on the bus, you can calculate the timing, since instruction times are outlines in the core technical reference manual.
Alex
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17814
  • Country: fr
Re: ARM Cortex M0 cycle counting
« Reply #2 on: March 14, 2025, 01:55:27 pm »
The way that makes most sense on Cortex-M is to use CYCCNT, which is meant for exactly that. Bummer though, it's usually not availble on the M0, so yes, using a timer is probably your best bet.

If on a Cortex-M3/4 or higher, do use CYCCNT.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
 
The following users thanked this post: WillTurner

Offline amwalesTopic starter

  • Regular Contributor
  • *
  • Posts: 135
  • Country: gb
Re: ARM Cortex M0 cycle counting
« Reply #4 on: March 14, 2025, 02:52:01 pm »
Thanks bruce that looks very interesting.
Ok so I made some modifications after seeing my mistake pointed out by grok

Code: [Select]
; Assume 40021000 is base address of GPIO port
; and 0x14 is offset of ODR

  ldr r1,=40021000   ; load base address of GPIO port
  ldr r2,[sp],#4     ; pop logic to be written to GPIO port

;                                                    Cycle count

.START
  str r2,[r1, #0x14] ; output value to GPIO port     2
  ldr r2,[sp],#4     ; pop logic                     2
  ldr r0,[sp],#4     ; pop delay count               2
  b INNER1           ; branch into middle of delay   2
 
.LOOP1
  mov r0,r0          ; NOP                              1
  mov r0,r0          ; NOP                              1
  mov r0,r0          ; NOP                              1
  mov r0,r0          ; NOP                              1
  mov r0,r0          ; NOP                              1
  mov r0,r0          ; NOP                              1
  mov r0,r0          ; NOP                              1
.INNER1
  sub r0, r0, #1     ; decrement delay count         1  1
  cbnz r0, LOOP1     ; loop if count > 0             *  *  *1 no branch or 2 if branch
.END

;                                                    START->END always completes in
;                                                    multiples of 10 cycles

Grok seems to agree with my fixes and the final analysis that the it take 10N cycles where N is the delay count.
I will need to verify the results on hardware.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6464
  • Country: nz
Re: ARM Cortex M0 cycle counting
« Reply #5 on: March 14, 2025, 03:10:53 pm »
It's crazy what a fancy version of T9 can do now.
 

Offline jnk0le

  • Regular Contributor
  • *
  • Posts: 228
  • Country: pl
Re: ARM Cortex M0 cycle counting
« Reply #6 on: March 14, 2025, 06:19:22 pm »
Taken branches are 2 cycle on M0+, M0 is 3.

Also there is no cbnz instruction on armv6-m, and it doesn't go backwards.
 

Offline amwalesTopic starter

  • Regular Contributor
  • *
  • Posts: 135
  • Country: gb
Re: ARM Cortex M0 cycle counting
« Reply #7 on: March 14, 2025, 10:33:12 pm »
Thanks for the comment about cbnz being missing.
What do you mean when you say it doesn't go backwards?
 

Offline dave j

  • Regular Contributor
  • *
  • Posts: 172
  • Country: gb
Re: ARM Cortex M0 cycle counting
« Reply #8 on: March 15, 2025, 11:53:19 am »
Thanks for the comment about cbnz being missing.
What do you mean when you say it doesn't go backwards?
Unlike normal branch instructions, the compare and branch ones will only branch forwards (see here).

In your case you can use
Code: [Select]
subs r0, r0, #1
bne LOOP1
instead with the same performance.
I'm not David L Jones. Apparently I actually do have to point this out.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->