Image of an arrow

Travailler les données d’un analyseur logique Saleae en Python

Avatar

sbourdelin

Salae Logic AnalyzerRécemment, j’ai été amené à devoir prendre des mesures de temps très précises pour répondre à une problématique de contrainte temps-réel. Sur un SoC particulier avec un système Linux dessus, la question était de savoir quelle était la fluctuation de la latence entre le déclenchement d’un événement matériel et la réponse d’une tâche logicielle associée à cet événement.

La gigue ou fluctuation du signal

Qu’est ce que la gigue ou jitter en anglais ? Prenons, par exemple, un événement avec une fréquence parfaite — disons l’heure à laquelle sonne mon réveil — et un autre événement moins parfait qui lui est associé, comme le moment où j’ouvre les yeux. Chaque jour, l’heure de mon réveil reste la même. En revanche, le moment où j’ouvre les yeux pour éteindre mon réveil varie… au désespoir de mon patron. :/

Cette fluctuation est la gigue. Dans ce cas, il s’agit d’une gigue temporelle, comme dans ma problématique.

Mesurer la gigue avec un oscilloscope

Typiquement, mesurer la latence entre deux événements matériels se fait très bien avec un oscilloscope à deux canaux. Il suffit de savoir où sonder, sur notre circuit, ces événements. Après quelques réglages, on peut visualiser la latence et, notamment, avoir une persistance sur chaque prise de mesure qui va nous donner une enveloppe de cette fluctuation.

Ma première démarche à donc été d’associer à ma tâche logicielle un autre événement matériel pour m’aider à prendre ces mesures. Mon événement matériel initial était une interruption et je savais où la sonder sur le SoC. À celui-ci, je réponds par un autre événement matériel qui consiste à faire commuter une GPIO que je sais également où sonder sur le SoC.

Ainsi à chaque fois que l’interruption se déclenche, la GPIO change d’état.

Ce qui nous donnera par exemple sur un oscilloscope quelque chose comme ça :

jitter_simulated

Avec en jaune l’interruption qui est réguliére, et en vert la fluctuation des temps de réponse de la GPIO.

Il ne me restait plus qu’à prendre mes mesures avec un oscilloscope. Mais là c’est le drame… je ne disposais pas d’oscilloscope suffisamment récent pour avoir une enveloppe consistante de mes signaux; faute de mémoire, je pouvais conserver tout au plus les 32 dernières mesures et je ne pouvais donc pas voir ma fluctuation sur de longues périodes.

Le seul autre équipement à ma disposition pour prendre des mesures était un analyseur logique Saleae Logic. Bien que très pratique, ce dernier ne me permettait pas de visualiser ma fluctuation du signal.

Comment visualiser la gigue avec l’analyseur logique de Saleae ?

Avec cet analyseur, ce que je peux obtenir comme résultat ressemble à cela:

logic_output

En zoomant on voit bien la latence entre le déclenchement de l’interruption (en haut) et la commutation de ma GPIO (en bas):

logic_output_zoom

Ce qui m’intéresse, c’est mesurer étant le temps entre le drapeau 1 et le drapeau 2 pour chaque interruption et le visualiser de façon facilement compréhensible, comme ceci:

logic_output_zoom_flag

Mais je ne peux pas faire ça à la main pour chaque interruption et recommencer à chaque prise de mesure.

C’est en discutant de mon problème, qu’un collègue et ami (Emeric Vigier, pour ne pas le nommer), me pointa à juste titre sur la fonction d’exportation de ce logiciel. Et, effectivement, l’ensemble des informations qui me sont nécessaires sont à ma disposition, le dernier problème étant juste qu’elles ne sont pas organisées comme je le désire.

Visualisation des données : du CSV au Graphique

Donc, comme précisé précédemment, l’analyseur logique de Saleae me permet d’exporter mes données au format CSV sous la forme:

Time[s], Interrupt Trigger, Gpio 0
0, 0, 1
0.00258295833333333, 1, 1
0.00258408333333333, 0, 1
0.002633, 0, 0
0.00758641666666667, 1, 0
0.00758758333333333, 0, 0
0.007629625, 0, 1
0.0125899166666667, 1, 1
...

La première valeur me donnant le temps en seconde, la deuxième l’état de mon interruption (0 = bas, 1 = haut), et la troisième l’état de ma GPIO. Donc, l’algorithme me permettant de récupérer ma latence sera:

Pour chaque ligne,

  1. Si mon interruption passe de 0 à 1, Alors je note son temps dans A
  2. Si j’ai A et que ma GPIO change d’état, Alors je note son temps dans B
  3. Si j’ai A et B, Alors je soustrais A à B et je garde le résultat dans le tableau C

Le tableau C contiendra ainsi l’ensemble des temps de latence. En quelques lignes de Python, cela donne le code suivant :

STEP_INTERRUPT  = 0
STEP_GPIO       = 1

with open(file_csv, 'r') as csvfile:
    cvsreader = csv.reader(csvfile, delimiter=',')

    # the first entry give us the initial state
    init_state      = next(cvsreader)
    interrupt_state = init_state[interrupt]
    gpio_state      = init_state[gpio]
    step            = STEP_INTERRUPT

    for row in cvsreader:

        # The first step is to find an interrupt edge
        if step == STEP_INTERRUPT:
            if (interrupt_state == 0 and int(row[interrupt]) == 1):
                interrupt_value = float(row[0])
                step = STEP_GPIO

        # The second step is to find a gpio commutation
        elif step == STEP_GPIO:
            if (gpio_state != int(row[gpio])):
                gpio_value = float(row[0])
               
                # here we know we have an interrupt edge value
                # and the gpio commutation time
                # we can take the delay mesure between the two
                delay = gpio_value - interrupt_value

                # store the delay value in millisecond.
                dic.append((delay * 1000, 0.5))

                # we can now reinit the step
                step = STEP_INTERRUPT

        interrupt_state = int(row[interrupt])
        gpio_state      = int(row[gpio])

À ce stade, je dispose de l’ensemble de mes latences, maintenant j’aimerais bien pouvoir les mettre en forme avec quelque chose de plus parlant — et ce n’est pas comme si l’on manquait de librairies pour réaliser des graphiques dans Python. Donc, prenons en une au hasard, et dessinons!

J’ai choisi la librairie pygal, qui permet de dessiner des points dans un espace à 2 dimensions. Il m’a suffit de rajouter ces quatre lignes de Python à mon script:

xy_chart = pygal.XY(stroke=False, fill=False, show_y_labels=False, legend_at_bottom=True, show_dots=True, dots_size=0.8, print_values=False)
xy_chart.title = 'Jiffies'
xy_chart.add('values in milli-second', sorted(dic))
xy_chart.render_to_png('jitter.png')

Et voilà le résultat tant désiré car nettement plus parlant:

jitter-with-pygal

On peut ainsi voir quelque chose qui se rapproche de notre première capture d’écran (l’exemple d’un oscilloscope) tout en économisant quelques milliers de dollars… cette fois, au grand bonheur de mon patron. 😉

Le script complet est disponible ici : github.com/sbourdelin/logic-jitter

  1. Excellent cet article sur « comment sauver 40 000 dollars avec 50 lignes de Python »!
    Tu as oublié de préciser: « Article terminé 2h avant que le réveil ne sonne, d’où le jitter à l’ouverture des yeux. 😉

  2. Très bonne utilisation de Python dans ce type de contexte!

    Par contre il y a bug: tu as un état de trop, STEP_GPIO!
    Durant l’état STEP_INTERRUPT tu obtiens toutes les valeurs nécessaire
    durant l’état STEP_GPIO, donc tu peux déjà calculer ‘delay’ dedans
    et passer directement de STEP_INTERRUPT à STEP_INIT.

    De plus passer par STEP_GPIO mange une entrée de tes données pour rien.
    J’ai posté un bug dans sur ton github 😉

Comments are closed.


Articles similaires

Image of an arrow

Savoir-faire Linux est fière d’annoncer la sortie de la version v2.3.0 de l’extension officielle du Projet Yocto pour VS Code. Lisez l’article complet en anglais. Liens et ressources Pour en savoir plus sur cette ambitieuse extension du Projet Yocto pour VS Code : Téléchargez l’extension depuis le magasin VS Code Parcourez le code, signalez des […]

Savoir-faire Linux est fière d’annoncer la sortie de la version v2.2.0 de l’extension officielle du Projet Yocto pour VS Code. Cette version majeure offre de nouvelles fonctionnalités très demandées par la communauté ! Parmi les nouveautés, la possibilité de gérer plusieurs configurations BitBake dans le même espace de travail VS Code, ou encore l’analyse des […]

[L’introduction est en français, le reste du texte en anglais]   L’économie d’énergie a toujours été une préoccupation majeure dans les systèmes embarqués, puisque par définition, ils peuvent avoir des contraintes énergétiques. Bien sûr, aujourd’hui, l’économie d’énergie est toujours au cœur des discussions. L’économie d’énergie est toujours un ensemble de compromis. En termes de disponibilité […]

L’équipe de Savoir-faire Linux est fière d’annoncer la sortie de la version v2.1 de l’extension du Projet Yocto pour VS Code. Le projet Yocto, avec le financement du Sovereign Tech Fund, a entrepris d’étendre et de moderniser cette technologie pour les cinq années à venir. Au sein de cette initiative, Savoir-faire Linux s’est vu confier […]

Thumbnail image

[L’introduction est en français, le reste du texte en anglais] TL;DR Les systèmes audio utilisent souvent des périphériques asynchrones, qui ont besoin d’être synchronisés avec du ré-échantillonnage. Nos mesures montrent que la charge CPU du ré-échantillonnage peut atteindre presque 30% d’un cœur sur un SoC i.MX8M Nano. Utiliser l’endpoint de feedback de l’USB gadget UAC2 […]