Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Essai de communication via port Serial 3-pins CG10/20/50
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Essai de communication via port Serial 3-pins CG10/20/50

Posté le 11/05/2022 08:22

Hello,

ayant juste un petit peu de temps, cette fin de semaine avant d'être une semaine off-line, je voulais regarder un peu la libsnd et le port serial 3-pins. Je me suis donc imprégné de la documentation que j'ai pu trouver ici et là. Mes recherches m'ont permis d'identifier les sources suivantes :
- les sources de la libsnd de Thomas Williamson (utilisée dans l'excellentissime Nesizm) et du PrizmSDK
- la doc de la bible PC collectée par Simon Lothar (partie CG20 - Serial) dispo ici : serial CG20
- l'explication de texte des syscalls correspondants dans le Wiki de Cemetech ici : wiki Serial

A partir de cela, je me suis fait une mini-librairie (je sais, c'est maladif en ce moment ) appelée libserial (original, vous ne trouvez pas) qui reprend les syscalls suivants directement liés au port serial 3-pins, ainsi que le header correspondant (serial.h) :
- Serial_ClearRX
- Serial_ClearTX
- Serial_Close
- Serial_IsOpen
- Serial_Open
- Serial_Peek
- Serial_PollRX
- Serial_PollTX
- Serial_Read
- Serial_ReadSingle
- Serial_Write
- Serial_WriteSingle
- Serial_WriteUnbuffered

ainsi que les suivants, plus ou moins éloignés, mais repris dans le prizmSDK (je les virerais si il ne servent effectivement pas) :
- App_LINK_GetDeviceInfo
- App_LINK_GetReceiveTimeout_ms
- App_LINK_Send_ST9_Packet
- App_LINK_SetReceiveTimeout_ms
- App_LINK_SetRemoteBaud
- App_LINK_TransmitInit
- App_LINK_Transmit
- Comm_Close
- Comm_Open
- Comm_Terminate
- Comm_TryCheckPacket

Pour vérifier que tout fonctionne, j'ai fait un simple petit programme pour vérifier l'état du port serial (ouvert et / ou fermé), puis procéder à son ouverture et à sa fermeture, tout cela sur ma CG50 (Graph 90+E) et ma CG20 pour vérifier que les syscalls sont toujours bien utilisables. Ok, ça compile, ça link et surtout ça fonctionne. Voici le code utilisé :

Vérif, ouverture et fermeture du port Serial - Cliquer pour dérouler
Vérif, ouverture et fermeture du port Serial - Cliquer pour enrouler


#include <gint/display.h>
#include <gint/keyboard.h>
#include <serial.h>

int main(void)
{
    dclear(C_WHITE);
    dtext(1, 1, C_BLACK, "Sample fxSDK Communication add-in.");

    if (Serial_IsOpen() != 1)
    {
        dtext(1,21, C_RED, "Serial port is CLOSED !!!" );
        dtext(1,31, C_RGB( 31, 24, 0), "Trying to Open it ..." );
        unsigned char mode[6]={0,9,0,0,0,0};
        Serial_Open( mode );
    }

    if (Serial_IsOpen() == 1) dtext(1,41, C_GREEN, "Serial port is now OPEN !!!" );
    else
    {
        dtext(1,41, C_RED, "Failed to open the Serial port : STILL CLOSED !!!" );
        dtext(1,51, C_BLACK, "Press a key to exit back to OS ..." );
        dupdate();
        getkey();
        return 0;
    }

    if (Serial_IsOpen() == 1)
    {
        dtext(1,121, C_RED, "Now closing the Serial Port !!!" );
        Serial_Close( 1 );
    }

    if (Serial_IsOpen() != 1) dtext(1,141, C_GREEN, "Serial port is now Closed !!!" );

    dupdate();

    getkey();

    return 1;
}



C'est donc un début vraiment encourageant, dans le sens où la gestion du port se fait correctement et la mini librairie semble bien fonctionner de son côté.

Bon, donc plein d'espoir, j'essaie de passer à l'étape suivante :
- sur une des 2 machines, envoyer un paquet de char dans le buffer de transmission (donc transmettre, en langage décodé),
- sur l'autre machine, recevoir un paquet de char dans le buffer de réception (donc recevoir ).

Le but étant ici juste d'envoyer d'un côté et de lire de l'autre côté, sans contrôle d'erreur et tout ce qu'il faudrait faire pour avoir des vraies communications "sérieuses" (donc pas taper merci ) ... on reste dans le très très expérimental par un gars qui découvre .

Ceci étant réalisé par le code suivant (enfin, l'expression adéquate serait plutôt : "ceci devant être réalisé par le code suivant" ) :

Envoi et réception sur port Serial - Cliquer pour dérouler
Envoi et réception sur port Serial - Cliquer pour enrouler
*

#include <gint/display.h>
#include <gint/keyboard.h>
#include <serial.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    dclear(C_WHITE);
    dtext(1, 1, C_BLACK, "Sample fxSDK Communication add-in.");

    if (Serial_IsOpen() != 1)
    {
        dtext(1,21, C_RED, "Serial port is CLOSED !!!" );
        dtext(1,31, C_RGB( 31, 24, 0), "Trying to Open it ..." );
        unsigned char mode[6]={0,9,0,0,0,0};
        Serial_Open( mode );
    }

    if (Serial_IsOpen() == 1) dtext(1,41, C_GREEN, "Serial port is now OPEN !!!" );
    else
    {
        dtext(1,41, C_RED, "Failed to open the Serial port : STILL CLOSED !!!" );
        dtext(1,51, C_BLACK, "Press a key to exit back to OS ..." );
        getkey();
        return 0;
    }

    dtext(1,210, C_BLACK, "SEND");
    dtext(60, 210, C_BLACK, "RECV");

    dtext(1, 61, C_BLACK, "Press F1 to set Send mode and F2 to set Receive mode" );
    dupdate();

    if (getkey().key == KEY_F1)
    {
        char MessageToSend[256];
        strcpy( MessageToSend, "Hello World !!!" );
        int CountSend = 15;

        dprint(1, 81, C_BLUE, "Will send a message %s ", MessageToSend );
        dupdate();
        getkey();

//        int result = Serial_Write( (unsigned char*) MessageToSend, CountSend ); // Fait Crash la babasse

        int result = Serial_WriteSingle( (unsigned char) 'Y' ); // idem, fait aussi crash la babasse

        if (result==0)
        {
            dprint(1, 101, C_GREEN, "Message sent" );
        }
        else if (result==2)
        {
            dprint(1, 101, C_RED, "buffer is full" );
        }
        dupdate();
        getkey();

    }
    else if (getkey().key == KEY_F2)
    {
        unsigned char MessageRead[256];
        int MaxCountRead = 256;
        short int CountRead = 0;
        dtext(1, 81, C_BLUE, "Will receive a message " );
        dupdate();

        int result = Serial_Read( MessageRead, MaxCountRead, &CountRead );
        if (result==0)
        {
            dprint(1, 101, C_GREEN, "%s", MessageRead );
        }
        else if (result==1)
        {
            dprint(1, 101, C_RED, "buffer is empty" );
        }
        dupdate();
        getkey();
    }


    if (Serial_IsOpen() == 1)
    {
        dtext(1,121, C_RED, "Now closing the Serial Port !!!" );
        Serial_Close( 1 );
    }

    if (Serial_IsOpen() != 1) dtext(1,141, C_GREEN, "Serial port is now Closed !!!" );

    dupdate();

    getkey();
    return 1;
}




En mode réception (appui sur F2 sur une des machines, cela semble fonctionner (sauf qu'il y a rien à lire donc j'ai le message correspondant affiché), par contre en émission (sur l'autre machine, après appui sur F1), j'ai systématiquement un crash avec reboot de la machine sur la ligne du Serial_Write/Serial_WriteSingle.

J'ai bien entendu testé chacune des machines en réception ET en émission, et c'est bien le même comportement sur chacune d'elle. L'émission fait systématiquement crasher et rebooter la machine.

Auriez-vous une idée ou un semblant d'idée pouvant expliquer ce comportement ?

Je précise que les syscalls sont bien ceux de la page ici (avec leur code respectifs) : serial CG20

Ciao

Sly


Lephenixnoir Hors ligne Administrateur Points: 22452 Défis: 149 Message

Citer : Posté le 11/05/2022 08:31 | #


Première suspicion : je ne vois pas de world switch. J'ai aucune idée de ce qu'il se passe dans ces syscalls ni de comment ça interagit avec gint.
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 11/05/2022 08:40 | #


Oui je me suis posé la question de savoir si on a besoin ou pas, je peux essayer avec pour voir si ça change qqchose.
Je fais l'essai et update en fonction.

Ajouté le 11/05/2022 à 08:42 :
Je suis en train de me dire, visiblement le Serial_Open, SerialIsOpen et Serial_Close fonctionnent sans gint_world_switch ...
Lephenixnoir Hors ligne Administrateur Points: 22452 Défis: 149 Message

Citer : Posté le 11/05/2022 08:44 | #


Et donc ? L'écriture pourrait utiliser le DMA.
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 11/05/2022 08:44 | #


certes
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 11/05/2022 08:48 | # | Fichier joint


Non, faux espoir, idem malgré le remplacement de la ligne


int result = Serial_WriteSingle( (unsigned char) 'Y' );

par :

int result = (int) gint_world_switch( GINT_CALL( Serial_WriteSingle, 'Y' ) );


Mais c'était une très très bonne idée.
Yatis En ligne Membre Points: 575 Défis: 0 Message

Citer : Posté le 11/05/2022 19:36 | #


Il faut absolument restaurer la VBR dans tous les cas car Casio utilise l'interruption du module SCIF pour fonctionner que ce soit en lecture ou en écriture. Donc le world switch est obligatoire. Essaie de passer par le syscall 0x1BBE Serial_Write(void *data, size_t count)

Ajouté le 11/05/2022 à 19:40 :
Et je viens de regarder le syscall Serial_Open(), idem, ça utilise beaucoup plus de module hardware (TMU, POWER, ...) et probablement une synchronisation est faites via le gestionnaire d'interruption. Donc c'est full world-switch si tu veux utiliser ces syscalls
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 11/05/2022 20:23 | #


Ok, je vais tout mettre dans une fonction et faire un call de cette fonction a travers un gint_world_switch pour voir si ca aide.

Je fais un point quand j'ai fait l'essai.

Pour info en fouinant sur Cemetech j'ai trouvé quelqu'un qui reporte que le code suivant fonctionne (on est pas loin de mon code)


static unsigned char serialMode[6] = {0, 5, 0, 0, 0, 0};

void dumpToSerial(unsigned int * startAddress, unsigned int size) {
  unsigned int i;
  if (Serial_IsOpen() == 1) {
    Serial_Close(1);
  }
  Serial_Open(serialMode);
  for (i = 0; i < size; i++) {
    while(1) {
      response = Serial_WriteSingle(*(startAddress + i));
      if (response == 0) {
        break;
      } else if (response == 2) {
        // Transmit Buffer is full, we need to wait
      } else if (response == 3) {
        PrintXY(1,2,"  Not Open",0x00,TEXT_COLOR_BLUE);
        while(1) GetKey(&key);
        break;
      }
    }
  }
}


donc on doit pas être très très loin, faut juste trouver ce qui coince ...
Lephenixnoir Hors ligne Administrateur Points: 22452 Défis: 149 Message

Citer : Posté le 11/05/2022 20:25 | #


Mets aussi une attente avant de revenir dans gint, il pourrait y avoir des trucs asynchrones.

Note que la "bonne" façon de faire est bien sûr de coder un driver dans gint.
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 11/05/2022 20:33 | #


Je suis tout à fait d'accord, je suis juste dans le défrichage

Le grosse étape à la serpette, puis vient le temps des paysagistes qui font ça propre
Yatis En ligne Membre Points: 575 Défis: 0 Message

Citer : Posté le 12/05/2022 08:13 | #


Mets aussi une attente avant de revenir dans gint, il pourrait y avoir des trucs asynchrones

AH OUI ! Parce que le Serial_Write() est extrêmement simple : il copie l'info dans un buffer interne (à la main) puis Casio active l'interruption de "transmission" puis sort de la fonction

Bonne chance pour sycro tout ça, j'imagine qu'il y a un bit qui indique le status de la transaction (tu peux check si la valeur du bit SCSCR. TIE == 0, si c'est le cas, Casio attend plus rien (il active l'interruption uniquement quand il y a besoin et désactive une fois le buffer de transmission vide (à voir pour le buffer de réception, je n'ai pas regardé)))
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 12/05/2022 08:29 | #


J'imagine que la valeur de l'octet 4 passé à Serial_Open (Stop bit) doit effectivement servir à ça.

J'avais peu de temps hier alors j'ai juste pu faire un petit essais (totalement infructueux) d'encapsulation de tout le toutim dans un world-switch.

Pas fructueux, mais au moins ça a pas crash comme à l'accoutumée.

A un moment, il faudra je pense revenir à la doc du 7305 (enfin 7724) et se palucher les registres. Ton RE sera certainement ultra utile à ce moment.

Tu aurais dispo le RE de tous les syscalls Serial_*** ? Pour voir exactement ce que chacun fait de manière détaillée.

Merci pour ton aide Yatis.
Yannis300307 Hors ligne Membre Points: 50 Défis: 0 Message

Citer : Posté le 02/08/2022 15:39 | #


Est-ce que quelqu’un a trouvé une solution pour éviter le crash ?
Slyvtt Hors ligne Community Manager Points: 801 Défis: 0 Message

Citer : Posté le 02/08/2022 16:59 | #


Hello, non je n'ai toujours pas trouvé d'où venait le problème.
Bon pour être tout à fait honnête, j'ai eu pas mal de choses à gérer qui m'ont un peu éloigné de la programmation depuis quelques semaines/mois.
J'essaierai de jeter un œil, peut être qu'une vision un peu neuve me donnera de meilleures idées.
Yannis300307 Hors ligne Membre Points: 50 Défis: 0 Message

Citer : Posté le 02/08/2022 17:33 | #


Je crois avoir trouvé : les syscalls ne sont pas bons par exemple, le syscall du Serial_WriteSingle est 0x040E et pas 0x1BBC. Avec ce changement la calculatrice ne crash plus, l'Arduino reçoit quelque chose mais il reçoit le caractère "⸮" (pour moi en tt cas). Mais c'est déja une grande avancée ! Il faut prendre ça : https://bible.planet-casio.com/simlo/chm/v20/fx_legacy_Serial.htm

Il faut juste le fix dans la lib.
Yannis300307 Hors ligne Membre Points: 50 Défis: 0 Message

Citer : Posté le 02/08/2022 17:49 | #


Juste, quelqu'un sait pourquoi gint_world_switch(GINT_CALL( Serial_WriteSingle, text)); met une erreur ?
Lephenixnoir Hors ligne Administrateur Points: 22452 Défis: 149 Message

Citer : Posté le 02/08/2022 17:55 | #


Alors pour les numéros de syscall c'est parce que la lib elle est explicitement pour Graph 90+E. x)

Pour l'erreur avec le switch, est-ce que tu penses pas qu'il y a une information super utile que tu pourrais inclure avec la question ?
Yannis300307 Hors ligne Membre Points: 50 Défis: 0 Message

Citer : Posté le 02/08/2022 17:56 | #


Pour l'erreur avec le switch, est-ce que tu penses pas qu'il y a une information super utile que tu pourrais inclure avec la question ?


/root/dev casio/Serialmo2/src/main.c:78:27: error: cast to union type from type not present in union


la partie de code est :
char text = 'B';
    gint_world_switch(GINT_CALL(Serial_WriteSingle, text));
Lephenixnoir Hors ligne Administrateur Points: 22452 Défis: 149 Message

Citer : Posté le 02/08/2022 18:02 | #


Pour les petits entiers il faut cast en int. C'est marqué dans le tuto... :x

Il y a quelques astuces pour utiliser plus de types :
Pour utiliser un char ou un short, castez en int et faites prendre un int à la fonction. Par exemple GINT_CALL(ma_fonction, (int)mon_char).
Yannis300307 Hors ligne Membre Points: 50 Défis: 0 Message

Citer : Posté le 02/08/2022 18:04 | #


Oui ça marche !! merci !
Yannis300307 Hors ligne Membre Points: 50 Défis: 0 Message

Citer : Posté le 10/08/2022 16:27 | #


Mon programme marchait mais pour je ne sais quelle raison sans que je ne change rien, il recrash comme avant ou ne veut pas ouvrir la connexion ...
Si qq a une idée ...

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2022 | Il y a 39 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd