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

C Discussion :

[FreeRTOS] Comment récupérer les données d'un buffer ?


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut [FreeRTOS] Comment récupérer les données d'un buffer ?
    Bonjour,

    J'ai programme embarqué qui utilise FreeRTOS et j'ai une tache qui remplie un buffer.
    Je voudrais créer la fonction readData() qui me permettrait de pouvoir récupérer les données : comment faut-il procéder ?
    Je pensais utiliser des mutex mais je ne vois pas trop comment faire sans que socket_task() et readData() s'inter-bloquent car ces deux fonctions ont besoin de connaitre l'état de l'autre fonction :
    - socket_task() doit savoir quand readData() a vidé le buffer pour pouvoir relancer la fonction de remplissage du buffer.
    - readData() ne doit pas lire le buffer s'il est en cours de modification par socket_task() (getSocketData() en cours d'execution).

    Ci-dessous, les contraintes que j'ai (surtout à cause de la gestion du timeout) :
    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
     
    static char rxBuffer[100];
    static size_t rxLen;
     
    void socket_task(void){
    	while(1){
    		// Remplissage du buffer
    		// => Cette fonction est blocante.
    		// => Elle ne doit pas être rappelée tant
    		//    que le buffer n'a pas été entièrement vidé.
    		bool_t status = getSocketData(rxBuffer, &rxLen);
    		if(status){
    			//... TODO : blocage tant que les données de rxBuffer n'ont pas été récupérée ...
    		}
    	}
    }
     
    // Fonction pour récupérer les données : elle est appelée depuis d'autres taches
    bool_t readData(char * data, size_t size, size_t *read, TickType_t timeout){
        // La fonction est blocante tant qu'elle n'a pas récupérée le nombe d'octets
        // définit par la variable size
        // ... ou si le timeout s'est déclenché.
    	// => Si timeout vaut portMAX_DELAY, alors il n'y a pas de gestion de timeout
    	//    (la fonction reste tout le temps blocante jusqu'a ce que le nombe d'octets
        //    définit par la variable size soit récupéré)
    	// => La fonction retourne true si pas de timeout déclenché (sinon false)
    	// => après execution de la fonction, read contient le nombre d'ooctets récupérés.
     
    	//... TODO ...
    	// => il faut arriver à gérer les cas où la valeur de size est différente de
    	//    la taille de rxBuffer.
     
    }
    Merci d'avance

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Actuellement, j'ai fait ça (solution théorique pas encore testée) :
    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
     
    static char rxBuffer[100];
    static size_t rxLen;
     
    static bool_t rxBufferIsProcessing;
    static bool_t readDataIsProcessing;
    static SemaphoreHandle_t socket_mutex;
     
    void socket_task(void){
    	while(1){
    		// Remplissage du buffer
    		// => Cette fonction est blocante.
    		// => Elle ne doit pas être rappelée tant
    		//    que le buffer n'a pas été entièrement vidé.
     
    		while(1){
    			xSemaphoreTake(socket_mutex, portMAX_DELAY);
    				if(readDataIsProcessing == false){
    					rxBufferIsProcessing = true;
    					xSemaphoreGive(socket_mutex);
    					break;
    				}
    			xSemaphoreGive(socket_mutex);
    		}
     
    		bool_t status = getSocketData(rxBuffer, &rxLen);
    		if(status){
    			// getSocketData() n'a pas renvoyé d'erreur
    			// => rien de special à faire
    		}
     
    		xSemaphoreTake(socket_mutex);
    			rxBufferIsProcessing = false;
    		xSemaphoreGive(socket_mutex);
     
    	}
    }
     
     
    // Fonction pour récupérer les données : elle est appelée depuis d'autres taches
    bool_t readData(char * data, size_t size, size_t *read, TickType_t timeout){
        // La fonction est blocante tant qu'elle n'a pas récupérée le nombe d'octets
        // définit par la variable size
        // ... ou si le timeout s'est déclenché.
    	// => Si timeout vaut portMAX_DELAY, alors il n'y a pas de gestion de timeout
    	//    (la fonction reste tout le temps blocante jusqu'a ce que le nombe d'octets
        //    définit par la variable size soit récupéré)
    	// => La fonction retourne true si pas de timeout déclenché (sinon false)
    	// => après execution de la fonction, read contient le nombre d'ooctets récupérés.
     
    	*read = 0;
     
    	if(size == 0){
    		return true;
    	}
     
     
    	if(size != *read){
    		do {
    			char * ptr = rxBuffer;
     
    			while(1){
    				if(xSemaphoreTake(socket_mutex, timeout) != pdTRUE){return false;}
    					if(rxBufferIsProcessing == false){
    						readDataIsProcessing = true;
    						break;
    					}
    				xSemaphoreGive(socket_mutex);
    			}
    				while(rxLen){
    					*data = *ptr;
    					data++; ptr++; rxLen--; (*read)++;
    					if(size == *read){
    						break;
    					}
    				}
    				readDataIsProcessing = false;
    			xSemaphoreGive(socket_mutex);	
    		} while(size != *read);
    	}
     
    	return true;
    }
    ... Mais, il y deux problèmes :
    - les while(1) font que les taches consomment du temps processeur pour rien
    - le timeout est réinitialisé à chaque fois que rxBuffer[] est mis à jour


    EDIT : je viens de me rendre compte qu'il y a un autre problème... vu que getSocketData() est bloquant lorsqu'il attends de nouvelles données... readData() est bloquée par le mutex si pas de données reçues

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Je suis parti sur ce nouveau système, ça vous semble bon ?
    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
     
    static char rxBuffer[100];
    static char * rxPtrBuffer;
    static size_t rxLen;
     
    static SemaphoreHandle_t rxBufferIsNotEmpty_event;
    static SemaphoreHandle_t rxBufferIsEmpty_event;
     
     
    void socket_task_init(void){
    	rxBufferIsNotEmpty_event = xSemaphoreCreateMutex();
    	rxBufferIsEmpty_event = xSemaphoreCreateMutex();
     
    	xSemaphoreTake(rxBufferIsNotEmpty_event, portMAX_DELAY); // initialisation de l'event
    	//xSemaphoreTake(rxBufferIsEmpty_event, portMAX_DELAY); // initialisation de l'event
     
    	rxLen = 0;
    	rxBuffer[0] = '\0';
    	rxPtrBuffer = rxBuffer;
    }
     
    void socket_task(void){
     
    	while(1){
    		// Remplissage du buffer
    		// => Cette fonction est blocante.
    		// => Elle ne doit pas être rappelée tant
    		//    que le buffer n'a pas été entièrement vidé.
     
    		// Attente de l'event buffer empty
    		xSemaphoreTake(rxBufferIsEmpty_event, portMAX_DELAY);
     
    		bool_t status = getSocketData(rxBuffer, &rxLen);
    		if(status){
    			// getSocketData() n'a pas renvoyé d'erreur
    			// => rien de special à faire
     
    			rxPtrBuffer = rxBuffer
     
    			// Génération de l'event buffer not empty
    			xSemaphoreGive(rxBufferIsNotEmpty_event);
    		}
     
     
    	}
    }
     
     
    // Fonction pour récupérer les données : elle est appelée depuis d'autres taches
    bool_t readData(char * data, size_t size, size_t *read, TickType_t timeout){
        // La fonction est blocante tant qu'elle n'a pas récupérée le nombe d'octets
        // définit par la variable size
        // ... ou si le timeout s'est déclenché.
    	// => Si timeout vaut portMAX_DELAY, alors il n'y a pas de gestion de timeout
    	//    (la fonction reste tout le temps blocante jusqu'a ce que le nombe d'octets
        //    définit par la variable size soit récupéré)
    	// => La fonction retourne true si pas de timeout déclenché (sinon false)
    	// => après execution de la fonction, read contient le nombre d'octets récupérés.
     
    	*read = 0;
     
    	if(size == 0){
    		return true;
    	}
     
     
    	if(size != *read){
    		TickType_t tickStartCount = xTaskGetTickCount();
     
    		do {			
    			TickType_t diffTime = xTaskGetTickCount() - tickStartCount;
     
    			if(diffTime >= timeout){
    				return false;
    			}
    			timeout -= diffTime;
     
    			// Attente de l'event buffer not empty
    			if(xSemaphoreTake(rxBufferIsNotEmpty_event, timeout) != pdTRUE){
    				return false;
    			}
     
    			// Traitement des données
    			while(rxLen){
    				*data = *rxPtrBuffer;
    				data++; rxPtrBuffer++; rxLen--; (*read)++;
    				if(size == *read){
    					break;
    				}
    			}
     
    			if(rxLen == 0){
    				// Génération de l'event buffer empty
    				xSemaphoreGive(rxBufferIsEmpty_event);
     
    			} else {
    				// Regénération de l'event buffer not empty pour le prochain
    				// appel de readData car on n'a pas vidé complètement le buffer.
    				xSemaphoreGive(rxBufferIsNotEmpty_event);
    			}			
     
    		} while(size != *read);
    	}
     
    	return true;
    }

  4. #4
    Membre émérite
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Points : 2 724
    Points
    2 724
    Billets dans le blog
    1
    Par défaut
    Petite question, pourquoi utiliser des socket?

    Je suppose que tu n'es pas en reseau et que tu lance tout dans la même application?

    Si oui regarde le design pattern master/slave ou worker, je ne sais plus comment ça s'appelle ^^.

    En gros le concept c'est que tu as une liste chainée de tache, et le master s'occupe de la remplir pendant que le slave s'occupe de la lire, le tout protégé par une mutex le temps de la lecture.

    En pseudo code ça donne ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    fonction ajoutTache(tache)
    {
      lock(list)
      pushBack(list, tache)
      unlock(list)
    }
    fonction lireTache()
    {
      lock(list)
      readFirst(list, tache)
      unlock(list)
      executeTache(tache)
    }
    Si tu as des questions n'hésite pas
    Pas de solution, pas de probleme

    Une réponse utile (ou +1) ->
    Une réponse inutile ou pas d'accord -> et expliquer pourquoi
    Une réponse à votre question


  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    J'ai utilisé le terme socket pour me faire comprendre plus facilement (j'ai essayer de simplifier mon problème au maximum) : en fait, je tentais d'utiliser un driver USB qui fonctionne avec une gestion de DMA.
    Maintenant ça fonctionne : mon erreur est d'avoir voulu ne pas modifier le code applicatif d'exemple... en le modifiant, ça simplifie grandement le système

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. comment récupérer les données supprimés
    Par ouadie99 dans le forum Windows XP
    Réponses: 1
    Dernier message: 02/03/2007, 18h59
  2. Réponses: 6
    Dernier message: 24/01/2007, 10h29
  3. Comment récupérer les données ?
    Par carlosdz dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 20/07/2006, 00h05
  4. Réponses: 3
    Dernier message: 06/07/2006, 18h49
  5. [VB6] MySQL Comment récupérer les données ?
    Par budylove dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 22/02/2006, 14h58

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