This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to count cycles on ARM cortex m0+?

Hi

I'm new to to ARM and am working on FRDM25Z board. I would like to calculate the timing for a simple blinking program using Kinetis Studio, but my calculations does not fit my oscilloscope output.

Here is my c program:

#include "MKL25Z4.h"

static int i = 0;

int main(void)

{

SIM_SCGC5 |=0x400; //enable clock to port B

PORTB_PCR19 = 0x100; //Make PTB19 as GPIO

GPIOB_PDDR|=0x80000; //Make BTB19 as output pin

while(1)

{

  GPIOB_PDOR &= ~0x80000; //turn green led on

  GPIOB_PDOR |= 0x80000;

}

This compiles to:

int main(void)

{

51c: b580       push {r7, lr}

51e: af00       add r7, sp, #0

C:\Users\baldurtho\workspace.kds\TestProject_005\Debug/../Sources/main.c:57

//PORT B Data direction register

#define GPIOB_PDDR (*(volatile unsigned int*)0x400FF054)

//PortB Data output register

#define GPIOB_PDOR (*((volatile unsigned int*)0x400FF040))

*/

SIM_SCGC5 |=0x400; //enable clock to port B

520: 4a10       ldr r2, [pc, #64] ; (564 <main+0x48>)

522: 4910       ldr r1, [pc, #64] ; (564 <main+0x48>)

524: 4b10       ldr r3, [pc, #64] ; (568 <main+0x4c>)

526: 58cb       ldr r3, [r1, r3]

528: 2180       movs r1, #128 ; 0x80

52a: 00c9       lsls r1, r1, #3

52c: 4319       orrs r1, r3

52e: 4b0e       ldr r3, [pc, #56] ; (568 <main+0x4c>)

530: 50d1       str r1, [r2, r3]

C:\Users\baldurtho\workspace.kds\TestProject_005\Debug/../Sources/main.c:58

PORTB_PCR19 = 0x100; //Make PTB19 as GPIO

532: 4b0e       ldr r3, [pc, #56] ; (56c <main+0x50>)

534: 2280       movs r2, #128 ; 0x80

536: 0052       lsls r2, r2, #1

538: 64da       str r2, [r3, #76] ; 0x4c

C:\Users\baldurtho\workspace.kds\TestProject_005\Debug/../Sources/main.c:59

GPIOB_PDDR|=0x80000; //Make BTB19 as output pin

53a: 4b0d       ldr r3, [pc, #52] ; (570 <main+0x54>)

53c: 4a0c       ldr r2, [pc, #48] ; (570 <main+0x54>)

53e: 6952       ldr r2, [r2, #20]

540: 2180       movs r1, #128 ; 0x80

542: 0309       lsls r1, r1, #12

544: 430a       orrs r2, r1

546: 615a       str r2, [r3, #20]

C:\Users\baldurtho\workspace.kds\TestProject_005\Debug/../Sources/main.c:62 (discriminator 1)

while(1)

{

GPIOB_PDOR &= ~0x80000; //turn green led on

548: 4b09       ldr r3, [pc, #36] ; (570 <main+0x54>) <baldur: 2 cycles>

54a: 4a09       ldr r2, [pc, #36] ; (570 <main+0x54>) <baldur: 2 cycles>

54c: 6811       ldr r1, [r2, #0]                                      <baldur: 2 cycles>

54e: 4a09       ldr r2, [pc, #36] ; (574 <main+0x58>) <baldur: 2 cycles>

550: 400a       ands r2, r1                                         <baldur: 1 cycle>

552: 601a       str r2, [r3, #0]                                     <baldur: 2 cycles>

C:\Users\baldurtho\workspace.kds\TestProject_005\Debug/../Sources/main.c:64 (discriminator 1)

//Delay_ms(500);

GPIOB_PDOR |= 0x80000;

554: 4b06       ldr r3, [pc, #24] ; (570 <main+0x54>)  <baldur: 2 cycles>

556: 4a06       ldr r2, [pc, #24] ; (570 <main+0x54>)   <baldur: 2 cycles>

558: 6812       ldr r2, [r2, #0]                                        <baldur: 2 cycles>

55a: 2180       movs r1, #128 ; 0x80                           <baldur: 1 cycle>

55c: 0309       lsls r1, r1, #12                                       <baldur: 1 cycle>

55e: 430a       orrs r2, r1                                            <baldur: 1 cycle>

560: 601a       str r2, [r3, #0]                                       <baldur: 2 cycles>

C:\Users\baldurtho\workspace.kds\TestProject_005\Debug/../Sources/main.c:66 (discriminator 1)

//Delay_ms(500);

}

562: e7f1       b.n 548 <main+0x2c>                             <baldur: 1/3 cycles>

564: 40047000 .word 0x40047000

568: 00001038 .word 0x00001038

56c: 4004a000 .word 0x4004a000

570: 400ff040 .word 0x400ff040 (address of portB on APB bus)

574: fff7ffff .word 0xfff7ffff (=~0x80000)

I have difficulties finding in the startup code what clock frequency I have. I checked by adding 10 "nop" commands.

(this was another strange thing: I found on the net that to dot "nop" I could do: __asm("mov r0,r0");, in C.

Strangely enough this was compiled to adds r0, r0, #0 !!!)

I got 477ns delay so each clock cycle is 4.77ns

( I made one project with processor expert (where I can read the clock on the processor component) and found that by default the clock is 32768x640=20.97MHz and this confirms my clock)

Here comes my problem: when I look at the signal on the scope it is 717 ns high and 618ns low. This would mean 717/47.7=15 clock cycles high and 618/47.7=13 clock cycles low.

But if I count (see above in <> brackets), and I expect the pin to flip on addresses 552 and 560 (the str command) I get 11 cycles low (missing 2 counts) and 14 counts high (assuming 3 clock cycle for branch back) (missing 1 count).

I have read that the pipeline for m0+ is two long so branching might explain the one missing on high side but what explains the two missing on the low side?

I would be happy for any comment, best regards,

Baldur

Parents
  • Hello baldurtho,

    the LED cannot be toggled in CPU cycle.

    If you insert wait such as

    for(i=0;i<0x500000;i++);

    after every PORT access,

    you can see the blinking of the LED.

    If your intention is to measure CPU cycle, you had better use SysTick timer.

    Best regards,

    Yasuhiko Koumoto.

Reply
  • Hello baldurtho,

    the LED cannot be toggled in CPU cycle.

    If you insert wait such as

    for(i=0;i<0x500000;i++);

    after every PORT access,

    you can see the blinking of the LED.

    If your intention is to measure CPU cycle, you had better use SysTick timer.

    Best regards,

    Yasuhiko Koumoto.

Children