gint : un noyau pour développer des add-ins
Posté le 20/02/2015 17:30
Ce topic fait partie de la série de topics du fxSDK.
En plus des options de programmation intégrée comme le Basic Casio ou Python, la plupart des calculatrices Casio supportent des
add-ins, des programmes natifs très polyvalents avec d'excellentes performances. Les add-ins sont généralement programmés en C/C++ avec l'aide d'un ensemble d'outils appelé SDK.
Plusieurs SDK ont été utilisés par la communauté avec le temps. D'abord le
fx-9860G SDK de Casio avec fxlib pour Graph monochromes (plus maintenu depuis longtemps). Puis le
PrizmSDK avec libfxcg pour Prizm et Graph 90+E (encore un peu actif sur Cemetech). Et plus récemment celui que je maintiens, le
fxSDK, dont gint est le composant principal.
gint est un unikernel, ce qui veut dire qu'il embarque essentiellement un OS indépendant dans les add-ins au lieu d'utiliser les fonctions de l'OS de Casio. Ça lui permet beaucoup de finesse sur le contrôle du matériel, notamment la mémoire, le clavier, l'écran et les horloges ; mais aussi de meilleures performances sur le dessin, les drivers et la gestion des interruptions, plus des choses entièrement nouvelles comme le moteur de gris sur Graph monochromes.
Les sources de gint sont sur la forge de Planète Casio :
dépôt Gitea Lephenixnoir/gint
Aperçu des fonctionnalités
Les fonctionnalités phares de gint (avec le fxSDK) incluent :
- Toutes vos images et polices converties automatiquement depuis le PNG, sans code à copier (via fxconv)
- Un contrôle détaillé du clavier, avec un GetKey() personnalisable et un système d'événements à la SDL
- Une bibliothèque standard C plus fournie que celle de Casio (voir fxlibc), et la majorité de la bibliothèque C++
- Plein de raccourcis pratiques, comme pour afficher la valeur d'une variable : dprint(1,1,"x=%d",x)
- Des fonctions de dessin, d'images et de texte optimisées à la main et super rapides, surtout sur Graph 90+E
- Des timers très précis (60 ns / 30 µs selon les cas, au lieu des 25 ms de l'OS), indispensables pour les jeux
- Captures d'écran et capture vidéo des add-ins par USB, en temps réel (via fxlink)
Avec quelques mentions spéciales sur les Graph monochromes :
Un moteur de gris pour faire des jeux en 4 couleurs !
La compatibilité SH3, SH4 et Graph 35+E II, avec un seul fichier g1a
Une API Unix/POSIX et standard C pour accéder au système de fichiers (Graph 35+E II seulement)
Et quelques mentions spéciales sur les Graph 90+E :
Une nouvelle police de texte, plus lisible et économe en espace
Le dessin en plein écran, sans les bordures blanches et la barre de statut !
Un driver écran capable de triple-buffering
Une API Unix/POSIX et standard C pour accéder au système de fichiers
Galerie d'add-ins et de photos
Voici quelques photos et add-ins réalisés avec gint au cours des années !
Arena (2016) — Plague (2021)
Rogue Life (2021)
Momento (2021)
Communication avec le PC (cliquez pour agrandir)
Utiliser gint pour développer des add-ins
Les instructions pour installer et utiliser gint sont données dans les divers tutoriels recensés dans le
topic du fxSDK. Il y a différentes méthodes de la plus automatique (GiteaPC) à la plus manuelle (compilation/installation de chaque dépôt). Le fxSDK est compatible avec Linux, Mac OS, et marche aussi sous Windows avec l'aide de WSL, donc normalement tout le monde est couvert
Notez en particulier qu'il y a des
tutoriels de développement qui couvrent les bases ; tout le reste est expliqué dans les en-têtes (fichiers
.h) de la bibliothèque que vous pouvez
consulter en ligne, ou dans les ajouts aux changelogs ci-dessous.
Changelog et informations techniques
Pour tester les fonctionnalités et la compatibilité de gint, j'utilise un add-in de test appelé gintctl (
dépôt Gitea Lephenixnoir/gintctl). Il contient aussi une poignée d'utilitaires d'ordre général.
Ci-dessous se trouve la liste des posts indiquant les nouvelles versions de gint, et des liens vers des instructions/tutoriels supplémentaires qui accompagnent ces versions.
Anecdotes et bugs pétés
Ô amateurs de bas niveau, j'espère que vous ne tomberez pas dans les mêmes pièges que moi.
TODO list pour les prochaines versions (2023-04-03)
gint 2.11
- Changements de contextes CPU. À reprendre du prototype de threading de Yatis pour permettre l'implémentation d'un véritable ordonnanceur. Demandé par si pour faire du threading Java.
- Applications USB. Ajouter le support de descripteurs de fichiers USB. Potentiellement pousser jusqu'à avoir GDB pour debugger.
- Support de scanf() dans la fxlibc. Codé par SlyVTT, plus qu'à nettoyer et fusionner.
Non classé
- Regarder du côté serial (plus facile que l'USB) pour la communication inter-calculatrices (multijoueur) et ultimement l'audio (libsnd de TSWilliamson).
- Un système pour recompiler des add-ins mono sur la Graph 90+E avec une adaptation automatique.
- Support des fichiers en RAM pour pouvoir utiliser l'API haut-niveau sur tous les modèles et éviter la lenteur de BFile à l'écriture quand on a assez de RAM.
Citer : Posté le 10/04/2024 19:37 | # | Fichier joint
Ce post sera dans les notes de publication de gint 2.11. @RDP
La fonctionnalité est actuellement disponible sur les branches dev du fxSDK et de gint.
Support élémentaire du debuggage à distance
Grâce à une contribution de Redoste (gint#27), nous avons maintenant la possibilité de debugger les add-ins gint à distance en utilisant GDB.
Pour l'instant fxlink est nécessaire donc le debuggage à distance n'est pas possible sous Windows/WSL.
Installation
Il vous faura mettre à jour gint ainsi que le fxSDK, et installer le nouveau dépôt Lephenixnoir/sh-elf-gdb qui fournit GDB pour la calculatrice.
% giteapc install Lephenixnoir/sh-elf-gdb
Note: Pour ceux qui ont déjà sh-elf-gdb parce qu'ils m'ont aidé à tester, je vous conseille de le désinstaller puis réinstaller : j'ai depuis ajouté un patch qui évite une erreur bizarre quand on debugge depuis Add-In Push.
Utilisation sur la calculatrice
Pour que le debugger soit utile il faut compiler avec les infos de debug activées, c'est à dire avec l'option -g. C'est fait par défaut dans les nouveaux projets avec la nouvelle version du fxSDK, mais pour les projets existants il faut l'ajouter manuellement dans le target_compile_options() de CMakeLists.txt :
Le debugger démarre automatiquement lorsqu'une exception se produit après que vous ayez appelé la fonction gdb_start_on_exception(), typiquement au début de votre main(). L'appel de cette fonction est ce qui cause l'inclusion du code approprié dans votre add-in.
int main(void)
{
gdb_start_on_exception();
/* ... */
}
Ce démarrage automatique est très utile si un crash se produit mais que vous ne l'attendiez pas : lorsque vous voyez le crash, vous pouvez brancher la calculatrice et commencer à debugger.
Par contre, ça ne permet pas de préconfigurer le programme (e.g. pour mettre des breakpoints avant de commencer l'exécution). Pour ça, vous pouvez simplement créer une exception passagère avec trapa au début de main().
{
gdb_start_on_exception();
/* Forcer une exception pour ajouter un breakpoint */
__asm__("trapa #42");
/* ... */
}
Indicateurs visuels du processus de debuggage à distance
Pour ne pas se perdre (et diagnostiquer tout potentiel bug avec le système), le debugger à distance affiche des icônes en haut à droite de l'écran.
De haut en bas :
Le plus important est que lorsque le debuggage à distance avec GDB est activé, il n'y a plus d'écran System ERROR. Et donc un crash se verra uniquement à la présence d'un indicateur visuel en haut à droite de l'écran. Ils sont petits surtout sur la Graph 90+E donc faites attention.
Utilisation sur le PC
Avant ou après que la calculatrice n'initie la connexion à GDB du fait d'un crash, lancez GDB sur l'ordinateur à l'aide du wrapper fxsdk gdb.
Les arguments de fxsdk gdb sont les mêmes que ceux de la commande gdb classique, et en particulier vous devez spécifier le nom du fichier ELF que vous êtes en train d'exécuter sur la calculatrice. Typiquement c'est build-*/myaddin. Attention à bien sélectionner build-cg-push si vous envoyez votre add-in avec Add-In Push parce que ce n'est pas le même ELF.
La différence entre fxsdk gdb et sh-elf-gdb directement est que le premier démarre automatiquement un bridge qui permet de communiquer avec la calculatrice et lance ensuite GDB en mode debuggage à distance. (L'option --bridge-only permet de ne démarrer que le bridge, si vous connaissez bien GDB et que vous voulez voir passer les paquets échangés.)
En gros c'est tout ce qu'il y a à faire, mais pour ne pas vous laisser sans détail sur GDB voilà quand même quelques explications de base sur son utilisation.
Exemples d'utilisation
Je pars du programme suivant, qui a pour bug évident qu'un pointeur invalide s'est retrouvé dans le tableau avec la liste des entrées du menu.
#include <gint/keyboard.h>
#include <gint/gdb.h>
void draw_menu(void)
{
const char *entries[5] = {
"Play", "Settings", "Credits", "Quit", (char *)0x14141414
};
for(int i = 0; i < 5; i++)
dtext(4, 4+12*i, C_BLACK, entries[i]);
}
int main(void)
{
gdb_start_on_exception();
dclear(C_WHITE);
draw_menu();
dupdate();
getkey();
return 0;
}
J'ai remarqué un crash tout à l'heure donc j'ai rajouté l'include ainsi que l'appel à la fonction gdb_start_on_exception() au début du programme. Je le lance sur ma Graph 90+E, et j'obtiens la pastille bleue. Je lance donc GDB sur le PC :
[19:26] calculators: waiting for calculator to connect...
[19:26] calculators 001:103: successfully claimed interface!
[19:26] socket: waiting for client on "/tmp/fxsdk-gdb-bridge-001-103.socket"...
Reading symbols from build-cg-push/myaddin...
The target architecture is set to "sh4al-dsp".
Remote debugging using /tmp/fxsdk-gdb-bridge-001-103.socket
0x8c202ecc in dtext_utf8_next (str_pointer=0x8c1dff40) at /home/el/Projects/gint/src/render/topti.c:59
59 uint8_t lead = *str++;
(gdb)
Les quelques messages commençant par "[19:26]" sont affichés par le bridge qui gère la connexion à la calculatrice, le reste est ensuite affiché par GDB. La partie qui nous intéresse commence à 0x8c202ecc, elle nous indique :
Et ensuite le prompt, "(gdb)". Clairement le crash s'est produit dans une fonction de gint, mais ce n'est pas forcément un bug dans gint ; on a peut-être mal appelé une fonction. La commande backtrace (raccourci "bt") affiche la série d'appels par laquelle on est arrivés au niveau du crash.
#0 0x8c202ecc in dtext_utf8_next (str_pointer=0x8c1dff40) at /home/el/Projects/gint/src/render/topti.c:59
#1 0x8c20347c in topti_render (size=-1, bg=-1, fg=0, f=0x8c20d2b0, str_char=0x14141414 <error: Cannot access memory at address 0x14141414>, y=52, x=4) at /home/el/Projects/gint/src/render-cg/topti.c:84
#2 dtext_opt (x=4, y=<optimized out>, fg=0, bg=-1, halign=0, valign=0, str=0x14141414 <error: Cannot access memory at address 0x14141414>, size=-1) at /home/el/Projects/gint/src/render-cg/topti.c:140
#3 0x8c202df2 in dtext (x=<optimized out>, y=<optimized out>, fg=<optimized out>, str=<optimized out>) at /home/el/Projects/gint/src/render/dtext.c:6
#4 0x8c200264 in draw_menu () at /home/el/Programs/tmp/gint-remote-debugging-example/src/main.c:12
#5 0x8c2002c4 in main () at /home/el/Programs/tmp/gint-remote-debugging-example/src/main.c:20
Vous pouvez voir pour chaque fonction son nom, ses paramètres, et le fichier source associé, et on remonte jusqu'à main() et draw_menu(), les fonctions de notre programme source.
Notez que pas mal de paramètres sont "<optimized out>" : c'est le résultat du fait que le compilateur a optimisé le programme et donc certaines variables ont sauté, et certains bouts de code auront sauté aussi d'ailleurs. Ça vous complique un peu la tâche. Si vous y tenez vous pouvez compiler avec -O0 ce qui vous donnera des informations de debug de meilleure qualité, par contre la taille de l'add-in et les perfs vont en prendre un sacré coup.
Plus important encore, vous remarquez qu'il y a un paramètre pour lequel il est écrit <error: Cannot access memory at address 0x14141414>, et ça déjà ça nous révèle qu'on a un pointeur invalide qui se balade dans le programme.
Ça se verra encore mieux si on inspecte les variables locales de la fonction dtext_utf8_next() qui a planté avec la commande info locals.
str = 0x14141415 <error: Cannot access memory at address 0x14141415>
lead = <optimized out>
n2 = <optimized out>
n3 = 253 '\375'
n4 = <optimized out>
Vous ne connaissez pas forcément le code de cette fonction interne de gint mais on peut se douter que str est une chaîne de caractères. Et le pointeur est bien invalide : vous pouvez le vérifier en essayant d'afficher ses contenus avec la commande print qui peut afficher à peu près n'importe quelle expression C.
Cannot access memory at address 0x14141415
J'en profite pour mentionner que les expressions qu'on évalue sont interprétées dans le contexte de la fonction dtext_utf8_next(). Pour inspecter les variables locales d'une autre fonction listée par bt et faire des calculs sur les valeurs associées, il faut d'abord sélectionner la fonction avec la commande frame suivi du numéro affiché par bt (par exemple frame 3 pour monter dans la fonction dtext()).
Normalement à ce stade on irait plutôt essayer de comprendre d'où le pointeur vient, mais pour s'amuser un peu et montrer les fonctionnalités cool implémentées par Redoste supposons qu'on veut continuer l'exécution en contournant l'erreur. On peut aller chercher l'instruction exacte qui a planté en affichant le code autour de la valeur $pc (x c'est "examine" pour regarder la mémoire, 3i demande 3 instructions, et pc est l'adresse de l'instruction qui a planté).
=> 0x8c202ecc <dtext_utf8_next+6>: mov.b @r6+,r1
0x8c202ece <dtext_utf8_next+8>: extu.b r1,r1
0x8c202ed0 <dtext_utf8_next+10>: mov r1,r0
Ici c'est donc r6 qui contient le pointeur invalide, ce qu'on peut confirmer avec info registers.
r0 0xb 11
r1 0x0 0
(...)
r6 0x14141414 336860180
(...)
r15 0x8c1dff10 0x8c1dff10
pc 0x8c202ecc 0x8c202ecc <dtext_utf8_next+6>
pr 0x8c20347c 0x8c20347c <dtext_opt+212>
(...)
Pour contourner l'erreur d'accès mémoire, je peux assigner une valeur factice à r1 (un caractère de fin de chaîne, donc la valeur 0) puis placer pc sur l'instruction d'après :
(gdb) set $pc = 0x8c202ece
Ensuite je continue l'exécution. Ici on ne peut pas utiliser la commande continue habituelle parce que sinon GDB enverrait à l'add-in la segfault qu'il était sur le point de se prendre (et le programme s'arrêterait, vous ramenant au menu principal). Il faut être plus explicite et demander de continuer sans signal avec la commande signal 0.
Continuing with no signal.
Le programme continue et se termine normalement. Voilà pour une première démo.
Maintenant, je recommence mais cette fois je vous montre comment on peut insérer un breakpoint et surveiller l'exécution avant que le bug ne se produise pour voir où ça part en vrille. D'abord on va forcer un arrêt avant que le bug ne se produise en ajoutant un petit trapa dans main() :
{
gdb_start_on_exception();
__asm__("trapa #42");
dclear(C_WHITE);
draw_menu();
/* ... */
}
Et cette fois le programme a une erreur dès l'entrée dans main(), ce qu'on voit dans GDB.
[23:18] calculators: waiting for calculator to connect...
[23:18] calculators 001:024: successfully claimed interface!
[23:18] socket: waiting for client on "/tmp/fxsdk-gdb-bridge-001-024.socket"...
Reading symbols from build-cg-push/myaddin...
The target architecture is set to "sh4al-dsp".
Remote debugging using /tmp/fxsdk-gdb-bridge-001-024.socket
main () at /home/el/Programs/tmp/gint-remote-debugging-example/src/main.c:20
20 dclear(C_WHITE);
On place alors un breakpoint. La commande habituelle pour faire ça dans GDB est break (raccourci "b"), mais ça vous donne un "breakpoint logiciel", et sans rentrer dans les détails on ne supporte que les "breakpoints matériels". Donc il faut utiliser la commande hbreak (raccourci "hb") à la place. Attention, si vous utilisez b ça risque de ne pas vous donner d'erreur (sur Graph 90+E avec Add-In Push) mais le breakpoint ne marchera pas.
Hardware assisted breakpoint 1 at 0x8c202ddc: file
/home/el/Projects/gint/src/render/dtext.c, line 6.
(gdb) c
Continuing.
Breakpoint 1, dtext (x=4, y=4, fg=0, str=0x8c20c0d0 "Play") at /home/el/Projects/gint/src/render/dtext.c:6
6 dtext_opt(x, y, fg, C_NONE, DTEXT_LEFT, DTEXT_TOP, str);
En spécifiant hb dtext j'indique à GDB que je veux m'arrêter chaque fois qu'on rentre dans la fonction dtext(). Une fois le breakpoint placé je reprends l'exécution avec la commande continue (raccourci "c").
Le programme s'arrête ensuite puisque le breakpoint est atteint, et vous pouvez voir aux paramètres qu'on est dans le premier appel, sur le point d'afficher le texte "Play". Je continue encore, et en spécifiant 4 en paramètre à continue j'indique que je veux sauter les 3 prochaines occurrences de ce breakpoint.
Will ignore next 3 crossings of breakpoint 1. Continuing.
Breakpoint 1, dtext (x=4, y=52, fg=0, str=0x14141414 <error: Cannot access memory at address 0x14141414>)
at /home/el/Projects/gint/src/render/dtext.c:6
6 dtext_opt(x, y, fg, C_NONE, DTEXT_LEFT, DTEXT_TOP, str);
Avec ça je me retrouve à l'arrêt au début de l'exécution du dtext() fatidique qui va nous créer le crash ; vous pouvez voir qu'on retrouve le pointeur invalide dans le paramètre str. Notez qu'à ce stade la segfault ne s'est pas encore produite !
Pour progresser plus lentement dans l'exécution, on peut utiliser la commande step (raccourci "s") pour avancer une ligne de code à la fois. Ici j'exécute la commande plusieurs fois à la suite, et vous pouvez voir qu'on descend dans les fonctions de rendu de texte de gint doucement mais sûrement.
dtext_opt (x=4, y=52, fg=0, bg=-1, halign=0, valign=0, str=0x14141414 <error: Cannot access memory at address 0x14141414>, size=-1)
at /home/el/Projects/gint/src/render-cg/topti.c:129
129 if(halign != DTEXT_LEFT || valign != DTEXT_TOP)
(gdb) s
140 topti_render(x, y, str, topti_font, fg, bg, size);
(gdb) s
topti_render (size=<optimized out>, bg=<optimized out>, fg=<optimized out>, f=<optimized out>, str_char=<optimized out>,
y=<optimized out>, x=<optimized out>) at /home/el/Projects/gint/src/render-cg/topti.c:140
140 topti_render(x, y, str, topti_font, fg, bg, size);
(gdb) s
63 if(x >= dwindow.right || y >= dwindow.bottom) return;
(gdb) s
64 if(y + height <= dwindow.top) return;
Je vous passe quelques étapes parce qu'il y a encore pas mal de lignes avant qu'on atteigne le crash ; je continue sans m'arrêter avec continue.
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x8c202ecc in dtext_utf8_next (str_pointer=0x8c1dff40) at /home/el/Projects/gint/src/render/topti.c:59
59 uint8_t lead = *str++;
Et là on retrouve le crash. Vous pouvez voir que cette fois il y a un message "Program received... Segmentation fault". Pour des raisons techniques ce message n'est pas affiché au tout premier arrêt quand vous lancez fxsdk gdb, mais vous pouvez connaître la raison de l'arrêt avec info program.
Dans tous les cas, on a bien compris d'où vient le bug maintenant, donc on peut arrêter le programme. On pourrait continue à ce stade, auquel cas GDB enverrait la segfault à l'add-in qui s'arrêterait tout seul (retour au menu), mais on peut aussi utiliser la commande kill (raccourci "k") qui est plus explicite et produit le même effet. Vous pouvez vous en servir pour quitter l'add-in à tout moment pendant une session de debuggage.
Kill the program being debugged? (y or n) y
[Inferior 1 (Remote target) killed]
(gdb) %
Limitations
Les seules choses qui ont été testées sont les suivantes :
Les breakpoints logiciels ne sont pas supportés pour l'instant donc pour mettre un breakpoint sur une fonction en RAM il faut nécessairement utiliser la commande hbreak et non break. On ne supporte qu'un ou deux breakpoints selon les cas, et on ne le dit pas vraiment à GDB, donc si vous en mettez plus ils risquent de ne pas marcher sans raison (i.e. le programme passe sur un breakpoint mais il ne s'arrête pas pour communiquer avec le debugger).
Normalement il ne doit pas y avoir de cas où le programme freeze et vous n'avez pas le contrôle sur le debugger pour pouvoir le kill. Si ça se produit (et que c'est pas une boucle infinie dans votre code) faites-moi signe.
Voilà voilà, enjoy! o/
Citer : Posté le 10/04/2024 20:07 | #
Ca donne envie de faire passer KhiCAS du prizmsdk vers gint ... si Casio revient sur la fermeture de ses prochaines calcs.
Est-ce qu'on peut appeler une fonction/méthode sur la calc depuis la console de gdb? Par exemple, si j'ai une variable g de type giac::gen qui a une méthode dbgprint(), puis-je écrire p g.dbgprint()? (je n'ai pas réussi à faire marcher ce genre de choses en utilisant gdb sur l'émulateur casio avec la dll patchée pour le support gdb).
Citer : Posté le 11/04/2024 07:54 | #
Excellent ! C’est vraiment cool de voir ce genre d’avancées sur gint, et vraiment utile
Bravo !!
Petit détail : est ce que ça ne serait pas plus simple d’ajouter une macro du genre gdb_breakpoint() qui appelle elle-même le trapa ? Peut-être plus explicite
Citer : Posté le 11/04/2024 09:10 | #
Ca donne envie de faire passer KhiCAS du prizmsdk vers gint ... si Casio revient sur la fermeture de ses prochaines calcs.
On croise les doigts.
Ah ça c'est une bonne question ! Je n'y avais pas pensé. On peut exécuter du code oui (genre appeler une fonction), je vais voir ce soir si on peut renvoyer du texte à GDB.
Petit détail : est ce que ça ne serait pas plus simple d’ajouter une macro du genre gdb_breakpoint() qui appelle elle-même le trapa ? Peut-être plus explicite
Pour l'instant je l'ai pas fait parce que c'est pas la façon "propre" de faire ; en principe GDB devrait avoir la main avant que le programme se lance quand on veut ajouter des breakpoints. En attendant de voir si je peux faire marcher ça proprement je préfère laisser ce "hack" visible.
Citer : Posté le 11/04/2024 10:02 | #
Ah ça c'est une bonne question ! Je n'y avais pas pensé. On peut exécuter du code oui (genre appeler une fonction), je vais voir ce soir si on peut renvoyer du texte à GDB..
C'est très utile pour moi, car l'affichage par p d'une variable de type gen est peu infomative (sauf si c'est un petit entier), et j'ai une macro dans mon .gdbinit :
define v
print ($arg0).dbgprint()
end
qui me permet d'afficher un gen de manière user-friendly en tapant v g (par exemple a+b si g est un gen de type symbolique)
Ca peut intéresser n'importe quel projet qui a une structure avec une méthode dbgprint() pour l'afficher.
Citer : Posté le 11/04/2024 10:03 | #
Carrément, j'ai vraiment envie d'avoir cette possibilité maintenant. xD
Citer : Posté le 12/04/2024 09:08 | #
Update : ça progresse et ça va marcher je pense, j'arrive à rediriger stderr pour que ça affiche dans GDB. D'abord il faut demander à gint de rediriger soit stdout soit stderr soit les deux (ici juste stderr) :
gdb_redirect_streams(false, true);
Le second appel a pour effet que tout affichage dans stderr sera passé à la console GDB ensuite. Dans gintctl j'ai une fonction comme ceci :
{
fprintf(stderr, "debug=%d\n", 73);
}
Dans le log ci-dessous, je crée volontairement une erreur (avec le trapa #42) pour lancer GDB. Ensuite je fais mon appel, et le seul problème pour l'instant c'est que la calto ne s'arrête pas après l'appel (le breakpoint placé à la fin du call par GDB n'a pas dû marcher). Donc je quitte brutalement.
95 __asm__("trapa #42");
(gdb) call gintctl_gdb_dbgprint()
debug=73
[Inferior 1 (Remote target) exited normally]
The program being debugged exited while in a function called from GDB.
Evaluation of the expression containing the function
(gintctl_gdb_dbgprint) will be abandoned.
Citer : Posté le 12/04/2024 12:01 | #
Désolé de pas trop être présent en ce moment, mais je suis avec attention les avancées du debug dans fxSDK/gint. Ca me fait ma détente de la journée de voir les trucs sympas qui avancent après mes journées de m__de du moment :D.
Bravo @Lephenixnoir et @Redoste, c'est vraiment un boulot fantastique que vous faites sur ce sujet qui va vraiment aider la communauté.
Ca va clairement révolutionner le game au niveau du développement car le debuf au printf() c'est bof au bout d'un moment !!! Ca offre des perspectives vraiment hyper intéressantes pour aller gratter dans les fonctions.
Je serai curieux de savoir si on sait "connecter" ça avec une IU (peut être directement dans VSCode d'ailleurs) afin de rendre le truc un peu plus convivial (j'avoue que GDB, je trouve un peu austère )
Encore une fois bravo à vous.
Citer : Posté le 12/04/2024 12:35 | #
gdb tout seul c'est spartiate, mais gdb dans emacs je trouve ça génial!
Citer : Posté le 12/04/2024 13:59 | #
Merci Bernard, faudra que j'essaie, je n'ai jamais regardé emacs pour cet usage.
Quand j'étais plus jeune j'adorais DDD mais hélas ce frontend est tombé en désuétude faute de support actif. Je le trouvais vraiment top.
Je pensais à un truc, du coup on a une version des libs compilées avec -g pour pouvoir pousser le debug jusqu'aux fonctions de gint/fxlibc ou c'est pas la peine ?
Citer : Posté le 12/04/2024 14:02 | #
gint est compilé avec -g oui, sinon tu pourrais pas voir dtext_utf8_next() dans l'exemple.
Citer : Posté le 12/04/2024 14:48 | #
Bein oui, j'suis con, effectivement
Bien vu
Un peu cérébralement surchargé le Sly en ce moment ...
Citer : Posté le 12/04/2024 18:21 | #
Les infos de débug ne prennent pas de place dans l'exécutable Casio, donc il n'y a pas trop de raison de ne pas les garder.
Sinon gdb dans emacs, ça reste très ligne de commande, pas du tout comme le debugger de visual studio (ddd si je me souviens bien c'était graphique mais on avait accès facilement à la console gdb). L'intérêt principal pour moi c'est de pouvoir relancer le prog avec les mêmes arguments juste en tapant r, faire du ligne à ligne avec n ou s, changer de frame avec f (et bt), taper des v noms de variables (ça c'est très difficile à réaliser dans les debugger graphiques sans console) et pouvoir modifier le source directement depuis la fenêtre de debug.
Citer : Posté le 12/04/2024 18:49 | #
Pour info pour l'instant run y'a pas et modifier les sources je doute que ça marche, mais sinon n/s/f/bt ça marche.
Citer : Posté le 12/04/2024 19:37 | #
Je suis en train de faire le tuto, ça marche trop bien !!!
Franchement c'est la classe, bravo !!
Citer : Posté le 12/04/2024 20:25 | #
Pour info pour l'instant run y'a pas et modifier les sources je doute que ça marche, mais sinon n/s/f/bt ça marche.
ah oui, je parlais du code natif de Xcas sur PC, ou du simulateur Numworks.
Pour la Casio, vu que ça nécessite un changement de SDK pour KhiCAS, j'attends de voir si Casio remet les addins et de l'espace de stockage.
Citer : Posté le 13/04/2024 09:23 | #
Pour la Casio, vu que ça nécessite un changement de SDK pour KhiCAS, j'attends de voir si Casio remet les addins et de l'espace de stockage.
Naturellement... sans compter que gint prend un peu de place aussi ce qui reposerait la question de la taille. Tu m'as juste rappelé que je parlais jamais de run qui est une commande classique donc je voulais préciser.
Sinon j'ai progressé sur la question des appels type dbgprint(). Pour les add-ins classiques (chargés en ROM) ça marchait déjà très bien. Pour les add-ins en RAM (Add-in Push) j'avais le problème décrit dans ce message parce que GDB voulait mettre un breakpoint logiciel, i.e. en modifiant le code, et on ne le supportait pas encore. Finalement il suffit de purger les deux caches quand on modifie le code et de réajuster PC après un breakpoint logiciel pour que GDB comprenne bien où on est.
Du coup, ça marche !
95 __asm__("trapa #42");
(gdb) call gintctl_gdb_dbgprint()
debug=73
(gdb)
Citer : Posté le 13/04/2024 13:53 | #
Pour la Casio, vu que ça nécessite un changement de SDK pour KhiCAS, j'attends de voir si Casio remet les addins et de l'espace de stockage.
Naturellement... sans compter que gint prend un peu de place aussi ce qui reposerait la question de la taille.
Oui, ça ne passerait pas avec l'addin version courte de KhiCAS où il ne reste que quelques centaines d'octets libres. Par contre avec la version longue en addin+overlay, ça ne causerait pas de soucis, sous réserve que l'espace de stockage revienne à une valeur décente sur la math+/fxcg100.
Du coup, ça marche !
Bravo! Je garde ça en mémoire, pour l'instant béni où Casio aura enfin la révélation et remettra les addins et au moins 8Mo d'espace en flash.
Citer : Posté le 06/07/2024 10:24 | #
Nouvelle version : gint 2.11.0
Release associée du fxSDK : fxSDK 2.11.0
Release associée de la fxlibc : fxlibc 1.5.1
⚠️ Vous devez réinstaller les libs et recompiler vos add-ins avec -B. Instructions dans l'annonce fxSDK.
Première mise à jour en plus d'un an (faut que me réveille !), y'a des choses à dire.
Changements majeurs :
Changements mineurs :
En interne, pas mal de petits changements visant à consolider le support de différentes plateformes (mono, G90, mono pour G90, CP400) ce qui donnera lieu à des changements dans la prochaine version majeure... gint 3.
Citer : Posté le 07/07/2024 21:23 | #
Yo, plein de nouveautés qui poppent !!!
Cool.
Je suis intrigué par cette phrase mystère :
Début de support prototype de la CP400 avec HollyHock-2 pour charger les programmes.
Késako ?
J'ai pu tester un tout petit peu le débug avec GDB, c'est vraiment top. ça va vraiment beaucoup aider.
Citer : Posté le 07/07/2024 21:27 | #
Il y a des gens qui développement sur ClassPad, avec un chargeur qui s'appelle HollyHock-2. C'est encore un peu flou pour moi mais j'ai commencé à jouer avec. Je pense pas que ça touche grand monde sur Planète Casio, vu que... ben personne a de ClassPad ici. ó_ó
Je suis preneur de retours d'expérience ici parce que c'est une fonctionnalité que je vais probablement pas utiliser énormément. Les trucs mondains j'arrive généralement à ne pas les écrire buggés si je suis réveillé (j'en écris pas tant que ça), et les bugs subtils avec gint ils vont de toute façon péter le debugger aussi.