Tout ça je le connais et je l'ai fais , ce que je comprend pas c'est l'algorithme,quand commuter quand on a besoin d la semaphore, où l'appeler.
C'est l'algo que je ne comprend pas.
Version imprimable
Tout ça je le connais et je l'ai fais , ce que je comprend pas c'est l'algorithme,quand commuter quand on a besoin d la semaphore, où l'appeler.
C'est l'algo que je ne comprend pas.
Au début, l'acquisition SPI prends les DEUX sémaphores, et ENSUITE, le thread d'envoi TCP/IP essaie de prendre le premier (ce qui va le bloquer, bien sûr).
Une fois le premier buffer rempli, le SPI lâche le sémaphore du premier buffer, ce qui permet au thread d'envoi d'avoir la main dessus. Une fois les données envoyées, le thread d'envoi lâche le sémaphore, et attends le second (normalement, il est encore bloqué par l'acquision SPI).
A chaque fois que le buffer est plein, le thread SPI doit effectuer les actions suivantes :
- Prendre l'AUTRE sémaphore, éventuellement avec un timeout négatif pour vérifier s'il est libre (s'il ne l'est pas => erreur critique).
- Relâcher le sémaphore courant (=> libère le thread TCP/IP en attente dessus).
- Acquérir les données jusqu'à remplissage du buffer.
Pour le thread TCP/IP, c'est la séquence suivante :
- Prendre le sémaphore courant (=> on se retrouve bloqué, il est pris par l'acquisition SPI).
- Une fois débloqué, envoyer les données sur le réseau jusqu'à vider le buffer.
- Libérer le sémaphore courant.
- Prendre l'autre (=> bloqué, normalement).
Merci infiniment , c'est ce que je faisai aussi , sauf que j'ai pas envi de taper des lignes de codes et de ne pas savoir les erreurs proviennent d'où surtout dans une programmation qui me fait perdre !!
Merci
Voilà quelques bouts de code pour assurer les échanges de buffers :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 int Current = 0 ; void* Buffers[2] ; int Semaphores[2] ; // Récupération du buffer/sémaphore courant. Buffers[Current] = .... ; Semaphores[Current] = .... ; // Récupération de l'AUTRE buffer/sémaphore. Buffers[1-Current] = .... ; Semaphores[1-Current] = .... ; // Changement de buffer courant. // A ne faire QUE lorsque l'acquisition SPI possède les DEUX sémaphores !!!! Current = 1 - Current ;
Voila quelque lignes de code que j'ai fait si tu peu jeter un coup d 'oeil je me suis juste occupe de l'envoi pour le moment :
Code de la fonction send :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 while(1) { if (T->Established() == 1) { // recuperer les buf/semaphore Buffers[Current] =data1; Semaphores[Current] =semID1 ; Buffers[1-Current] = data2; Semaphores[1-Current] =semID2; // envoi T->Send(Buffers[Current],8*3,Semaphores[Current]); //echnage de buffer semaphore Current = 1 - Current ; }
Code:
1
2
3
4
5
6
7
8
9 short cSocket::Send(unsigned char * bufptr, USHORT bufLen,int far *sem) { int result; RTX_Reserve_Sem(*sem,0); result=send ( sd, bufptr, bufLen, MSG_DONTWAIT, &error ); RTX_Free_Sem(*sem); //if (result==-1) established = 0; //si l'envoi echoue on ferme la connection return result; }
Bon je crois je suis énormément perdu la :
Tu dis que AU DEBUT il faut que le SPI reserve les deux semaphore , comment alors faire sachant que mon SPI fonctionne sur interruption externe.
Dans le main je ne sais pas comment faire le "AU DEBUT", ni l'echange de buffers puisque comme j'ai dit le SPI est en interruption.Code:
1
2
3
4
5
6
7
8
9 void main() { //installation de l'interruption while(1) { if(connected) //envoi } }
Donc en gros je te demande stp qu'est ce que je dois mettre dans les fonction :
etCode:void huge Config_SPI_HW::ReadWriteBlock(unsigned char *rbuffer,unsigned char *wbuffer) //Read/Write 8 Bytes
qu'est ce que le main doit contenir et qu'est ce que le thread envoi et l'interruption vont contenir???Code:short cSocket::Send(unsigned char * bufptr, USHORT bufLen)
Merci
Salut j'attend toujours ta réponse , en attendant je te file mon pseudo code pour voir si c'est ce qu'il faut faire :
Le souci est comment le SPI peut posseder les deux sémaphore tout au début.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 unsigned char data1[8*3]; // les deux buffer unsigned char data2[8*3]; unsigned char zz=0x00; unsigned char wbuffer[8]={zz,zz,zz,zz,zz,zz,zz,zz}; // pour la fonction de la lecture SPI int far *semID1; // semaphore for protecting data1 , et data2 int far *semID2; // variable pour l'échange int Current = 0 ; // variables d'echange cote EVNOI TCP void* Buffers[2] ; int Semaphores[2] ; int _Current = 0 ; //variables d'echange coté SPI void* _Buffers[2] ; int _Semaphores[2] ; short cSocket::Send(USHORT bufLen) { Buffers[Current]=data1; //recupere buffer et semaphore Semaphores[Current]=semID1 ; Buffers[1-Current] = data2; Semaphores[1-Current] =semID2; RTX_Reserve_Sem(Semaphores[Current],0); send ( sd, Buffers[Current], bufLen, MSG_DONTWAIT, &error ); RTX_Free_Sem(Semaphores[Current]); current=1-current; //echange de semaphore et buffer. } void huge Config_SPI_HW::ReadWriteBlock() { spi_waiton_sem_setmode_dyn(SPI_MODE, div); //pour synchroniser les esclaves SPI. _Buffers[_Current]=data1; //recupere buffer et semaphore _Semaphores[_Current]=semID1 ; _Buffers[1-_Current] = data2; _Semaphores[1-_Current] =semID2; RTX_Reserve_Sem(Semaphores[Current],0); //Lecture SPI while(1) { for (i=0;i<8;i++) { spi_read_write_dyn(_Buffers[_Current]+i,wbuffer+i,1); //Introduction de retard while(ctr-->0); ctr = 2; } } RTX_Free_Sem(_Semaphores[_Current]); //liberer la semaphore _Current =1-_Current; //echange de buffer semaphore spi_release_sem(); // liberer le bus SPI } main() { // debut de code while(1) { if(connected) { Send(8*3); } else { // ecoute et réinitialisation de la connection } }
Merci et désolé encore pour le dérangement!
Déjà, il faut vérifier que le SPI peut bien acquérir les sémaphores tout en étant en IT. Normalement, oui, mais c'est à vérifier quand même.
Ensuite : au départ, l'acquisition SPI peut parfaitement locker les deux sémaphores parce qu'ils n'appartiennent à personne.
Enfin : tu ne dois pas échanger les buffers, et encore moins les sémaphores, dans le thread TCP/IP. Seul l'acquisition SPI a le droit de le faire, le thread TCP/IP prenant TOUJOURS le buffer/sémaphore courant.
Dit autrement, le consommateur (thread TCP/IP) boucle sur un seul et même buffer, c'est le producteur (acquisition SPI) qui est maître des deux buffers et autorise la permutation.
Comment le TCP/IP doit boucler sur un seul buffer???
Prendr l'autre ca veux dire l'autre buffer non!!??Citation:
Pour le thread TCP/IP, c'est la séquence suivante :
Prendre le sémaphore courant (=> on se retrouve bloqué, il est pris par l'acquisition SPI).
Une fois débloqué, envoyer les données sur le réseau jusqu'à vider le buffer.
Libérer le sémaphore courant.
Prendre l'autre (=> bloqué, normalement).
Ce n'est pas logique si on boucle sur le meme buffer on risque de l'ecraser par l'ecriture SPI a tout moment!!!
Vraiment je comprend plus rien en ce que tu m'a di c'est un peu contradictoire pour moi,l'envoi doit se fair sur un buffer quand ce buffer est plein l'envoi se fera cette fois sur l'autre , il y'a bel et bien 2 buffer quand meme dans le processus TCP/IP , et apres tu di :
Comment ca se fait???8OCitation:
Enfin : tu ne dois pas échanger les buffers, et encore moins les sémaphores, dans le thread TCP/IP
Oui, il envoie (par exemple) toujours le contenu du premier buffer.
Prendre le SÉMAPHORE de l'autre buffer. Une fois plein, l'acquisition SPI va échanger buffers et sémaphores.
Mais non. A part sur la première boucle (et encore...), le SPI, lui, remplit systématiquement le SECOND buffer.
Oui, mais regarde de nouveau le schéma que j'avais indiqué en début de sujet, sur le double buffer : à chaque fois, un des accès est coupé pour un des éléments.
Le fait de "changer de buffer" signifie que l'on échange les pointeurs des buffers, et des sémaphores associés, lorsque le buffer SPI est plein.
Parce que le thread TCP/IP est consommateur (= "esclave", si tu préfères). Ce n'est pas lui qui peut décider du taux de remplissage du buffer en cours d'acquisition SPI, mais bel et bien le code d'acquisition SPI lui-même. C'est donc le SPI qui est "maître" des buffers, et qui décide du moment où l'échange se produit.
Ok ,alors pourquoi tu a expliqué au début que :
Citation:
Quand le buffer d'acquisition SPI est plein, tu permutes les deux buffers (en fait, simplement le pointeur sur le buffer), et tu préviens par un sémaphore / mutex / flag global que l'envoi doit se faire sur l'autre buffer
Voila ma dérniere version du code , tu peux me dire si c'est bon là , sinon tu peux editer le code et mettre des explications dessus , genre des commentaires là où ça marche pas :D
Déclarations :
Code TCP :Code:
1
2
3
4
5
6
7 int far *semID1; // semaphore for protecting data1 , et data2 int far *semID2; // variable pour l'échange int Current = 0 ; // variables d'echange cote EVNOI TCP void* Buffers[2] ; int Semaphores[2] ;
Code SPICode:
1
2
3
4
5
6
7
8
9
10 short cSocket::Send(unsigned char * bufptr, USHORT bufLen) { RTX_Reserve_Sem(Semaphores[Current],0); // reserve semaphore courant int result = send ( sd, bufptr, bufLen, MSG_DONTWAIT, &error ); // envoi quand il est débloqué RTX_Free_Sem(Semaphores[Current]); // Quand le buffer est vidé on libére la sémaphore courante if (result==-1) established = 0; //si l'envoi echoue on ferme la connection return result; }
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 void huge Config_SPI_HW::ReadWriteBlock() //Read/Write 8 Bytes { spi_waiton_sem_setmode_dyn(SPI_MODE, div); //pour synchroniser les esclaves SPI. Buffers[Current]=data1; //recupere buffers et semaphores Semaphores[Current]=semID1 ; Buffers[1-Current] = data2; Semaphores[1-Current] =semID2; RTX_Reserve_Sem(Semaphores[Current],0); //réserve le sémaphore courant. //Lecture SPI while(1) { for (i=0;i<8;i++) { spi_read_write_dyn(Buffers[Current]+i,wbuffer+i,1); //Introduction de retard while(ctr-->0); ctr = 2; } } RTX_Free_Sem(Semaphores[Current]); //liberer la semaphore courante. Current =1-Current; //echange de buffer /semaphore spi_release_sem(); // liberer le bus SPI }
Ah j'ai oublié le main :
Code:
1
2
3
4
5
6
7
8
9 while(1) { if (T->Established() == 1) { T->Send(Buffers[Current],8*3); }
Voilà merci :P