Estoy trabajando en una aplicación de audio en el Núcleo F411RE y me he dado cuenta de que mi tratamiento fue demasiado lento, haciendo que la aplicación omitir algunas muestras.
Buscando a mi desmontaje pensé que dado el número de instrucciones y el 100 MHz de reloj de CPU (que me he fijado en STM32CubeMx), que debería ser mucho más rápido.
He comprobado SYSCLK valor y es de 100Mhz como se esperaba. Para estar 100% seguro de que poner 1000 "nop" en mi bucle principal y mide 10 µs, lo que corresponde a un 100 MHz de reloj.
He medido exactamente el tiempo tomado por mi de procesamiento y toma de 14,5 µs es decir 1450 ciclos de reloj. Creo que es demasiado, teniendo en cuenta que el proceso es bastante simple :
for(i=0; i<12; i++)
{
el1.mode[i].phase += el1.osc[i].phaseInc; // 16 µs
if(el1.osc[i].phase >= 1.0) // 20 µs (for the whole "if"
el1.osc[i].phase -= 1.0;
el1.osc[i].value = sine[ (int16_t)(el1.osc[i].phase * RES) ]; // 96 µs
el1.val += el1.osc[i].value * el1.osc[i].amp; // 28 µs
} // that's a total of 1.63 µs for the whole loop
donde la fase y phaseInc son de precisión simple carrozas, y el valor es un int16_t, sine[] es una tabla de consulta que contiene 1024 int16_t.
No debería ser más que un deseo de 500 ciclos, derecho? Me miré en el desmontaje, se hace uso de la las instrucciones de punto flotante... Por ejemplo, el último de la línea de desmontaje es : vfma.f32 => 3 ciclos vcvt.s32.f32 => 1 ciclo vstr => 2 ciclos ldrh.w => 2 ciclos
(ciclos de tiempo de acuerdo a este ), con Lo que un total de 8 instrucción de esa línea, que es el "más grande". Yo realmente no se por qué es tan lento... tal vez porque estoy usando estructuras o algo?
Si alguien tiene alguna idea, me encantaría escucharlo.
EDIT : acabo de medir el tiempo, línea por línea, usted puede ver en el código anterior. Parece que la mayor parte del tiempo consumming línea es la tabla de la línea, lo que significa que es tiempo de acceso a memoria que es crítico? ¿cómo podría mejorar?
EDIT2: desmontaje, según lo solicitado por BruceAbott (lo siento, es un poco desordenado, probablemente debido a la forma en que fue optimizado por el compilador):
membrane1.mode[i].phase += membrane1.mode[i].phaseInc;
0800192e: vldr s14, [r5, #12]
08001932: vldr s15, [r5, #8]
08001936: vadd.f32 s15, s15, s14
0800193a: adds r5, #24
179 if(membrane1.mode[i].phase >= 1.0)
0800193c: vcmpe.f32 s15, s16
08001940: vmrs APSR_nzcv, fpscr
180 membrane1.mode[i].phase -= 1.0;
08001944: itt ge
08001946: vmovge.f32 s14, #112 ; 0x70
0800194a: vsubge.f32 s15, s15, s14
0800194e: vstr s15, [r5, #-16]
182 membrane1.mode[i].value = sine[(int16_t)(membrane1.mode[i].phase * RES)];
08001952: ldr.w r0, [r5, #-16]
08001956: bl 0x80004bc <__extendsfdf2>
0800195a: ldr r3, [pc, #112] ; (0x80019cc <main+428>)
0800195c: movs r2, #0
0800195e: bl 0x8000564 <__muldf3>
08001962: bl 0x8000988 <__fixdfsi>
08001966: ldr r3, [pc, #104] ; (0x80019d0 <main+432>)
184 membrane1.val += membrane1.mode[i].value * membrane1.mode[i].amp;
08001968: vldr s13, [r5, #-4]
182 membrane1.mode[i].value = sine[(int16_t)(membrane1.mode[i].phase * RES)];
0800196c: sxth r0, r0
0800196e: ldrh.w r3, [r3, r0, lsl #1]
08001972: strh.w r3, [r5, #-8]
184 membrane1.val += membrane1.mode[i].value * membrane1.mode[i].amp;
08001976: sxth r3, r3
08001978: vmov s15, r3
0800197c: sxth r3, r4
0800197e: vcvt.f32.s32 s14, s15
08001982: vmov s15, r3
08001986: vcvt.f32.s32 s15, s15
174 for(i=0; i<12; i++) // VADD.F32 : 1 cycle
0800198a: cmp r5, r6
184 membrane1.val += membrane1.mode[i].value * membrane1.mode[i].amp;
0800198c: vfma.f32 s15, s14, s13
08001990: vcvt.s32.f32 s15, s15
08001994: vstr s15, [sp, #4]
08001998: ldrh.w r4, [sp, #4]
0800199c: bne.n 0x800192e <main+270>