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

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
Ligne 23 : Ligne 23 :


== Ordonnanceur ==
== Ordonnanceur ==
[à completer  et commenter , seulement des codes !!!!]
[à completer  et commenter , seulement des codes pour le moment !!!!]


structure d'un process<syntaxhighlight lang="c">
structure d'un process<syntaxhighlight lang="c">
Ligne 32 : Ligne 32 :
int state;
int state;
} process;
} process;
</syntaxhighlight>tableau des process v1<syntaxhighlight lang="c">
process Tasks_list[NBTASKS] = {
{0 , led1_blink, 0,0},
{0 , led2_blink, 0,0},
{0 , led3_blink, 0,0},
{0 , led4_blink, 0,0},
{0 , led5_blink, 0,0},
      };


</syntaxhighlight>Initialisation des leds<syntaxhighlight lang="c">
</syntaxhighlight>Initialisation des leds<syntaxhighlight lang="c">
Ligne 75 : Ligne 85 :
Current_task = 0;  
Current_task = 0;  
}
}
</syntaxhighlight>minuteur (voir cours)
sauvegarde registre<syntaxhighlight lang="c">
#define SAVE_REGISTERS() \
asm volatile ( \
"push r0 \n\t" \
...\
)
#define RESTORE_REGISTERS() \
asm volatile ( \
"pop r31   \n\t" \
...\
)


</syntaxhighlight>ISR<syntaxhighlight lang="c">
</syntaxhighlight>ISR<syntaxhighlight lang="c">
Ligne 87 : Ligne 113 :


</syntaxhighlight>main<syntaxhighlight lang="c">
</syntaxhighlight>main<syntaxhighlight lang="c">
void init() {
        led_init();
init_minuteur(DIV, PER);
for(int Cprocess =0 ; Cprocess<NBTASKS; Cprocess++) {
init_stackPointer_tasks(Cprocess);
init_piles(Cprocess);
}
}
int main() {
int main() {
cli();
cli();
Ligne 106 : Ligne 123 :
return 0;
return 0;
}
}
</syntaxhighlight>fonction sleep<syntaxhighlight lang="c">
void goSleep(int time) { // met un process en veille pour une durée donné
// valeur max de time 32000 car int sur atmega328p code sur 16 bits donc 32000 max
cli();
Tasks_list[Current_task].sleep_time = time;
TCNT1=0;
sei();
TIMER1_COMPA_vect();
</syntaxhighlight>scheduler v2<syntaxhighlight lang="c">
void scheduler() {
for (int i=0 ; i<NBTASKS ; i++) {
if (Tasks_list[i].sleep_time - SLEEP_DEC < 0) {
Tasks_list[i].sleep_time = 0;
} else {
Tasks_list[i].sleep_time -= SLEEP_DEC;
}
}
do {
Current_task++;
if (Current_task >= NBTASKS) {
Current_task = 0;
}
} while (Tasks_list[Current_task].sleep_time > 0);
}
</syntaxhighlight>exemple led<syntaxhighlight lang="c">
void led5_blink() {
while(1) {
for(int i =0; i<5; i++) {
PORTD ^= (1<<PLED5);
_delay_ms(400);
}
goSleep(20);
}
}
</syntaxhighlight>initialisation état<syntaxhighlight lang="c">
void init_state() { //initialise state
for (int i= 0; i<NBTASKS; i++) {
if (Tasks_list[i].functionAddress == NULL) {
Tasks_list[i].state = 1;
}
else {
Tasks_list[i].state = 0;
}
}
}
</syntaxhighlight>finir, tuer et ajouter un process<syntaxhighlight lang="c">
void finish() { //supprime un process lorsque celui-ci est terminé
cli();
Tasks_list[Current_task].state =1;
Tasks_list[Current_task].sleep_time = 0;
Tasks_list[Current_task].functionAddress = NULL;
TCNT1=0;
sei();
TIMER1_COMPA_vect();
}
void kill(void (*function)(void)) { //tue le process passé en paramètre
cli();
for(int i = 0; i<NBTASKS; i++) {
if(Tasks_list[i].functionAddress == function) {
Tasks_list[i].state =1;
Tasks_list[i].sleep_time = 0;
Tasks_list[i].functionAddress = NULL;
}
}
sei();
}
void add(void (*newFunction)(void)) { //ajoute un process
cli();
int i =0;
while(Tasks_list[i].state != 1) {
i++;
}
Tasks_list[i].functionAddress = newFunction;
Tasks_list[i].state = 0;
init_stackPointer_tasks(i);
init_piles(i);
sei();
}
</syntaxhighlight>tableau des process v2<syntaxhighlight lang="c">
process Tasks_list[NBTASKS] = {
{0, ANTI_BLOCK, 0,0},
{0 , main_leds, 0,0}
      };


</syntaxhighlight>
</syntaxhighlight>

Version du 8 novembre 2025 à 20:23

Shield Arduino

Afin de tester notre futur carte réseau, nous avons fait un sheild d'arduino qui prendra le rôle de la carte mère durant.

Schématique

Nous nous sommes évidemment aider de la datasheet de l'atmega328p ainsi que celle de l'arduino uno afin de sélectienner les bon pins.

Datasheet ATmega328p
Datasheet Arduino Uno R3

Plus précisément nous nous insirons très fortement du schéma page 10 de la datasheet de l'arduino :

Schéma pinouts

Nous sommes donc parti de l'exemple fourni par Mr Redon. Mais nous avons utilisé une template disponible dans kicad permettant de créer des sheilds d'arduino Uno R3.

Schématique shield arduino

Routage

Au niveau du routage, nous avons tenté de faire simple (sans trop abuser sur les vias. Nous avons positionner le lecteur de carte sd au bord de la carte afin de ne pas avoir de problèmes avec d'autres composants lorsque nous voudrons mettre ou enlever la carte sd.

Routage shield arduino

Soudage

La schématique et le routage terminés, nous avons soudé les différents pins permettant de souder la carte shield à l'arduino, le reste n'étant pas forcément utile pour le moment (il est important de noter que notre shield est arrivé avec des composants présoudés).

Shield soudage de base .jpg

Tests

Il faudra ensuite faire des test d'allumage des leds, afin de vérifier le bon fonctionnement du shield

Les leds fonctionnant à merveille, Il est temps de passer de passer à l'ordonnanceur.

Ordonnanceur

[à completer et commenter , seulement des codes pour le moment !!!!]

structure d'un process

typedef struct {
	uint16_t stackPointer;
	void (*functionAddress)(void);
	int sleep_time;
	int state;
} process;

tableau des process v1

process Tasks_list[NBTASKS] = {
				{0 , led1_blink, 0,0},
				{0 , led2_blink, 0,0},
				{0 , led3_blink, 0,0},
				{0 , led4_blink, 0,0},
				{0 , led5_blink, 0,0},
			       };

Initialisation des leds

void led_init() {
	DDRC |= (1<<PLED1) | (1<< PLED2);
	DDRB |= (1<<PLED3);
	DDRD |= (1<<PLED4) | (1<<PLED5);
}
void led1_blink() {
	while(1) {
		PORTC ^= (1<<PLED1);
		_delay_ms(100);
        }
}
void led2_blink() {
...

initialisation pointeur de pile et pile

void init_stackPointer_tasks(int Cprocess) { //initialise le pointer de pile
	if(Tasks_list[Cprocess].state == 0) {
		Tasks_list[Cprocess].stackPointer = FIRST_STACK_POSITION - (Cprocess * STACK_LENGTH);
	}
}


void init_piles(int Cprocess){ //initilalise la pile
	if(Tasks_list[Cprocess].state == 0) {
		int save = SP;
		SP = Tasks_list[Cprocess].stackPointer;
		uint16_t address = (uint16_t)Tasks_list[Cprocess].functionAddress;
		asm volatile("push %0" : : "r" (address & 0x00ff) );
		asm volatile("push %0" : : "r" ((address & 0xff00)>>8) );
		SAVE_REGISTERS();
		Tasks_list[Cprocess].stackPointer = SP;
		SP = save;
	}
}

scheduler v1

void scheduler() {
	Current_task++;
	if (Current_task >= NBTASKS) {
		Current_task = 0; 
}

minuteur (voir cours) sauvegarde registre

#define SAVE_REGISTERS() \
	asm volatile ( \
		"push r0 	 \n\t" \
		...\
)


#define RESTORE_REGISTERS() \
	asm volatile ( \
		"pop r31 	  \n\t" \
		...\
)

ISR

ISR(TIMER1_COMPA_vect, ISR_NAKED) {
	SAVE_REGISTERS();
	Tasks_list[Current_task].stackPointer = SP;
	scheduler();
	SP = Tasks_list[Current_task].stackPointer;
	RESTORE_REGISTERS();
	asm volatile("reti");
}

main

int main() {
	cli();
	init();
	sei();
	
	SP = Tasks_list[Current_task].stackPointer;
	Tasks_list[Current_task].functionAddress();
	
	return 0;
}

fonction sleep

void goSleep(int time) { // met un process en veille pour une durée donné
	// valeur max de time 32000 car int sur atmega328p code sur 16 bits donc 32000 max
	cli();
	Tasks_list[Current_task].sleep_time = time;
	TCNT1=0;
	sei();
	TIMER1_COMPA_vect();

scheduler v2

void scheduler() {
	for (int i=0 ; i<NBTASKS ; i++) {
		if (Tasks_list[i].sleep_time - SLEEP_DEC < 0) {
			Tasks_list[i].sleep_time = 0;
		} else {
			Tasks_list[i].sleep_time -= SLEEP_DEC;
		}
	}


	do {
		Current_task++;
		if (Current_task >= NBTASKS) {
			Current_task = 0;
		}
	} while (Tasks_list[Current_task].sleep_time > 0);
}

exemple led

void led5_blink() {
	while(1) {
		for(int i =0; i<5; i++) {
			PORTD ^= (1<<PLED5);
			_delay_ms(400);
		}
		goSleep(20);
	}
}

initialisation état

void init_state() { //initialise state
	for (int i= 0; i<NBTASKS; i++) {
		if (Tasks_list[i].functionAddress == NULL) {
			Tasks_list[i].state = 1;
		}
		else {
			Tasks_list[i].state = 0;
		}
	}
}

finir, tuer et ajouter un process

void finish() { //supprime un process lorsque celui-ci est terminé
	cli();
		Tasks_list[Current_task].state =1;
		Tasks_list[Current_task].sleep_time = 0;
		Tasks_list[Current_task].functionAddress = NULL;
	TCNT1=0; 
	sei();
	TIMER1_COMPA_vect();
}

void kill(void (*function)(void)) { //tue le process passé en paramètre
	cli();
	for(int i = 0; i<NBTASKS; i++) {
		if(Tasks_list[i].functionAddress == function) {
			Tasks_list[i].state =1;
			Tasks_list[i].sleep_time = 0;
			Tasks_list[i].functionAddress = NULL;
		}
	} 
	sei();
}


void add(void (*newFunction)(void)) { //ajoute un process
	cli();
	int i =0;
	while(Tasks_list[i].state != 1) {
		i++;
	}
	Tasks_list[i].functionAddress = newFunction;
	Tasks_list[i].state = 0;
	init_stackPointer_tasks(i);
	init_piles(i);

	sei();
	
}

tableau des process v2

process Tasks_list[NBTASKS] = {
				{0, ANTI_BLOCK, 0,0},
				{0 , main_leds, 0,0}
			       };

Carte Réseau

Lors de la répartition des tâches, nous avons opté pour une solution basée sur la carte réseau. Le sujet nous permettait de choisir parmi plusieurs microcontrôleurs. Nous avons retenu l’ATmega32U4, qui nous semble représenter un juste milieu entre l’ATmega16U2 et l’AT90USB.

Notre carte intègre des LED permettant d’afficher différents états de communication (que nous définirons ultérieurement).

À la demande de M. Redon, nous avons ajouté un MAX232 ainsi que des connecteurs DB9 et DB25. Nous espérons que ces éléments pourront être utiles.

Schématique CReseau.png
Routage Creseau.png