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

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Ligne 182 : Ligne 182 :
</pre>
</pre>


|}
Voila maitenant nos taches, il est important de créer une TacheZombie qui comme son nom l'indique est toujours révéillée.
{| class="wikitable" style="width:100%;"
! scope="col" | Code
|-
| style="width:50%;" |
<pre>
void TacheZombie() //Tache toujours réveillé
{
while(1)
{
_delay_ms(1.5*PERIODE_INTERUPTION); //Delay légèrement supèrieur à la periode pour éviter tout soucis
}
}
void TacheA()
{
while(1)
{
PORTC ^= 0x08;
Attente(300);
    }
}
void TacheB()
{
while(1)
{
PORTD ^= 0x80;
Attente(500);
    }
}
</pre>
|}
|}
== Soudure et Test du SHIELD ==
== Soudure et Test du SHIELD ==

Version du 16 janvier 2024 à 13:53

Ordonnanceur

Nous commençons maintenant l'ordonnanceur, tout d'abord nous créeons la structure de nos Taches.

Code
struct TacheInfo{
	void (*depart)(void);
	uint16_t SPointeur;
	int etat;
};

Puis nous ajoutons les 2 premières taches demandées qui sont de faire clignoter 2 leds différentes à des timing différents.

Code
void TacheA(){
    while(1)
    {
        PORTC ^= 0x08;
	_delay_ms(300);
    }
}

void TacheB(){
    while(1)
    {
        PORTD ^= 0x80;
	_delay_ms(500);
    }
}

struct TacheInfo Taches[2]={
  {TacheA,0x0600,0},
  {TacheB,0x0700,0}
};

On s'occupe maintenant de l'ordonnanceur, ainsi que de l'ISR.

Code
void ordonnanceur ()
{	
	PORTD ^= 0x02;
	courant++;
	if (courant == NBR_TACHE) courant = 0;
}

ISR(TIMER1_COMPA_vect,ISR_NAKED)
{
	/* Sauvegarde du contexte de la tâche interrompue */
	SAVE_REGISTER();
	Taches[courant].SPointeur = SP;

	/* Appel à l'ordonnanceur */
	ordonnanceur();

	/* Récupération du contexte de la tâche ré-activée */
	SP = Taches[courant].SPointeur;
	RESTORE_REGISTER();
	asm volatile ( "reti" );
}

Nous avons décider de faire clignoter une LED (PORTD ^= 0x02) à chaques utilisations de la fonction ordonnanceur() dans l'ISR.

La variable courant indique la Tache qui est actuellement en cours.

A chaque chaques changements de tache, l'ISR se déclenche enregistre la tache en cours (les registres ainsi que le Stack Pointer), appel l'ordonnanceur, puis change "charge" la tache suivante.

On oublie pas maitenant de générer l'interruption toute les 20ms, pour cela on choisit un prescaler de 1024 et un nombre de ticks de 312.

Code
#define PRESCALER 1024
#define NB_TICK  312
#define CTC1  WGM12

void init_timer(){
TCCR1A = 0;  // No output pin connected, no PWM mode enabled
TCCR1B = 1<<CTC1; // No input pin used, clear timer counter on compare match
#if (PRESCALER==1024)
 TCCR1B |= (1<<CS12 | 1<<CS10);
#endif
OCR1A = NB_TICK;
TCNT1 = 0;
TIMSK1 = (1<<OCIE1A); // No overflow mode enabled, no input interrupt, output compare interrupt
}

Ainsi que d'initialiser les Taches pour assurer le bon fonctionnement de notre ordonnanceur.

Code
void init_taches(int pid)
{
	int save=SP;
	SP=Taches[pid].SPointeur;
	uint16_t adresse=(uint16_t)Taches[pid].depart;
	asm volatile ("push %0 \n\t" : : "r" (adresse & 0x00ff));
	asm volatile ("push %0 \n\t" : : "r" ((adresse & 0xff00) >> 8));
	SAVE_REGISTER();
	Taches[pid].SPointeur=SP;
	SP=save;
}

On peut maintenant tester notre ordonnanceur.

Code Vidéo
#define NBR_TACHE 2
int main(void){
	init_ports();
	init_timer();
	init_taches(1);
	sei();
	SP = Taches[courant].SPointeur;
	Taches[courant].depart();
	return 0;
}

Les 2 leds clignotent bien avec le bon timing, et la led témoin de l'ordonnanceur clignotent aussi, ce qui indique que l'ISR est bien actif.

Nous pouvons donc maitenant passer à la gestion des "sleeps".

En effet, l'utilisation de _delay_ms dans chaque tache n'est pas la manière la plus optimale de procéder. Et meme cela nous bloquera par la suite.

Nous ajoute donc à la structure de nos Taches, une structure InfoEndormi, qui, comme son nom l'indique nous donne des informations si la tache est endormie. A savoir la raison mais aussi des donnees comme par exemple le temps que cette tache doit passer endormie.

Puis afin de remplacer _delay_ms, nous créeons une fonction Attente qui endors une tache pour un temps donné.

Code Code
#define REVEILLE 0
#define ENDORMI 1
#define RAISON_DELAY 0

struct InfoEndormi{
    int raison;
    uint16_t donnee;
}sleep_t;


struct TacheInfo{
    void (*depart)(void); 
    uint16_t SPointeur;
    int etat;
    struct InfoEndormi endormi;
};
void Attente(uint16_t temps_ms){
    cli();
    Taches[Tache_courante].etat = ENDORMI;
    Taches[Tache_courante].endormi.raison = RAISON_DELAY;
    Taches[Tache_courante].endormi.donnee = temps_ms;
    TCNT1 = 0;
    sei();
}

Voila maitenant nos taches, il est important de créer une TacheZombie qui comme son nom l'indique est toujours révéillée.

Code
void TacheZombie() //Tache toujours réveillé
{
	while(1)
	{
		_delay_ms(1.5*PERIODE_INTERUPTION); //Delay légèrement supèrieur à la periode pour éviter tout soucis
	}
}

void TacheA()
{
	while(1)
	{
		PORTC ^= 0x08;
		Attente(300);
    }
}

void TacheB()
{
	while(1)
	{
		PORTD ^= 0x80;
		Attente(500);
    }
}

Soudure et Test du SHIELD

Au cours des 2 premières séances nous avons soudé et testé notre Shield

Shield soudé et monté sur Arduino

Sur l'un des connecteurs, la led est abîmée dû à une soudure excessive. Sachant que les leds sont uniquement utilisées en tant qu'indicateurs pour savoir quelle carte fille à le contrôle et que nous n'en utiliserons pas plus de 3 pour tester nos programmes, cela ne vas pas avoir d'influence négative.

Code Image
#include <avr/io.h>

void init_led(){
  DDRD=0x92;
  DDRC=0x09;
}

int main(){
  init_led();
  while(1)
    {
	PORTD=0x92;
	PORTC=0x09;
    }
  return 0;
}
Test des Leds du Shield

Puis nous avons aussi soudé l'adaptateur HE10 pour l'utilisation de la matrice de leds

Adaptateur HE10 pour Matrice de leds

Carte FPGA

Carte électronique numérique

Nous avons choisi la Carte Fille : Ecran LCD

Pendant la 3ème séance nous avons finis le Schématic de la carte

Schematic de la Carte Fille : Ecran LCD

Puis nous avons Routé la carte et envoyé à la Fabrication

Routage de la Carte Fille : Ecran LCD
Carte non soudée Carte soudé
Carte non soudée
Carte soudée

Références utiles

Lien du git :

https://archives.plil.fr/mchauvel/PICO_Taha_NEHARI_Martin_CHAUVELIERE.git

https://github.com/Matiasus/HD44780

NHD-C12832A1Z-FSW-FBW-3V3-ND

http://cdzillidan.free.fr/electronique-numerique/modules/afficheurs-lcd/hd44780/fonctionnement-interne.html

https://michlstechblog.info/blog/raspberry-pi-connecting-a-hd44780-display-with-i2c-bus/

ReX : Merci d'utiliser le squelette de page présenté en séance.