« SE4Binome2024-7 » : différence entre les versions
Aucun résumé des modifications |
Aucun résumé des modifications |
||
Ligne 18 : | Ligne 18 : | ||
=== ORDONNANCEUR === | === ORDONNANCEUR === | ||
==== SQUELETTE BASIQUE DE L'ORDONNANCEUR ==== | ==== SQUELETTE BASIQUE DE L'ORDONNANCEUR ==== | ||
Le but de l'ordonnanceur est de répartir l'éxecution des multiples tâches que doit exécuter l'arduino. Pour faire cela, à intervalle régulier (puisque nous fonctionnons en Round Robin),l'Interrupt Service Routine (ISR) va sauvegarder l'état des registres, interrompre la tâche en cours, puis appeler l'ordonnanceur qui va choisir quelle tâche doit maintenant s'exécuter, puis restaurer l'état des registres. | Le but de l'ordonnanceur est de répartir l'éxecution des multiples tâches que doit exécuter l'arduino, et que celles-ci nous semblent simultanées. Pour faire cela, à intervalle régulier (puisque nous fonctionnons en Round Robin),l'Interrupt Service Routine (ISR) va sauvegarder l'état des registres, interrompre la tâche en cours, puis appeler l'ordonnanceur qui va choisir quelle tâche doit maintenant s'exécuter, puis restaurer l'état des registres. | ||
Pour réaliser l'ordonnanceur, nous commençons par initialiser un minuteur qui va définir la fréquence d'interruption (<code>diviseur</code>), le mode de la minuterie (<code>CTC1</code>)) et la période (<code>periode</code>)). | Pour réaliser l'ordonnanceur, nous commençons par initialiser un minuteur qui va définir la fréquence d'interruption (<code>diviseur</code>), le mode de la minuterie (<code>CTC1</code>)) et la période (<code>periode</code>)). | ||
Ligne 60 : | Ligne 60 : | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Nous avons un pointeur destiné à pointer vers la fonction à exécuter pour cette tâche. Le pointeur SPointer sert à sauvegarder la position du pointeur de pile pour cette fonction à l'interruption, chaque fonction ayant sa propre pile d'exécution. L'état permet d'intégrer une fonction sleep par la suite, qui rendra la tâche inactive pendant le delai delay contenu dans data. | Nous avons un pointeur destiné à pointer vers la fonction à exécuter pour cette tâche. Le pointeur SPointer sert à sauvegarder la position du pointeur de pile pour cette fonction à l'interruption, chaque fonction ayant sa propre pile d'exécution. Cela est vital car lorsque l'on voudra continuer l'exécution de cette fonction par la suite, nous devons savoir l'état dans lequel elle s'était arrêtée. L'état permet d'intégrer une fonction sleep par la suite, qui rendra la tâche inactive pendant le delai delay contenu dans data. | ||
==== CLIGNOTEMENT DES LEDs ==== | ==== CLIGNOTEMENT DES LEDs ==== |
Version du 13 novembre 2024 à 11:11
Code Source et autre programmes
TESTS PRELIMINAIRES
Vérification des connecteurs HE-10
Nous avons testé un 7-segments sur tous les connecteurs HE-10. Vous pouvez le voir dans la sous-section COMMUNICATION SPI de la section ORDONNANCEUR.
Lecture Carte SD
Cette image montre la detection de la carte SD sur le Shield par l'ordinateur. On peut observer son type ou sa taille et d'autres informations.
![]() |
Fonctionnement des LEDs
Avant de nous aventurer dans les méandres de l'ordonnanceur, nous devons vérifier que toutes les LEDs sont bien connectées. Nous n'avons pas de photos du dit test mais nous vous invitons à aller voir la sous-section CLIGNOTEMENT DES LEDs dans la section ORDONNANCEUR. Vous pouvez même observer une différence de fréquence entre les clignotements.
ORDONNANCEUR
SQUELETTE BASIQUE DE L'ORDONNANCEUR
Le but de l'ordonnanceur est de répartir l'éxecution des multiples tâches que doit exécuter l'arduino, et que celles-ci nous semblent simultanées. Pour faire cela, à intervalle régulier (puisque nous fonctionnons en Round Robin),l'Interrupt Service Routine (ISR) va sauvegarder l'état des registres, interrompre la tâche en cours, puis appeler l'ordonnanceur qui va choisir quelle tâche doit maintenant s'exécuter, puis restaurer l'état des registres.
Pour réaliser l'ordonnanceur, nous commençons par initialiser un minuteur qui va définir la fréquence d'interruption (diviseur
), le mode de la minuterie (CTC1
)) et la période (periode
)).
Ensuite, nous définissons le comportement qu'il va adopter à chaque interruption. Cela est géré par la fonction ISR en mode NAKED, ce qui implique que l'on va devoir gérer les sauvegardes
des registres nous mêmes (lors d'une interruption, nous commençons toujours par sauvegarder l'état des registres et les restaurons à la fin, sans quoi nous perdons tout le contexte la précédant).
Nous définissons donc en parallèle deux macros SAVE_REGISTERS()
et RESTORE_REGISTERS()
que nous appelons respectivement au début et à la fin de chaque interruption.
Puis nous créons notre fonction ordonnanceur, qui est pour l'instant vide, puisque les tâches n'ont pas encore été construites, et c'est ce à quoi nous allons maintenant nous atteler.
STRUCTURE DES TÂCHES
La structure des tâches est la suivante :
typedef struct Task {
void (*fonction)(void); // Pointeur vers une fonction prenant aucun paramètre et ne retournant rien
uint16_t SPointer; // Pointeur de pile
int state; // État de la tâche
struct prog_data data; // Données de la tâche
} Task;
struct prog_data {
int Type;
union {
int delay; // On peut ajouter d'autres types de données ici si nécessaire
} data;
};
Nous avons un pointeur destiné à pointer vers la fonction à exécuter pour cette tâche. Le pointeur SPointer sert à sauvegarder la position du pointeur de pile pour cette fonction à l'interruption, chaque fonction ayant sa propre pile d'exécution. Cela est vital car lorsque l'on voudra continuer l'exécution de cette fonction par la suite, nous devons savoir l'état dans lequel elle s'était arrêtée. L'état permet d'intégrer une fonction sleep par la suite, qui rendra la tâche inactive pendant le delai delay contenu dans data.
CLIGNOTEMENT DES LEDs
COMMUNICATION SERIE
COMMUNICATION SPI
![]() |
FONCTION SLEEP
Makefile
export CC = avr-gcc
export MCU = atmega328p
export TARGET_ARCH = -mmcu=$(MCU)
export CFLAGS = -Wall -I. -DF_CPU=16000000 -Os #-g
export LDFLAGS = -g $(TARGET_ARCH) -lm -Wl,--gc-sections # -Os
TARGET = ordonnanceur1
#TERM = /dev/ttyUSB0
TERM = /dev/ttyACM0
CPPFLAGS = -mmcu=$(MCU)
PGMER = -c arduino -b 115200 -P $(TERM)
PGMERISP = -c arduino -b 115200 -P $(TERM)
ARVDUDECONF= -C /usr/local/arduino/arduino-0021/hardware/tools/avrdude.conf
export DUDE = /usr/bin/avrdude -F -v -p $(MCU) $(AVRDUDECONF)
C_SRC = $(wildcard *.c)
OBJS = $(C_SRC:.c=.o)
all: $(TARGET).hex
ass:$(C_SRC)
$(CC) -S $(CPPFLAGS) $(CFLAGS) $< -o $@
clean:
rm -f *.o
%.o:%.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
$(TARGET).elf: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS)
$(TARGET).hex: $(TARGET).elf
avr-objcopy -j .text -j .data -O ihex $(TARGET).elf $(TARGET).hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex $(TARGET).elf eeprom.hex
upload: $(TARGET).hex
stty -F $(TERM) hupcl # reset
$(DUDE) $(PGMER) -U flash:w:$(TARGET).hex
# $(DUDE) $(PGMERISP) -U flash:w:$(TARGET).hex
size: $(TARGET).elf
avr-size --format=avr --mcu=$(MCU) $(TARGET).elf
Schéma, PCB & KiCAD
Shield
Photos et vidéos | description |
---|---|
![]() |
Le shield soudée avec juste le BootLoader dans le microP |
Carte RNDIS
PINOUT
PIN UTILITY | PIN NAME |
---|---|
ChipSelect | PB0 |
CLK/SCK | PB1 |
MOSI | PB2 |
MISO | PB3 |
Pin d'Interruption | PB4 |
LED[1-4] | PC[0-3] |
NOTES
deux ports USB pour la carte fille : un pour la connexion en ISP/Réseau à l'ordinateur et un pour la programmation. Possibilité de faire une connexion SPI avec un câble RJ45