IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Embarqué Discussion :

Optimisation compilateur -> fonction non exécutée


Sujet :

Embarqué

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 21
    Points : 22
    Points
    22
    Par défaut Optimisation compilateur -> fonction non exécutée
    Bonjour tout le monde,

    Je réalise actuellement un programme sur un STM32L152RB à l'aide de l'IDE Keil. Ce programme fonctionne sous l'OS temps réel ChibiOS et une bonne partie de mon code fonctionne d'hors et déjà.
    Mon problème se présente lorsque je réalise un bout de code pour interragir avec un altimètre connecté sur une liaison I²C. Cette liaison servant déjà pour d'autres périphériques et fonctionnant pour l'initialisation de mon altimètre, je doute que le problème vienne de là. Mais lorsque je souhaite faire appel a des fonctions que j'ai réalisées me permettant d'aller recueuillir des données en passant par le bus I²C, celles-ci ne sont réellement exécutées que lorsque le niveau d'optimisation du compilateur est à 0. Lorsque celui-ci est au niveau 3, il ne tente même pas d'entrer dedans! J'ai bien regardé rapidement le code assembleur généré et en effet, l'appel de la fonction n'existe pas dans le code généré avec le plus haut degré d'optimisation (contrairement à celui généré pour le niveau 0). J'ai essayé de déclarer mes variables en static, en volatile, en globale... mais ça ne change rien... :/
    Donc, quelqu'un aurait-il une idée du "pourquoi" et pourrais m'expliquer ce qui pousse l'optimisation à supprimer ces bouts de code.
    Voici le code que j'utilise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    #include "alti.h"
    
    static long pressure0;
    long altitude = 0;
    long pressure = 0;
    static long_BMP085_reg g_long_registres;
    static PressureVar variables;
    
    // Cette fonction n'est pas exécutée
    long readUncompensatedTemperature()
    {
    		uint8_t txbuf[2] = {0};
    		uint8_t rawTemperature[2] = {0};
    		txbuf[0] = 0xF4; //Register address //Calibration data ac1
    		txbuf[1] = 0x2E; //Temperature
    		i2cAcquireBus(&I2CD1);
    		i2cMasterTransmitTimeout(&I2CD1, 0x77, txbuf, 2, NULL, 0, 1000);
    		i2cReleaseBus(&I2CD1);
    		chThdSleepMilliseconds(5);
    
    		txbuf[0] = 0xF6;
    		i2cAcquireBus(&I2CD1);
    		i2cMasterTransmitTimeout(&I2CD1, 0x77, txbuf, 1, rawTemperature, 2, 100);
    		i2cReleaseBus(&I2CD1);
    
    		return (((uint16_t)rawTemperature[0]<<8)|((uint16_t)rawTemperature[1]));
    }
    
    // Cette fonction n'est pas exécutée
    long readUncompensatedPressure()
    {
    		uint8_t txbuf[2] = {0};
    		uint8_t rawPressure[3] = {0};
    
    		txbuf[0] = 0xF4; //Registrer address //Calibration data ac1
    		txbuf[1] = 0x34+(OSS<<6); //Temperature
    		i2cAcquireBus(&I2CD1);	
    		i2cMasterTransmitTimeout(&I2CD1, 0x77, txbuf, 2, NULL, 0, 100);
    		i2cReleaseBus(&I2CD1);
    		chThdSleepMilliseconds(26);
    
    		txbuf[0] = 0xF6;
    		i2cAcquireBus(&I2CD1);
    		i2cMasterTransmitTimeout(&I2CD1, 0x77, txbuf, 1, rawPressure, 3, 100);
    		i2cReleaseBus(&I2CD1);
    
    		return (((long)rawPressure[0]<<16)|((long)rawPressure[1]<<8)|(long)rawPressure[2])>>(8-OSS);	
    }
    
    long calculateTemperature(/*PressureVar *variables,*/)
    {
    	static int uncompensatedTemperature = 0;
    	uncompensatedTemperature = readUncompensatedTemperature();    // cet appel n'est pas réalisé!
    	variables.X1 = (uncompensatedTemperature-g_long_registres.ac6)*g_long_registres.ac5>>15;
    	variables.X2 = (g_long_registres.mc<<11)/(variables.X1+g_long_registres.md);
    	variables.B5 = variables.X1+variables.X2;
    	return (variables.B5+8)>>4;
    }
    
     long calculatePressure(/*, PressureVar *variables*/)
    {
    	
    	static long uncompensatedPressure = 0;
    	//int temperature = 0;
    	static long pressure = 0;
    
    	uncompensatedPressure = readUncompensatedPressure();       // cet appel n'est pas réalisé!
    	calculateTemperature(/*variables,*/);
    
    	variables.B6 = variables.B5-4000;
    ...
    	variables.B7 = ((unsigned long)uncompensatedPressure-variables.B3)*(50000>>OSS);
    
    	if(variables.B7 < 0x80000000)
    	{
    		pressure = (variables.B7*2)/variables.B4;
    	}
    	else
    	{
    		pressure = (variables.B7/variables.B4)*2;
    	}
    	variables.X1 = (pressure/pow(2,8))*(pressure/pow(2,8));
    ...
    	return pressure;
    }
    
    void initAlti()
    {
    	uint8_t txbuf[10] = {0};
    	BMP085_reg registres;
    	//PressureVar variablesPression;
    
    	//récupération de ac1
    	txbuf[0] = 0xAA; //Calibration data ac1
    	i2cAcquireBus(&I2CD1);
    	i2cMasterTransmitTimeout(&I2CD1, 0x77, txbuf, 1, (uint8_t*)registres.ac1, 2, 1000);
    	i2cReleaseBus(&I2CD1);	
    	g_long_registres.ac1 = (short)((registres.ac1[0]<<8)+registres.ac1[1]);		
    
    ...
    	
    	pressure0 = calculatePressure(/*g_long_registres, &variablesPression*/);
    }
    
    long getAltitude()
    {
    	pressure = calculatePressure(/*g_long_registres, &variablesPression*/);
    	altitude = 44330.75*(1-pow((double)pressure/pressure0, 0.19029))*100;
    
    	return altitude;
    }
    Merci beaucoup!

  2. #2
    Membre expérimenté

    Homme Profil pro
    Responsable des études
    Inscrit en
    Mars 2009
    Messages
    553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable des études
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2009
    Messages : 553
    Points : 1 672
    Points
    1 672
    Par défaut
    Hello,
    Tout d'abord, de quel type d'optimisation s'agit-il? Une optimisation sur la vitesse d'exécution ou bien sur la taille du code ?
    Le fait que l'appel de fonction n'existe pas dans le code assembleur ne signifie pas nécessairement que ton code a été supprimé. Le compilateur a peut-être choisi de traiter cette fonction comme "inline".
    Ensuite, comment as-tu vérifié que cette fonction n'est pas réalisée? Grâce au débugger? Le débuggage de code optimisé donne des résultats très aléatoires, et peut donner l'impression que le code exécuté n'a aucun rapport avec le code écrit. Il vaut mieux ne pas s'y fier.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 21
    Points : 22
    Points
    22
    Par défaut
    Bonjour,

    Il s'agit d'une optimisation sur la vitesse d'exécution.
    Durant mes recherches, je suis tombé sur le mot clef "inline" en C. J'imagine que ça a un rapport avec ce que tu m'expliques, mais j'avoue ne pas avoir tout saisi à son propos. Y a-t'il un moyen de voir dans le code asm si ma fonction apparaît en inline?
    Et oui, j'ai bien vérifié avec le debugger. J'aimerais pouvoir dire que je suis sûr que mon problème vient bien de la non-exécution de ces 2 fonctions. Mais vu que je ne suis pas beaucoup plus sûr du reste du code, c'est compliqué à certifier!

    Merci de ton aide!

  4. #4
    Membre expérimenté

    Homme Profil pro
    Responsable des études
    Inscrit en
    Mars 2009
    Messages
    553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable des études
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2009
    Messages : 553
    Points : 1 672
    Points
    1 672
    Par défaut
    Hello,

    Dans le cas général: le compilateur va créer du code assembleur pour ta fonction. Puis, dans le reste de ton programme, chaque appel à cette fonction va se traduire par un saut (jump, branch, ...) qui déplace l'exécution du programme à l'endroit où se trouve le code assembleur de cette fonction. Lorsque la fin de la fonction est atteinte, l'exécution du programme saute à nouveau pour revenir au point de départ (l'instruction juste après le jump, en fait).

    Si la fonction est relativement courte, et sur certains processeurs, ton programme va passer plus de temps à effectuer ces sauts qu'à exécuter le code de la fonction appelée.

    Donc le compilateur peut décider, pour gagner en vitesse, de remplacer les appels à cette fonction par autant de copies du code de la fonction. Ton code assembleur ne contient plus d'instruction de saut vers cette fonction, mais pourtant son code existe et est exécuté. C'est ce qu'on appelle un fonction "inline".

    Pour savoir si ton code est effectivement appelé ou pas, je te recommande des méthodes plus empiriques: printf, allumer une led, ...

Discussions similaires

  1. Fonction non valide ( exécution fonction excel vba)
    Par Sawzaaren dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 14/02/2012, 14h34
  2. Réponses: 0
    Dernier message: 14/10/2011, 14h54
  3. Réponses: 2
    Dernier message: 28/04/2011, 17h30
  4. Fonctions non trouvées à l'exécution
    Par remy_ dans le forum Ogre
    Réponses: 4
    Dernier message: 19/10/2009, 11h41
  5. Optimisation d'une fonction non convexe
    Par Kevin_18 dans le forum Mathématiques
    Réponses: 4
    Dernier message: 06/08/2008, 09h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo