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 : Précédente1, 2
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
LephenixnoirHors ligneAdministrateurPoints: 15492 Défis: 136 Message

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


Bien joué ! Si ton code est à peu près clean tu peux soumettre une pull request...
MilangHors ligneMembrePoints: 285 Défis: 0 Message

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


Donc au niveau du code
Donc rajouter de lasm pour prendre en compte le channel 1 et je modifie un peu ta fonction pour choisir dynamiquement le bon channel, c'est ça ?
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:31 | #


Oui, c'est ça ! Si possible dans dma_setup() ne pas c/c le code de configuration mais utiliser un pointeur.
MilangHors ligneMembrePoints: 285 Défis: 0 Message

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


Dans les arguments ?
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:38 | #


Hmm, je dirais prendre le numéro de channel en argument (0/1/2) et ensuite calculer le pointeur (&DMA.DMA{0,1,2}) à l'intérieur de la fonction.
MilangHors ligneMembrePoints: 285 Défis: 0 Message

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


Au niveau de init, il faut mettre quelles adresses pour gint_int_handler
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:49 | #


0x800 pour le channel 0, 0x820 pour le 1, 0x840 pour le 2 et il semble y en avoir un dernier, qui serait 0x860 à tester.
MilangHors ligneMembrePoints: 285 Défis: 0 Message

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


Allez hop je t'écrirai aussi dma_memset et dma_memcpy, avec les parametres standards

Ajouté le 19/07/2019 à 11:22 :
du coup du coté de inth.s c'est bon :
/*
**  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
    mov.l    @r1, r0
    mov    #-4, r2
    and    r2, r0
    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



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

_inth_dma_dma1:
    /* Clear the TE flag and DMA Enable in CHCR */
    mov.l    2f, r1
    mov.l    @r1, r0
    mov    #-4, r2
    and    r2, r0
    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



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

_inth_dma_dma2:
    /* Clear the TE flag and DMA Enable in CHCR */
    mov.l    3f, r1
    mov.l    @r1, r0
    mov    #-4, r2
    and    r2, r0
    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 */
2:    .long 0xfe00803c
3:    .long 0xfe00804c


Ajouté le 19/07/2019 à 11:31 :
mais par contre pour calculer automatiquement le pointeur j'ai des doutes :
je le met de type void* ?
Pour calculer DMA.DMAx ça c'est ok :
void* UsedDMA=0xFE008020 + 2*x;

Mais du coup, pour l'exploiter, est-ce que j'ai le droit de faire par exemple
UsedDMA.CHCR.DE = 0; // Comment le compilateur peut il savoir de quoi je parle ?
au lieu de
DMA.DMA0.CHCR.DE = 0;
C'est en fait ça qui me fait douter sur le choix du (void*)
est-ce que il faut modifier les fonctions en "ctx_" ? Je n'ai pas vraiment compris à quoi elles servent


Enfin, pour ce qui est du memset et memcpy, pour l'instant je ne sais pas si on peut écrire octet par octet avec le DMA, et j'en ai pas particulièrement besoin en fait
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 19/07/2019 12:47 | #


C'est pas mal, merci ! Queques remarques sur l'assembleur. Ces deux lignes ne sont pas nécessaires :

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

puisque la section est déjà définie et l'alignment est préservé au-dessus (au contraire si le bloc au-dessus fait pas un multiple de 4 en taille je préfère que ça plante avec une erreur de compil' parce que c'est pas normal !).

Pour la suite, si tu veux accéder au registre OR, c'est 0x34 octets avec CHCR0, mais du coup par rapport à CHCR1 c'est 0x24 et par rapport à CHCR2 c'est 0x14. Couper le master switch arrête tous les DMAs en même temps donc c'est probablement quelque chose à modifier mais je m'occuperai de la doc pour trouver comment...

Comme ces gestionnaires d'interruption sont tous des blocs de taille fixe, c'est bien qu'ils soient "free-standing". En particulier les données doivent être à la fin des blocs parce que le repositionnement va casser les références indirectes. Les adresses des CHCR devraient donc être à la fin de chaque bloc ; tu peux aussi vérifier que chaque gestionnaire doit faire exactement 32 octets.

Milang a écrit :
Pour calculer DMA.DMAx ça c'est ok :
void* UsedDMA=0xFE008020 + 2*x;

Le plus clean c'est de compter en octets, auquel cas ce serait :
sh7305_dma_channel_t *UsedDMA = (void *)(0xfe008020 + 16 * x);

Note que tu peux aussi caster 0xfe008020 en void* puis calculer dessus puisque dans GCC l'arithmétique de void* est par octet. Le cast est important sinon tu ne peux pas accéder aux données ensuite !

Mais du coup, pour l'exploiter, est-ce que j'ai le droit de faire par exemple
UsedDMA.CHCR.DE = 0; // Comment le compilateur peut il savoir de quoi je parle ?

Une fois que tu as casté c'est bon, à la notation près :
UsedDMA->CHCR.DE = 0;

J'ai remarqué que dans mon header <gint/mpu/dma.h> j'ai documenté 6 channels différents en fait. S'il en existe bien 6 alors je paramétrerai le code et les interrupt handlers pour éviter d'avoir 6 fois la même chose, ce qui serait dommage.

est-ce que il faut modifier les fonctions en "ctx_" ? Je n'ai pas vraiment compris à quoi elles servent

Ces fonctions servent à sauvegarder l'état complet du DMA dans un objet de type ctx_t (contexte) puis à le restaurer à la fin. C'est parce que gint prend le contrôle du matériel mais doit ultimement le rendre au système d'exploitation, et donc restaurer tous les paramètres à leur état initial. Comme le driver modifie maintenant le DMA1/2, il faut aussi les sauvegarder - donc rajouter des éléments dans ctx_t et copier plus de choses, avec une boucle certainement. Si tu as un doute je le ferai.

Enfin, pour ce qui est du memset et memcpy, pour l'instant je ne sais pas si on peut écrire octet par octet avec le DMA, et j'en ai pas particulièrement besoin en fait

Tu peux mais c'est pas intéressant ! Laisse par blocs de 32 octets, on documentera que ces fonctions ne sont que pour des blocs 32-alignés avec des tailles multiples de 32 et puis c'est tout.

Merci encore pour ton aide !
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 19/07/2019 14:05 | #


A quoi correspond le premier argument de gint_intlevel(int,int) ?
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 19/07/2019 14:09 | #


C'est le numéro d'une position dans les registres IPR* du contrôleur d'interruption. Regarde page 364 de la doc du SH7724 : il suffit de compter de haut en bas et de gauche à droite en partant de 0. Par exemple IPRB & 0x00f0 c'est 6 (DMAC1A sur SH7724 ; vois <gint/mpu/intc.h> pour une liste plus proche du SH7305).

Je vais les nommer parce que c'est trop casse-pieds de suivre les numéros.
MilangHors ligneMembrePoints: 285 Défis: 0 Message

Citer : Posté le 19/07/2019 14:23 | #


je ne comprends toujours pas quelle est la valeur que je dois mettre

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 19/07/2019 14:40 | #


En fait la réponse est "rien" parce que l'interruption que le gint_intlevel() actuel active concerne l'ensemble du DMA donc tous les channels à la fois.
Pages : Précédente1, 2

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