Posté le 10/05/2023 13:16
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 35 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
Citer : Posté le 11/05/2023 19:06 | #
Je suis pas assez calé hardware pour donner une critique, mais ce n'est pas si simple.
La Numworks est idéal pour le Python ; La G90 supporte Python et à Python extra. Mais je ne recommanderai pas une G90 pour une personne qui veut coder en Python.
La G90 est une plate-forme super pour le gaming et pour créer des jeux/utilitaires. La Numworks, moins voir pas du tout.
Bref, je vais pas vous pondre un pavé, c'est compliqué quoi. Ça dépend du ou des besoins.
Citer : Posté le 11/05/2023 20:29 | #
Je ne suis pas d'accord, je trouve que la Numworks est loin d'être idéale pour faire du Python. D'abord il y a vraiment trop peu de tas disponible. Et mon port de MicroPython pour la CG90 (micropy) a plus de modules que celui de Numworks, on peut tester si la syntaxe est correcte directement dans l'éditeur, il y a du parenthese matching, ...
Citer : Posté le 23/05/2023 17:44 | #
Il y a du nouveau depuis la coupure pour ceux qui ne suivent pas l'actualité sur tiplanet.
Mon port d'Upsilon pour Casio permet maintenant la sauvegarde de l'état, y compris l'historique des calculs, et la possibilité d'échanger avec le système de fichiers hote:
https://www-fourier.univ-grenoble-alpes.fr/~parisse/casio/upsilon.g3a
Citer : Posté le 26/05/2023 10:51 | #
Une chose que j'aimerais rajouter dans ce port, c'est la possibilité d'appeler des fonctions de giac depuis Upsilon. L'idée serait d'avoir un fichier binaire linké en 0x8c200000 qui serait chargé par Upsilon en RAM, et qui contient la fonction
const char * run_caseval(const char *);
qui s'occupe de faire l'évaluation par giac d'une chaine provenant d'Upsilon (par exemple quand on valide une ligne de commande dans l'appli Calculs).
Mais il faut que je puisse repérer l'adresse de run_caseval dans le binaire, et je n'arrive pas à voir comment écrire le script de ld pour ça.
J'ai créé un fichier giacmain.cc qui contient seulement une table avec l'adresse du pointeur à appeler:
const char * run_caseval(const char * s);
extern const unsigned caseval_ptr[];
const unsigned caseval_ptr[]={
(unsigned) run_caseval,
};
J'ai essayé le script ci-dessous (en m'inspirant du script pour khicas en 2 addins), mais caseval_ptr n'est pas du tout au début de la zone, il est en 8c3c8da0 . Comment faire? Merci d'avance!
OUTPUT_FORMAT(elf32-sh)
OUTPUT_ARCH(sh3)
ENTRY(initialize)
MEMORY
{
/* Loads code at 300000, skips g3a header */
/* rom (rx) : o = 0x00300000, l = 2M-32000 */
/* RAM is available at 0x8c200000, 3M maybe more */
/* use emu.ld for emulator since it's at 0x88200000 */
r8c2 (rx) : o = 0x8c200000, l = 1K
r8c2p (rx) : o = 0x8c200000+1K, l = 2048K-1K
ram (rwx) : o = 0x8c400000, l = 256k /* skip 4k at start */
}
SECTIONS
{
/* Code, in ROM */
.giacmain : {
giacmain*.o(.rodata)
giacmain*.o(.rodata.*)
} > r8c2
.text : {
*(.pretext)
*(.text)
*(.text.*)
} > r8c2p
/* Read-only data, in ROM */
.rodata : {
*(.rodata)
*(.rodata.*)
} > r8c2p
/* RW initialized data, VMA in RAM but LMA in ROM */
.data : ALIGN(4) {
_datald = LOADADDR(.data) ;
_sdata = . ;
*(.data)
*(.data.*);
_edata = . ;
} >ram AT>r8c2p
/* Uninitialized data (fill with 0), in RAM */
.bss ALIGN(4) : ALIGN(4) {
_bbss = . ;
*(.bss)
*(.bss*)
*(COMMON)
_ebss = . ;
/* Extra unused static space */
_sextra = ALIGN(32);
_eextra = ORIGIN(ram) + LENGTH(ram);
} >ram
/DISCARD/ : {
*(.debug_*) ;
*(.comment) ;
}
}
Citer : Posté le 26/05/2023 11:08 | #
Tu peux supprimer le tableau du code source et juste le créer dans le linker script. Tu vas dans la première section qui est stockée dans r8c2 (le premier bout qui finit par > r8c2) et tu y mets un LONG avec le symbole. Par exemple, si la première section dans r8c2 est un .text :
LONG(run_caseval);
/* Tu peux mettre d'autres valeurs si tu veux */
*(.text .text.*)
/* ... */
} > r8c2
Du coup l'adresse de run_caseval() sera stockée à 0x8c200000. Attention pas la fonction, juste son adresse. De tête ça devrait donner ça :
run_caseval_function **f = (void *)0x8c200000;
(*f)("1+2");
Citer : Posté le 27/05/2023 13:07 | #
Merci pour ton aide précieuse. Malheureusement j'ai une erreur
calc.ld:21: undefined symbol run_caseval referenced in expression
si je fais
SECTIONS
{
/* Code, in ROM */
.text : {
LONG(run_caseval)
*(.pretext)
*(.text)
*(.text.*)
} > r8c2p
...
Si j'enlève run_caseval, ça marche.
Bon pour le moment je vais adopter la solution transitoire suivante: utiliser main comme point d'entrée pour récupérer l'adresse de run_caseval, mais aussi pour initialiser le binaire (data et bss), de toutes façons il faut bien le faire. C'est d'ailleurs quelque chose qu'il faudrait aussi faire pour KhiCAS en 2 morceaux, le 2ème morceau doit aussi être initialisé explicitement, et c'est ce qui explique peut-être un problème étrange que j'avais évoqué avec un problème d'initialisation du code 3d.
Voilà ce que donne le début du dump, sans rien faire de spécial:
8c200000 g .text 00000000 initialize
8c200000 l d .text 00000000 .text
8c20000c l .text 00000000 dataLoop
8c200018 l .text 00000000 dataDone
8c20001e l .text 00000000 bssLoop
8c200028 l .text 00000000 bssDone
8c20003e l .text 00000000 GlibAddinAplExecutionCheck
8c200050 l .text 00000000 main
8c200054 l .text 00000000 v_syscall
8c200058 l .text 00000000 v_datald
8c20005c l .text 00000000 v_edata
8c200060 l .text 00000000 v_sdata
8c200064 l .text 00000000 v_ram_bbss
8c200068 l .text 00000000 v_ram_ebss
8c20006c g F .text 0000000c .hidden bool giac::m_lex_is_strictly_greater<giac::gen>(giac::monomial<giac::gen> const&, giac::monomial<giac::gen> const&)
...
à priori l'adresse de main sera toujours à l'adresse 8c200050 (j'ai essayé de remplacer ENTRY(initialize) par ENTRY(main) dans le script du loader mais ça ne marche pas). Et mon main est dans le code ci-dessous, donc son appel devrait permettre de localiser la fonction run_caseval
extern "C" const char * run_caseval(const char * s);
extern const unsigned caseval_ptr[];
const unsigned caseval_ptr[]={
(const unsigned) run_caseval,
};
extern "C" unsigned * datald,*sdata,*edata,*bbss,*ebss;
// data provided by linker script
// main should be called once at binary load time
__attribute__((noinline)) int main(){
// init the binary file and return address of the syscall table
// this is done by initialize in an addin, but here we must do it explicitly
unsigned * src=datald,*target=sdata;
for (;target<edata;++src,++target)
*target=*src;
for (target=bbss;target<ebss;++target)
*target=0;
return (int) caseval_ptr;
}
Citer : Posté le 27/05/2023 13:43 | #
Oups, j'ai écrit un peu vite et oublié que les symboles ont un underscore en plus sur cette plateforme.
Tu ne seras pas surpris de savoir que je déconseille fortement d'hardcoder les adresses puisque là tu as deux fichiers différents et ton linker script n'impose l'ordre d'aucune section à part la toute première (dans laquelle main n'est pas)
Citer : Posté le 27/05/2023 14:52 | #
Effectivement en ajoutant le _ ca compile, mais je ne récupère pas l'adresse de run_caseval, le hexdump me donne 0000 0000. Ca marche pour main par contre, donc je vais faire avec LONG(_main) en premier, en étant ainsi assuré que l'offset de lecture de main ne bougera pas.
Citer : Posté le 05/06/2023 17:35 | #
J'ai un peu avancé, mais je bloque pour l'initialisation de l'overlay, car edata et sdata contiennent 0 dans le code de main
__attribute__((noinline)) int main(){
unsigned * src=datald; unsigned *target=sdata;
for (;target<edata;++src,++target)
*target=*src;
for (target=bbss;target<ebss;++target)
*target=0;
...
En regardant un extrait du dump des symboles et le hexdump de l'overlay, il semble que c'est la valeur de v_datald, v_edata et v_sdata, v_ram_bbss et v_ram_ebss qu'il me faut utiliser, mais comment on les adresse depuis C vu qu'il n'y a pas de _ devant le v? (evidemment je pourrais utiliser des adresses absolues, mais c'est mal...).
Ou bien on peut peut-être appeler initalize qui a l'air de faire l'initialisation, mais je ne sais pas à quoi correspond GlibAddinAplExecutionCheck
8c200010 g .text 00000000 initialize
8c20001c l .text 00000000 dataLoop
8c200028 l .text 00000000 dataDone
8c20002e l .text 00000000 bssLoop
8c200038 l .text 00000000 bssDone
8c20004e l .text 00000000 GlibAddinAplExecutionCheck
8c200060 l .text 00000000 main
8c200064 l .text 00000000 v_syscall
8c200068 l .text 00000000 v_datald
8c20006c l .text 00000000 v_edata
8c200070 l .text 00000000 v_sdata
8c200074 l .text 00000000 v_ram_bbss
8c200078 l .text 00000000 v_ram_ebss
...
8c3cfbbc g *ABS* 00000000 datald
8c3e0000 g .data 00000000 sdata
...
8c3e03e4 g .bss 00000000 bbss
8c3e03e4 g .data 00000000 edata
8c3e03e4 l d .bss 00000000 .bss
...
8c40ed88 g .bss 00000000 ebss
Le début de l'hexdump de l'overlay (les 16 premiers octets contiennent l'adresse de la table contenant caseval et 31415927 qui me sert de marqueur qu'il s'agit bien de l'overlay giac et pas d'un fichier quelconque renommé).
0000000 3a8c 0062 4131 2759 0000 0000 0000 0000
0000010 e62f 224f 462f 14d0 15d2 14d3 3232 0389
0000020 0661 1222 faaf 0472 13d2 12d3 00e1 3632
0000030 028b 0900 fbaf 1422 536e 01e6 00e4 06b0
0000040 6365 07d7 ed65 f665 264f 2b47 f66e 05d2
0000050 2b42 29e0 0000 0000 0000 0000 0000 0000
0000060 3a8c 0062 0280 7000 3c8c bcfb 3e8c e403
0000070 3e8c 0000 3e8c e403 408c 88ed 01d0 2b40
...
Merci d'avance si tu as une piste!
Citer : Posté le 05/06/2023 19:28 | #
Hello, la "valeur" du symbole correspond à l'adresse de la "variable" associée. Donc pour
Tu dois faire
uint32_t x = (uint32_t)&datald;
/* x = 0x8c3cfbbc */
Et tu as aussi besoin de l'appeler _datald vu que le compilateur C met un underscore devant tous les noms de variables quand il nomme les symboles (sur cette plateforme).
Citer : Posté le 06/06/2023 08:05 | #
Oui, c'est fait comme ça dans le fichier de ld
/* RW initialized data, VMA in RAM but LMA in ROM */
.data : ALIGN(4) {
_datald = LOADADDR(.data) ;
_sdata = . ;
*(.data)
*(.data.*);
_edata = . ;
} >ram AT>r8c2p
Bon, ça fonctionne parfois mais j'ai des problèmes de crash, probablement liés avec la gestion mémoire. Pour l'overlay, j'utilise le "vieux" SDK avec modification du malloc de la libc qui appelle ton kmalloc alors que l'addin principal Upsilon utilise gint, je soupconne que c'est la raison. Et difficile de déduire quoi que ce soit des infos du crash:
PC = 0041eaf0
TEA= 0041eaF0
TRA=0x0
L'adresse est celle de gint_default_panic
Pour la gestion de la mémoire, dans l'initialisation de l'overlay je fais la chose suivante, qui est peut-être incompatible avec l'utilisation de Upsilon/gint
// init kmalloc
bool is_emulator = *(volatile uint32_t *)0xff000044 == 0x00000000;
uint32_t stack;
__asm__("mov r15, %0" : "=r"(stack));
bool prizmoremu=stack<0x8c000000;
int calculator=prizmoremu?2:1;
/* À appeler une seule fois au début de l'exécution */
kmalloc_init();
/* Ajouter une arène sur la RAM inutilisée */
static_ram.name = "_uram";
static_ram.is_default = 0; // 0 disable this area, 1 enable
//void *malloc_start = &sextra;
//void *malloc_end = &eextra;
//int malloc_size = malloc_end - malloc_start;
static_ram.start = &sextra;
static_ram.end = &eextra;
kmalloc_init_arena(&static_ram, true);
kmalloc_add_arena(&static_ram);
if (prizmoremu) {
/* Prizm ou émulateur Graph 90+E */
ram3M.name="_3M";
ram3M.is_default=1;
ram3M.start=0x883e0000+256*1024;
ram3M.end=ram3M.start+0x80000;
kmalloc_init_arena(&ram3M, true);
kmalloc_add_arena(&ram3M);
}
else {
/* Graph 90+E & FXCG50(?) */
ram3M.name="_3M";
ram3M.is_default=1;
ram3M.start=0x8c3e0000+256*1024;
ram3M.end=ram3M.start+0x80000;
kmalloc_init_arena(&ram3M, true);
kmalloc_add_arena(&ram3M);
}
Sachant que dans le fichier loader contient
MEMORY
{
/* Loads code at 300000, skips g3a header */
/* rom (rx) : o = 0x00300000, l = 2M-32000 */
/* RAM is available at 0x8c200000, 3M maybe more */
/* use emu.ld for emulator since it's at 0x88200000 */
r8c2p (rx) : o = 0x8c200000, l = 2048K-128K
ram (rwx) : o = 0x8c3e0000, l = 256k
}
Citer : Posté le 06/06/2023 08:26 | #
J'ai une autre info de crash plus intéressante: 040 TLB miss on read, PC=41f646 (c'est à la fin de gint_malloc), TEA=1216be9c,
0041f378 l F .text 000000c8 gint_free
0041f440 l F .text 000000d0 gint_malloc_max
0041f510 l F .text 00000144 gint_malloc
0041f654 l F .text 00000180 gint_realloc
0041f7d4 g F .text 000000f0 kmalloc_init_arena
0041f8c4 g F .text 00000018 kmalloc_get_gint_stats
0041f8dc l F .text 00000030 arena_owning
0041f90c g F .text 00000010 kmalloc_init
0041f91c g F .text 00000054 kmalloc_get_arena
0041f970 g F .text 00000094 kmalloc
0041fa04 g F .text 00000034 kfree
0041fa38 g F .text 00000094 krealloc
0041facc g F .text 0000008c kmalloc_max
0041fb58 g F .text 00000024 kmalloc_add_arena
Citer : Posté le 06/06/2023 11:23 | #
En fait, c'est peut-être un problème avec la taille de la stack. Lorsque je passe un buffer alloué sur la stack de 2048 à 1024, ça marche nettement mieux. C'est quoi la taille de la stack utilisable dans un addin avec gint? Comment peut-on la changer?
Citer : Posté le 06/06/2023 12:02 | #
Alors une seconde... du coup tu as l'add-in Upsilon principal qui tourne sous gint et toi tu veux charger un add-in SDK dedans. Moralement ce qui est sûr c'est que déjà il faut world switch pour invoquer cet add-in. Ensuite il faut s'assurer que tu n'as pas de conflit de RAM notamment si KhiCAS essaie d'utiliser le même espace pour ses globales que Upsilon. On est d'accord que tu as linké l'intégralité de KhiCAS à 0x8c200000 et donc la seule mémoire que KhiCAS utilise hors de cette zone c'est ce qui est fournie par kmalloc ? Si oui tout va bien a priori.
N'oublie pas de donner le message on sait jamais... un crash avec le PC de gint_default_panic() ça arrive absolument jamais donc il y a sans doute quelque chose de précis (le stack overflow an retour d'un world switch en particulier est suspect parce que c'est l'un des rares panic qui ne se fait pas invoquer par une exception CPU et donc pour lequel la valeur de PC est indéfinie).
Tu essaies de déclarer de la RAM supplémentaire sur Prizm alors qu'elle n'existe pas... et tu ne différencies pas l'émulateur Prizm de l'émulateur Graph 90+E (mineur). Oui la Graph 90+E et la fx-CG 50 peuvent être traitées ensemble, je ne connais aucune différence entre les deux.
Je comprends pas le but ici. Déjà il faut bien comprendre que tu as deux versions de kmalloc, une liée statiquement dans Upsilon, une liée statiquement dans KhiCAS. Si tu n'as pas touché le linker script, alors sextra/eextra représentent la zone de RAM allouée pour KhiCAS dans le linker script KhiCAS masi pas exploitée, c'est donc la fin de ta section ram à 0x8c3e0000. Tu peux tout à fait t'en servir.
(Au passage 0 ça ne désactive pas la zone, ça la cache juste à malloc() : kmalloc() peut toujours s'en servir.)
Pour l'instant c'est réservé par kinit(), et en l'occurrence c'est 16 ko. Pour le changer il faut donc modifier ce code. C'est un peu hardcodé quand même, je dois pouvoir en faire un paramètre du linker script si besoin.
Globalement la pile est petite et c'est fait exprès parce que c'est de l'espace réservé statiquement qui est rarement utilisé. Note qu'il ne suffit pas de se limiter à 16 ko soi-même parce que BFile alloue pas mal de gros tableaux comme un bourrin. Dans l'ensemble si tu veux des objets plus gros que 1 ko je n'hésiterais pas et je les mettrais sur le tas.
Citer : Posté le 06/06/2023 13:40 | #
Il me semble que Upsilon et l'overlay sont complètement séparés en mémoire, puisque l'overlay utilise seulement la zone des 3Mo à la fois pour le code, la ram statique (elle est utilisée à 93% donc peu intéressante pour malloc) et le tas (l'arène de 512k qui est l'arène par défaut).
Je vais rajouter le world switch, je n'y avais pas pensé (en fait je n'ai pas compris quand il faut l'utiliser), ça devrait permettre de faire des GetKey du fxsdk. Comment on l'utilise pour
const char * outexact=caseval(buf);
//const char * outexact=gint_world_switch(GINT_CALL(caseval,buf));
le compilateur n'aime pas la ligne commentée.
Ceci étant, je ne pense pas que ça soit la cause des problèmes de crash, vu les symptômes. 16K de pile ce n'est pas suffisant pour Upsilon et l'overlay, déjà giac tout seul a besoin de plusieurs K, en particulier pour le parser, et Numworks réserve une pile de 32K pour Epsilon, donc Upsilon a besoin de pile aussi (il en faut de toute façon pour Micropython...) et c'est fort possible qu'on puisse le faire crasher tout seul avec 16K de pile. 32K voire 48, ce serait plus sur (surtout pour Casio où on a toujours eu l'habitude d'avoir de ne pas se soucier de la pile, donc de faire des alloca plutot que des malloc qui prennent plus de temps et où il faut fermer par un free...).
Je mets en ligne l'addin et l'overlay actuels si tu veux tester. En général dès qu'on mixe un peu de l'app Calcul avec une exécution d'un script Python un peu exigeant, ça crashe.
Citer : Posté le 06/06/2023 13:49 | #
Pour le world switch c'est bien ça, faut juste cast la valeur de retour :
Malheureusement une partie des types est perdue dans l'appel donc on peut faire beaucoup mieux... enfin en C++ on pourrait faudrait que je le code un jour.
Je me note de te fournir un paramètre pour la taille de la pile. Je suis un peu sous l'eau dans l'immédiat mais ça devrait pas être dur...
Citer : Posté le 06/06/2023 17:03 | #
Merci! Un autre report de crash
180 Illegal instruction
PC 0041ebe0 (gint_default_panic)
TEA 0041cfa0 (_WEAK_keydev_std)
TRA 0x0
Opcodes 000b e000 [2f86] 2f96
Citer : Posté le 06/06/2023 17:21 | #
Alors là sans plus d'infos ça devient de la divination...
J'ai besoin de savoir quand est-ce que tu lances ça, si tu arrives à lancer et utiliser Upsilon avant de lancer KhiCAS ou si c'est au lancement d'Upsilon, si le world switch a été fait à ce stade, quelle partie de la mémoire a été utilisée, quel protocole tu testes, etc etc.
Citer : Posté le 06/06/2023 19:05 | #
Il n'y a aucun problème pour lancer Upsilon puis l'overlay. J'ai quelques calculs restaurés de l'historique des calculs qui se sont faits normalement automatiquement au lancement d'Upsilon (genre factor(x^4-1) ou integrate(x^2*sin(x),x,0,x)). Je peux faire des calculs, ça ne crashe pas. Je quitte Calculs, je passe dans l'UI Python d'Upsilon et je lance un script Python moyennement complexe de 3.5K (un calendrierà, puis je reviens dans Calculs et je lance 1+2 et paf j'ai cette erreur 180 avec les mêmes opcodes, mais ici le TEA est aussi à 0041ebe0.
Citer : Posté le 06/06/2023 21:38 | #
Bon, le crash que j'ai décrit ci-dessus est résolu. C'est ma faute, j'avais augmenté le tas Python sur la FXCG en utilisant l'espace mémoire qui sert aussi pour l'overlay. Mais entre-temps j'avais oublié...
Citer : Posté le 08/06/2023 14:39 | #
Nouveau type de crash,
1080 Stack overflow during world switch
PC est dans la fonction cpu_setSR (PC=41e5a8 et début de cpu-setSR 41e59a)
TEA = 00426c20 (g F .text 0000005e .hidden __udiv_qrnnd_16)
Plus aucune touche ne fonctionne.
J'imagine que ca pourra être résolu avec plus de stack...