Outils pour utilisateurs

Outils du site


Action disabled: diff
tns_nucleo_prof

Ceci est une ancienne révision du document !


Outils de développement en ligne: https://developer.mbed.org/compiler/#nav:/Nucleo_blink_led/main.cpp;

https://developer.mbed.org/teams/ST-Americas-mbed-Team/wiki/Preparing-the-STM32-Nucleo-Board

Présentation des broches de la carte

Utilisation console

Upgrade firmware de la carte

Le 23/03/2017 à 16:59, Hugues Gilliard a écrit

Jonathan Piat <jonathan.piat@iut-tlse3.fr> a écrit

J'ai finalement réussi à comprendre ce qui pouvait déconner pour la génération du sinus (en plus du problème de sin dans libmath. J'ai un résultat plutot inatendu pour le bout de code suivant :

#define SAMPLING_RATE  ( 48000.0f)
#define SIN_FREQ  ( 480.0f)
 ...
if (t >= SAMPLING_RATE/SIN_FREQ)
   t = 0;

donne l'assembleur suivant :

  .loc 1 102 0
  fmsr    s14, r3    @ int    @ D.8604, D.8604
  fsitos    s14, s14    @ D.8606, D.8604
  .loc 1 109 0
  mov    r0, #1207959552    @,
  .loc 1 102 0
  fcmpes    s14, s15    @ D.8606, tmp128
  fmstat
  .loc 1 103 0$

le code assemblé fait :

  1. charge SAMPLING_RATE/SIN_FREQ (pré-calculé) dans un registre floating point
  2. convertit “t” de integer vers floating point et le charge dans un registre floating point
  3. fait la comparaison floating point des deux valeurs
  4. transfert le flag résultat de l'unité floating point vers le flag du processeur pour la prise de décision

En utilisant SAMPLING_RATE et SIN_FREQ en unsigned int, la comparaison prend une instruction. J'ai d'abord cru qu'il y avait un problème de division non précalculé, et j'ai donc casté les opérandes SAMPLING_RATE et SIN_FREQ en (const) ce qui avait réglé le problème … mais j'ai fini par réaliser que (const) = (const int) et que donc que le résultat de la division est un entier.

Donc l'utilisation de la FPU n'est pas gratuit du tout car elle utilise des registres spécifiques et non les registres processeurs ce qui implique des transferts depuis/vers la FPU. L'assembleur du code FIR le montre bien :

vfma.f32    s15, s14, s12    @ output_val, tmp176, tmp177
add    r4, r2, r3, lsl #2    @, tmp181, tmp161, tmp178,
subs    r3, r3, #1    @ read_index, tmp178,
flds    s14, [r4]    @ tmp182, signal_samples

le produit accumulation est fait en une instruction (visiblement trois cycles), mais il faut ajouter le chargement de de l'échantillon k-1 avec flds. Après optimisation, la boucle du FIR est déroulée sur 8 itérations, ce qui permet de faire le chargement de 8 coéfficients, de faire 8 itérations de la boucle et de recommencer. Initialement, j'accédais au résultat du FIR par un pointeur (variable retour du FIR passée en argument) et en fait ça fout la grosse merde. Lorsque on utilise un pointeur sur le résultat, ça implique pour chaque itération de déréférencer le pointeur, copier le contenu dans un registre processeur, copier vers un registre FPU, calculer le MAC, recopier vers un registre CPU pour pouvoir stocker la valeur résultat au travers du pointeur.

Du coup je vais retester demain le temps de clacul, mais au vu de l'ASM, ça devrait dépoter.

Autre truc sympa pour l'optimisation du FIR en fixed point :

https://www.arm.com/files/pdf/DSPConceptsM4Presentation.pdf

tns_nucleo_prof.1490909107.txt.gz · Dernière modification : 2017/03/30 23:25 de bvandepo