flyboy74 wrote: Tue May 05, 2020 11:42 pm
...
If anyone out there knows assembler I would be interested to know how many machine instructions my interrupter handler uses. I am using a STM32F407 so it is a 32bit RISC running at 168MHz so that is just under 6ns per instruction.
I have not yet looked at your latest version.
This was one attempt I made to figure out how much time is spent in the interrupt routine:

- neopixel1.jpg (66.04 KiB) Viewed 8929 times
The bottom trace there, and what it was triggered on, is the LED pulse line, showing a 500ns T0H pulse.
The middle trace is a GPIO line set high on entry to the timer interrupt routine, and set low on exit from the interrupt. OK, so adding code flip the GPIO will slow it down a bit, but actually, to compensate, I removed the updating of ARR, and also made the resetting of TIM_SR_UIF unconditional. So that indicates it is spending approx 400ns in there, but that does not include interrupt latency...
Finally the top trace show activity in the main while(1) loop, flipping another GPIO there. From that you can see that the mainline code goes out to lunch for just under 600ns when the interrupt occurs.
That was when compiled with GCC, "optimize for speed".
If that is anything to go by, for 400kHz LEDs, you would be using a bit under 24% of the CPU time, and it would be close to 48% for 800kHz LEDs. I'm wondering how this would go on a F103 - I'd guess it could handle 400kHz, but 800kHz could be a challenge.
FWIW it seems to execute around 35 instructions normally. This is up to the point where it is checking lastbit (in original version), which obviously only happens when it runs out of data.
Code: Select all
TIM4_IRQHandler:
08000cb0: ldr r3, [pc, #116] ; (0x8000d28 <TIM4_IRQHandler+120>)
08000cb2: ldr r2, [r3, #16]
08000cb4: lsls r2, r2, #31
08000cb6: bpl.n 0x8000cc0 <TIM4_IRQHandler+16>
109 TIM4->SR &= ~TIM_SR_UIF; // clear UIF flag
08000cb8: ldr r2, [r3, #16]
08000cba: bic.w r2, r2, #1
08000cbe: str r2, [r3, #16]
112 if(pos<sizeof(LED_data)){
08000cc0: ldr r1, [pc, #104] ; (0x8000d2c <TIM4_IRQHandler+124>)
08000cc2: ldrh r3, [r1, #0]
08000cc4: cmp r3, #179 ; 0xb3
08000cc6: bhi.n 0x8000cf8 <TIM4_IRQHandler+72>
107 void TIM4_IRQHandler(void){
08000cc8: push {r4, r5, r6}
113 if(LED_data[pos] & mask){
08000cca: ldr r0, [pc, #100] ; (0x8000d30 <TIM4_IRQHandler+128>)
08000ccc: ldr r4, [pc, #100] ; (0x8000d34 <TIM4_IRQHandler+132>)
08000cce: ldrb r2, [r0, #0]
08000cd0: ldrb r4, [r4, r3]
08000cd2: tst r2, r4
08000cd4: bne.n 0x8000d16 <TIM4_IRQHandler+102>
117 TIM4->CCR1 = low_CCR1;
08000cd6: ldr r5, [pc, #96] ; (0x8000d38 <TIM4_IRQHandler+136>)
08000cd8: ldr r4, [pc, #76] ; (0x8000d28 <TIM4_IRQHandler+120>)
08000cda: ldrh r6, [r5, #0]
118 TIM4->ARR = low_ARR;
08000cdc: ldr r5, [pc, #92] ; (0x8000d3c <TIM4_IRQHandler+140>)
117 TIM4->CCR1 = low_CCR1;
08000cde: str r6, [r4, #52] ; 0x34
118 TIM4->ARR = low_ARR;
08000ce0: ldrh r5, [r5, #0]
08000ce2: str r5, [r4, #44] ; 0x2c
120 if(mask==1){
08000ce4: cmp r2, #1
121 mask = 0B10000000;
08000ce6: itet eq
08000ce8: moveq r2, #128 ; 0x80
123 }else mask = mask >> 1;
08000cea: lsrs r2, r2, #1
122 pos+=1;
08000cec: adds r3, #1
123 }else mask = mask >> 1;
08000cee: strb r2, [r0, #0]
08000cf0: it eq
08000cf2: strheq r3, [r1, #0]
131 }
08000cf4: pop {r4, r5, r6}
08000cf6: bx lr
125 if(lastbit){
08000cf8: ldr r3, [pc, #68] ; (0x8000d40 <TIM4_IRQHandler+144>)
08000cfa: ldrb r2, [r3, #0]
08000cfc: cbz r2, 0x8000d10 <TIM4_IRQHandler+96>
126 TIM4->CCER &= ~TIM_CCER_CC1E; //disable output to pin so that it will be low.