Seuls les membres ayant 30 points peuvent parler sur le chat.

Forum Casio - Autres questions


Index du Forum » Autres questions » le DMA controller sur g35 ?
MilangHors ligneMembrePoints: 285 Défis: 0 Message

le DMA controller sur g35 ?

Posté le 18/07/2019 18:57

J'ai enendu parler du DMA(direct memory access) et de son utilisation pour augmenter les perfs de la g90 pour l'affichage.

Je me suis logiquement posé les questions suivantes :

1. Le DMA existe-t-il sur les modèles monochromes ?
2. Si oui, est-il possible de l'exploiter pour effacer une certaine zone de la RAM ?
3. si oui et oui, comment l'exploiter ?

En fait j'aimerais pouvoir l'utiliser dans mon moteur 3d pour effacer le zbuffer pendant que le processeur calcule les coordonnées de points après rotation.


Pages : 1, 2Suivante
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 19:01 | #


Pour la première question, la réponse est oui, en tous cas sur SH4. Ce qui est un peu chiant serait de devoir l'implémenter sur SH3, mais vu ton use case tu peux peut-être l'utiliser sur SH4 et faire la méthode manuelle sur SH3.

Oui, c'est possible de l'utiliser pour effacer de la mémoire. Toutefois, des restrictions s'appliquent :

* Il faut que la zone de mémoire soit continue (ie. pas un rectangle à moins qu'il fasse toute la largeur de la VRAM)
* Il faut que la zone soit alignée correctement (plus c'est aligné mieux c'est)

Pour l'exploiter, il faut... un driver DMA. J'en ai un pour gint mais il est encore réduit à l'usage que j'en fais pour l'écran de la Graph 90+E. Je prévois d'écrire des fonctions dma_memset() et dma_memcpy() pour plus tard.

La référence ici c'est la doc du SH7724, qui te donne toutes les informations sur le fonctionnement de l'outil. Attention, si tu l'utilises sous fxlib, il faut faire attention à ne pas utiliser les interruptions.

Je trouve ton idée très intéressante. Quel taille il fait le z-buffer ? Histoire de voir combien de temps ça prend pour l'effacer à la main déjà !
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 19:07 | #


le zbuffer fait 16 384 octets (128*64*2) -c'est un buffer 16 bits en raison de la taille de la ram. si jamais j'ai la place pour le 32 bits je le ferai plus tard

L'intêret c'est de lancer l'effacement du zbuffer et d'ensuite faire les calculs préalables au rendu, et si besoin d'attendre que le dma controller ait fini. ça permet au minimum de gagner le temps de calcul pris par le processeur.

Ajouté le 18/07/2019 à 19:37 :
Mais du coup, si jamais tu implémentais ces fonctions dans le futur, quelle serait l'architecture à choisir, étant donné que le DMA controller n'existe pas sur sh3 ?
Le sh3 -> bah il y a pas de DMAc
Le sh4 -> j'avais cru comprendre que c'est fortement déconseillé sur le tuto pour installer gcc
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 19:41 | #


C'est pas une mauvaise idée du tout, y'a peut-être moyen de gagner 2.5 ms par frame, quelque chose du genre !

Attention, tu confonds des choses. D'un côté tu as l'architecture sur la calculatrice, de l'autre celle du compilateur. Si tu compiles avec sh3eb-elf, toutes les calculatrices peuvent lancer le code, garanti ! Si tu compiles avec sh4eb-elf -m4-nofpu, tu peux lancer sur les Graph mono SH4 et les Graph 90 (ce qui n'est pas encore très bien fait dans le tuto, c'est pour ça que je le déconseille).

Donc, tu peux continuer de compiler pour SH3. Si j'implémente ces fonctions dans le futur, la méthode sera facile car on peut détecter à l'exécution si la calculatrice est SH3 ou SH4.

• Si elle est SH4, tu peux utiliser le DMA.
• Si elle est SH3, tu peux vider le z-buffer à la main, ce sera pas pire qu'avant !
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 19:45 | #


OK, bah j'ai plus qu'à attendre que tu implémentes ces deux fonctions
Non, mais en vrai, je vais essayer de me renseigner si c'est rentable d'écrire ces deux fonctions en plus de gint, et si oui, bah je te les donnerai. Si ça prend beaucoup trop de temps, bah je mettrai ça de côté pour plus tard.

Ou est-ce que tu stockes le driver DMA dans gint ?
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 19:48 | #


C'est gentil ! Pour le driver actuel, il est dans src/dma/dma.c avec le gestionnaire d'interruption dans inth.s.

L'idée générale c'est qu'il faudrait utiliser le channel 1 du DMA au lieu du 0, le reste est quasiment identique à ce qui existe déjà (ajouter un gestionnaire d'interruption du coup).
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 20:15 | #


Bon, je ne connais que les bases en assembleur, donc je vais poser des questions

    /*
    **  gint:dma:inth - Interrupt handler for the DMA
    **  An easy one, just clears some flags and marks all transfers as finished.
    */

    .global _inth_dma_dma0
    .section .gint.blocks, "ax"
    .align 4

    /* DMA TRANSFER ENDED INTERRUPT HANDLER - BYTES */

    _inth_dma_dma0:
        /* Clear the TE flag and DMA Enable in CHCR */
        mov.l    1f, r1 // à quoi correspond 1f ?
        mov.l    @r1, r0
        mov    #-4, r2
        and    r2, r0 // que fait cette fonction ? (je vois bien que c'est un and, mais ça écrit ou ?)
        mov.l    r0, @r1

        /* Clear the AE and NMIF flags in OR, and cut the master switch */
        add    #0x34, r1
        mov.w    @r1, r0
        shlr8    r0
        shll8    r0
        mov.w    r0, @r1

        rte
        nop
        nop
        nop

    1:    .long 0xfe00802c    /* CHCR0 - OR is 0x34 bytes after this */


Ajouté le 18/07/2019 à 20:17 :
Est-ce que j'aurai besoin de modifier le gestionnaire d'interruptions ? (à priori, je pense que oui, mais seulement sur quelques lignes pour changer de channel)
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 20:31 | #


1f c'est truc de l'assembleur GNU qui fait référence au premier label 1 vers le bas (forward). 1b serait pareil mais vers le haut. Ça marche avec les labels qui sont des chiffres. Ici donc, mov.l 1f, r0 charge dans r0 l'adresse de CHCR0.

and r2, r0 c'est r0 &= r2, puisque r2 vaut -4 ça met les bits 0 et 1 de CHCR0 à 0.

Oui, tu auras besoin de modifier le gestionnaire, mais pas grand-chose. Uniquement :

1. Copier le bloc et le nommer _inth_dma_dma1 (facile)
2. Modifier l'adresse en bas pour mettre celle de CHCR1

Si l'envie t'en prend tu peux aussi faire pareil pour avoir le channel 2, ce serait tout bénef'.

Edit : Ah il faut éviter de couper le master switch aussi puisque ça arrêterait tous les channels en même temps.
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 20:34 | #


Et du coup, quelle est l'adresse du channel1 ?
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 20:55 | #


Tu peux d'abord regarder dans la doc du SH7724, un microprocesseur qui est proche de celui de la calculatrice. La section 16 dit quels registres existent et à quoi ils servent : https://bible.planet-casio.com/common/hardware/mpu/sh7724.pdf

Mais le microprocesseur de la calculatrice est un SH7305, avec parfois des différences ; la doc n'existe pas. On se réfère à SimLo. Voici une des nombreuses pages utiles de son travail : https://bible.planet-casio.com/simlo/chm/v20/fx_7305_Registers.htm
ZezombyeHors ligneRédacteurPoints: 1621 Défis: 12 Message

Citer : Posté le 18/07/2019 20:55 | #


C'est pas déjà ce que fait monochromelib ?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 20:55 | #


Zezombye a écrit :
C'est pas déjà ce que fait monochromelib ?

MonochromeLib n'utilise pas le DMA. Tu penses à quoi exactement ? :o
ZezombyeHors ligneRédacteurPoints: 1621 Défis: 12 Message

Citer : Posté le 18/07/2019 20:57 | #


Ben il accède directement à la mémoire
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 20:58 | #


C'est pas comme ça que ça marche. Bien sûr que MonochromeLib accède "directement" à la mémoire, toutes les applications le font tout le temps. xD

Le DMA c'est un module pour transférer de la mémoire pendant que tu fais autre chose, essentiellement entre la RAM et les périphériques. Mais ici on peut aussi faire des transferts entre la RAM et la RAM.
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 21:25 | #


Ok c'est bon j'ai l'adresse : 0xfe00803c (en fait c'était con, on aurait presque pu le deviner après 0xfe00802c)
Après, il y a aussi des trucs que j'ai pas compris au niveau de l'utilisation du driver :
Que fait exactement la fonction
    static int dma_setup(dma_size_t size, uint blocks,
        void *src, dma_address_t src_mode,
        void *dst, dma_address_t dst_mode,
        int interrupts)
    {
        /* Safety guard: only start a transfer if there's not one running */
        if(DMA.DMA0.CHCR.DE) return 1;

        /* Disable DMA0 and disable the master DMA switch */
        DMA.DMA0.CHCR.DE = 0;
        DMA.OR.DME = 0;

        /* Set DMA source and target address */
        DMA.DMA0.SAR = (uint32_t)src & 0x1fffffff;
        DMA.DMA0.DAR = (uint32_t)dst & 0x1fffffff;

        /* Set the number of blocks to be transferred */
        DMA.DMA0.TCR = blocks;

        /* Fill in CHCR. Set RS=0100 (auto-request) and the user-provided
           values for TS (transfer size), DM and SM (address modes) */
        DMA.DMA0.CHCR.lword = 0x00000400;
        DMA.DMA0.CHCR.TS_32 = (size >> 2);
        DMA.DMA0.CHCR.TS_10 = (size & 3);
        DMA.DMA0.CHCR.DM = dst_mode;
        DMA.DMA0.CHCR.SM = src_mode;
        DMA.DMA0.CHCR.IE = !!interrupts;

        /* Prepare DMAOR by enabling the master switch and clearing the
           blocking flags. */
        DMA.OR.DME = 1;
        DMA.OR.AE = 0;
        DMA.OR.NMIF = 0;

        return 0;
    }

Est elle appelée avant chaque transfert ou une seule fois ?
Où transfère-t-elle ? (source et target sont les memes)

Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 21:28 | #


C'est la fonction qui configure le channel 0. Elle transfère là où on lui dit via les paramètres src et dst, qui ne sont pas forcément égaux.

Cette fonction marche bien mais au lieu d'utiliser uniquement DMA.DMA0 elle devrait prendre en paramètre le numéro d'un channel et choisir dynamiquement DMA.DMA0, DMA.DMA1 ou DMA.DMA2 (je ne sais pas si j'ai mis les deux derniers ).
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 21:33 | #


mais du coup, elle réalise une simple copie de tableau ?
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 21:34 | #


Oui, essentiellement - le DMA c'est ça. Mais comme l'incrément de src ou de dst peut être nul, on peut avoir des effets cool :

* dst fixe : envoi à l'écran de la Graph 90 (puisque l'adresse du registre est fixe)
* src fixe : memset() (on pointe vers la valeur de remplissage)
* sinon : copie de mémoire
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 21:37 | #


bah moi ça me va, j'ai juste à créer une const int defValue= 0, mettre src fixe et utiliser ta fonction alors...

Ajouté le 18/07/2019 à 21:38 :
ça me fait un memset

Ajouté le 18/07/2019 à 21:42 :
il y a juste pas de header associé, mais tout compte fait, ça c'est le dernier de mes soucis, si je déclare juste l'entête de la fonction dans mon code, c'est réglé !
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

Citer : Posté le 18/07/2019 22:06 | #


C'est pas tout à fait suffisant car pour tirer parti de toute la puissance du DMA les transferts se font par blocs de 32 octets. Il te faut donc dupliquer 32 fois la valeur initiale

Je ferai le header, t'embête pas trop avec ça. Assure-toi que le prototype soit le même memset() et ça roulera !
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 18/07/2019 22:09 | #


Merci !
Allez hop et un topic résolu en un soir !
Une alternative intéressante à toutes les boucles que vous avez vu jusque là :
For 1→X To 2:X-1→X:Next :E

Projet de jeu multijoueur : 1V1 3D
Pages : 1, 2Suivante

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2019 | Il y a 38 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