« SE4Binome2025-4 » : différence entre les versions

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Aucun résumé des modifications
Ligne 41 : Ligne 41 :
Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais.
Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais.


<syntaxhighlight lang="c">
#define SAVE_REGISTERS()  \
        asm volatile (  \
        "push r0 \n\t" \
        "in r0,__SREG__ \n\t push r0 \n\t" \
        "push r1 \n\t push r2 \n\t push r3 \n\t push r4 \n\t push r5 \n\t push r6 \n\t push r7 \n\t push r8 \n\t push r9                        \n\t" \
        "clr  r1 \n\t" \
        "push r10 \n\t push r11 \n\t push r12 \n\t push r13 \n\t push r14 \n\t push r15 \n\t push r16 \n\t push r17 \n\t push r18 \n\t push r19 \n\t" \
        "push r20 \n\t push r21 \n\t push r22 \n\t push r23 \n\t push r24 \n\t push r25 \n\t push r26 \n\t push r27 \n\t push r28 \n\t push r29 \n\t" \
        "push r30 \n\t push r31 \n\t" \
        );


ici on definit la structure d'une tâche, qu'elle fonction elle doit exécuter, quand elle doit etre exécuter, la derniere fois qu'elle ''été exécuté, sa priorité et son ID''<syntaxhighlight lang="c">
#define RESTORE_REGISTERS() \
typedef struct {
        asm volatile ( \
    void (*pFunction)(void); // Pointeur vers la fonction de la tâche
        "pop r31 \n\t pop r30 \n\t" \
    uint32_t Period_ms;      // Période d'exécution souhaitée (en ms)
        "pop r29 \n\t pop r28 \n\t pop r27 \n\t pop r26 \n\t pop r25 \n\t pop r24 \n\t pop r23 \n\t pop r22 \n\t pop r21 \n\t pop r20 \n\t" \
    uint32_t Last_Run_Time;  // Timestamp de la dernière exécution
        "pop r19 \n\t pop r18 \n\t pop r17 \n\t pop r16 \n\t pop r15 \n\t pop r14 \n\t pop r13 \n\t pop r12 \n\t pop r11 \n\t pop r10 \n\t" \
    uint8_t  Priority;      // Priorité (0: la plus faible)
        "pop r9 \n\t pop r8 \n\t pop r7 \n\t pop r6 \n\t pop r5 \n\t pop r4 \n\t pop r3 \n\t pop r2 \n\t pop r1                      \n\t" \
    uint8_t  ID;            // ID de la tâche
        "pop r0 \n\t out __SREG__,r0 \n\t" \
} Task_t;
        "pop r0 \n\t" \
        );
</syntaxhighlight>ici on definit l'etat de la tache<syntaxhighlight lang="c">
typedef enum{
        Ready,
        Sleep,
}task_state;


</syntaxhighlight>
#if 0
struct task {
        uint16_t function;
        uint16_t stack;
};
#endif


ici, configure le Timer1 pour générer '''une interruption toutes les 20 ms'''. Cette interruption sert de '''tick système''' pour que le scheduler exécute les tâches périodiques.<syntaxhighlight lang="c">
typedef struct  {
void SCHEDULER_Init(void) {
        void(*function)(void);
    TaskCount = 0;
        uint16_t stack;
    GlobalTick = 0;
        volatile task_state state;
        uint16_t sleepTime;
}process;
</syntaxhighlight><syntaxhighlight lang="c">


    // 1. Mise à zéro des Registres
ISR(TIMER1_COMPA_vect,ISR_NAKED){    // Procédure d'interruption
    TCCR1A = 0; // Réinitialise TCCR1A
SAVE_REGISTERS();
    TCCR1B = 0; // Réinitialise TCCR1B
Tasks[current].stack=SP;
    TCNT1  = 0; // Initialise le compteur à zéro
LED_PORT ^= (1<<LED1_BIT);
scheduler();
SP=Tasks[current].stack;
RESTORE_REGISTERS();
asm volatile ( "reti" );
}


    // 2. Mode CTC (Clear Timer on Compare Match)
    // WGM12 = 1 dans TCCR1B pour le mode CTC
    TCCR1B |= (1 << WGM12);


     OCR1A = 5000;  
void wait(uint16_t delay) {
     Tasks[current].sleepTime = delay;
    Tasks[current].state = Sleep;
    TCNT1=nb_ticks-1;
    while(Tasks[current].state == Sleep);
}


     // 3. Définir le Prescaler à 1024 (CS12=1, CS10=1 dans TCCR1B)
void add_task(void (*task_function)(void)) {
    TCCR1B |= (1 << CS12) | (1 << CS10);  
     for (int n = 0; n < MAX_TASKS; n++) {
        if (Tasks[n].function == 0) {
            Tasks[n].function = task_function;
            Tasks[n].stack = (uint16_t)(STACKTOP - n * STACKSIZE);
            Tasks[n].state = Ready;
            sei();
        }
    }
}


    // 4. Autoriser l'interruption Timer1 Compare Match A (OCIE1A dans TIMSK1)
// Fonction pour supprimer une tâche
     TIMSK1 |= (1 << OCIE1A);  
void remove_task(int n) {
     if (n >= 0 && n < MAX_TASKS) {
        Tasks[n].function = 0;  // Supprime la tâche en réinitialisant la fonction
        Tasks[n].state = Sleep; // Met la tâche en état de sommeil
    }
}


    // 5. Activer les interruptions globales
    sei();
}


</syntaxhighlight>
</syntaxhighlight>
Ici, il est question d'enregistrer une nouvelle tâches, en mettant son code, sa période, son ID, etc....<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
int8_t SCHEDULER_AddTask(void (*pFunction)(void), uint32_t Period_ms, uint8_t Priority) {
int8_t SCHEDULER_AddTask(void (*pFunction)(void), uint32_t Period_ms, uint8_t Priority) {
     if (TaskCount < MAX_TASKS) {
     if (TaskCount < MAX_TASKS) {
Ligne 98 : Ligne 139 :
</syntaxhighlight>
</syntaxhighlight>


[[Fichier:Clignotement de la led.mov|vignette]]


=='''Carte Son'''==
=='''Carte Son'''==

Version du 5 janvier 2026 à 13:28

Carte Son pour un pico ordinateur : lien git SE4-PICO-B4.git


Présentation projet

Dans le cadre du cursus Systèmes Embarqués (SE4), ce projet consiste à concevoir un système capable de générer des signaux sonores de manière autonome. L'objectif est de transformer une valeur numérique calculée par un programme en une tension électrique réelle pour faire vibrer un haut-parleur.

Le système repose sur deux éléments principaux :

La carte Shield Arduino(PICO) : Équipée d'un microcontrôleur ATmega32U4, elle assure l'intelligence du système et l'ordonnancement des tâches. La carte fille son : Elle contient le dispositif de conversion numérique-analogique (DAC) et l'étage d'amplification.


Shield

Réalisation du shield arduino

Nous avons réalisé un bouclier pour Arduino Uno afin d'implémenter un système d'ordonnancement, ce qui nous permettra de simuler le fonctionnement d'une carte mère.

Schématique - Routage et vue 3D

PicoShield - schema électrique SE4-2025
PicoShield - schema vue3D SE4-2025 G4
PicoShield - schema routage SE4-2025 G4
PicoShield - schema vue3D SE4-2025 G4
PicoShield - schema vue3D SE4-2025 G4




Ordonnanceur / Système d'exploitation

Le code implémente un mini ordonnanceur préemptif sur Arduino, qui alterne deux tâches toutes les 20 ms grâce à un timer et à son ISR.

Chaque tâche a sa propre pile et son contexte CPU.

Code de l'ordonnanceur

Un ordonnanceur sert à gérer l'exécution des tâches dans un système temps réel, en assurant qu'elles s'exécutent dans un ordre optimal et respectent les délais.

#define SAVE_REGISTERS()  \
        asm volatile (  \
         "push r0 \n\t" \
         "in r0,__SREG__ \n\t push r0 \n\t" \
         "push r1 \n\t push r2 \n\t push r3 \n\t push r4 \n\t push r5 \n\t push r6 \n\t push r7 \n\t push r8 \n\t push r9                        \n\t" \
         "clr  r1 \n\t" \
         "push r10 \n\t push r11 \n\t push r12 \n\t push r13 \n\t push r14 \n\t push r15 \n\t push r16 \n\t push r17 \n\t push r18 \n\t push r19 \n\t" \
         "push r20 \n\t push r21 \n\t push r22 \n\t push r23 \n\t push r24 \n\t push r25 \n\t push r26 \n\t push r27 \n\t push r28 \n\t push r29 \n\t" \
         "push r30 \n\t push r31 \n\t" \
        );

#define RESTORE_REGISTERS() \
        asm volatile ( \
         "pop r31 \n\t pop r30 \n\t" \
         "pop r29 \n\t pop r28 \n\t pop r27 \n\t pop r26 \n\t pop r25 \n\t pop r24 \n\t pop r23 \n\t pop r22 \n\t pop r21 \n\t pop r20 \n\t" \
         "pop r19 \n\t pop r18 \n\t pop r17 \n\t pop r16 \n\t pop r15 \n\t pop r14 \n\t pop r13 \n\t pop r12 \n\t pop r11 \n\t pop r10 \n\t" \
         "pop r9 \n\t pop r8 \n\t pop r7 \n\t pop r6 \n\t pop r5 \n\t pop r4 \n\t pop r3 \n\t pop r2 \n\t pop r1                       \n\t" \
         "pop r0 \n\t out __SREG__,r0 \n\t" \
         "pop r0 \n\t" \
        );

ici on definit l'etat de la tache

typedef enum{
        Ready,
        Sleep,
}task_state;

#if 0
struct task {
        uint16_t function;
        uint16_t stack;
};
#endif

typedef struct  {
        void(*function)(void);
        uint16_t stack;
        volatile task_state state;
        uint16_t sleepTime;
}process;
ISR(TIMER1_COMPA_vect,ISR_NAKED){    // Procédure d'interruption
SAVE_REGISTERS();
Tasks[current].stack=SP;
LED_PORT ^= (1<<LED1_BIT);
scheduler();
SP=Tasks[current].stack;
RESTORE_REGISTERS();
asm volatile ( "reti" );
}


void wait(uint16_t delay) {
    Tasks[current].sleepTime = delay;
    Tasks[current].state = Sleep;
    TCNT1=nb_ticks-1;
    while(Tasks[current].state == Sleep);
}

void add_task(void (*task_function)(void)) {
    for (int n = 0; n < MAX_TASKS; n++) {
        if (Tasks[n].function == 0) {
            Tasks[n].function = task_function;
            Tasks[n].stack = (uint16_t)(STACKTOP - n * STACKSIZE);
            Tasks[n].state = Ready;
            sei();
        }
    }
}

// Fonction pour supprimer une tâche
void remove_task(int n) {
    if (n >= 0 && n < MAX_TASKS) {
        Tasks[n].function = 0;  // Supprime la tâche en réinitialisant la fonction
        Tasks[n].state = Sleep; // Met la tâche en état de sommeil
    }
}
int8_t SCHEDULER_AddTask(void (*pFunction)(void), uint32_t Period_ms, uint8_t Priority) {
    if (TaskCount < MAX_TASKS) {
        TaskList[TaskCount].pFunction = pFunction;
        TaskList[TaskCount].Period_ms = Period_ms;
        TaskList[TaskCount].Last_Run_Time = GlobalTick; // Exécution immédiate
        TaskList[TaskCount].Priority = Priority;
        TaskList[TaskCount].ID = TaskCount + 1;
        TaskCount++;
        //return TaskCount;
	return TaskList[TaskCount - 1].ID;
    }
    return 0; // en cas d'echec
}


Carte Son

Description

Notre carte fille son sera alimentée par la carte mère.

Elle comporte une ATmega328p comme coeur et sa spécificité est un convertisseur numérique vers analogique dit R-2R.

Pour fonctionner, elle a besoin :

  • d'un microphone
  • d'un haut-parleur pour jouer le son,
  • d'un connecteur USB permettant la configuration de l'appareil via une connexion a un ordinateur .

Schématique - routage et vue 3D

PicoShield - schema électrique SE4-2025
Carte son - schema electrique SE4-2025 G4
Carte son - schema routage SE4-2025 G4
Carte son - schema routage SE4-2025 G4
Carte son - schema vue3D recto SE4-2025 G4
Carte son - schema vue3D recto SE4-2025 G4
Carte son - schema vue3D verso SE4-2025 G4
Carte son - schema vue3D verso SE4-2025 G4