Please note: We are aware of an issue affecting replies on the Arm Community forums, which may not be loading as expected.
We apologize for any inconvenience and appreciate your patience while we investigate and work to resolve the issue.
Thank you for your understanding.
Hello, I´m trying to implement a small assembly routine in a cortex M0+ in order to introduce a software controlled delay in microseconds. For performing this, i wrote this small while() routine:
So, knowing exactly what assembly instructions are executing, the clk clock frequency, and the number of clk cycles per instruction, I can calculate the CyclesToDelay value for a desired delay to introduce.Assembly:
__no_operation();0002 73F8 NOPCyclesToDelay--;0002 73FA LDR R1, [R0]0002 73FC SUBS R1, R1, #10002 73FE STR R1, [R0]while (CyclesToDelay > 0)0002 7400 LDR R1, [R0]0002 7402 CMP R1, #00002 7404 BNE 0x000273F8
Instruction clk cycles according https://developer.arm.com/documentation/ddi0432/c/programmers-model/instruction-set-summary are:
NOP 1 clk cycles
LDR 2 clk cycles
SUBS 1 clk cycles
STR 2 clk cycles
CMP 1 clk cycles
BNE 3 clk cycles
Total clk cycles in this routine = 12 clk cycles,CORE_CLK = 48mhzThen,1) 1 CORE_CLK cycle = 1 / 48 us2) 12 CORE_CLK cycles = 12/48 us ( The number of microseconds one loop of this routine should delay)Finally:3) CyclesToDelay * (12/48) = delay_we_want_to_introduce(us)
or CyclesToDelay = delay_we_want_to_inject(us) * 48 / 12However, measuring the delays obtained with this method does not seem to be very accurate. I dont know if this is going to be deterministic or if this is totally possible in this Cortex M0+. Feedback would be appreciated. Many thanks.
I was about to say that you might use the DWT CYCCNT register, as I have done for CM3 and CM4. Alas it appears to be missing from CM0/CM0plus.
For what it's worth, here's the code for CM3/4, it might help you in some way.
static void init(void); static uint32_t ticksPerMilli; /******************************** PUBLIC API *******************************/ void delayMillis( size_t ms ) { if( ticksPerMilli == 0 ) { init(); } // Reset the cycle counter and enable it, so it starts counting DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; while( DWT->CYCCNT < (ms * ticksPerMilli) ) ; } void delaySeconds( size_t s ) { delayMillis( s * 1000 ); } /***************************************************************************/ static void init(void) { // Bit mask definitions (*_Msk) are from core_cmN.h // To use DWT, you have to set the Trace Enable bit in DEMCR... CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; /* Trace DEMCR might not be writable from CPU (only debugger??). If that is true, the 'delay via cyccnt' can't be used on this MCU. */ if( !(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) ) assert(0); // CYCCNT might not be implemented. Assertion as above if( DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk ) assert(0); // SystemCoreClock is a CMSIS Core-managed variable ticksPerMilli = SystemCoreClock / 1000; }
Yes, it seems that this option its not avaliable on this MCU. Thanks anyway,, hehe