Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

18F27K42 et DMA ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#1 Message par paulfjujo » sam. 3 sept. 2022 16:27

bonjour,

Ce post ,uniquement pour revenir sur le sujet de lecture d'un fichier via un terminal PC
Ici concerne la lecture d'un fichier WAV.
decodage de l'entete et envoi des dtas sur sortie Audio via un PWM 8 bits + filtre...

Apres avoir testé plusieurs terminaux, avec la fonction CTS , permettant de bloquer le flux d'envoi par le terminal..
La notion de CTS ou RTS depend de quel coté on se place.
J'utilise ici, un cordon prolific complet (avec Pin CTS et RTS !)
ce qui est de plus en plus rare ... la plupart du temps cordons ou module avec seulement TX ,RX,0V
tests avec
VBRAY terminal version 2014 .. OK mais sous Win XP .. car pas trop top en WIN10 ! dommage.
YAT terminal .. tres interessant mais petit probleme sur envoi de fichier .. pas de break possible
Terraterm Terminal ... se comporte bien .J'achete !

le PIC18F27K42 a beaucoup de RAM ... j'ai pu donc mettre un tampon RAM de 7500 bytes
guere plus car reste que 2,8% dispo.
il faut donc des fichiers wav assez courts ... j'enleve déja l'entete inutile de 64 bytes
Les fichiers WAV doivent etre echantillonnés à 11025 hz ..(. on pourrait meme les abaisser à 800O Hz)
j'utilise RC5 out comme pin CTS ... reliée à RTS du prolific cable.

Vous allez me dire qu'on peut utiliser une SDCard .. ce n'était pas le but ici .
Il y a aussi des modules tout fait , chez mikroE , pour lire des MP3 ...
je ne cherche pas la facilité.
Mais voir si un PIC peut rivaliser avec une appli PC en VB6 ..par exemple Horloge parlante..
J'avais déja utilisé , en son temps , un SPO256 + ROM pour faire parler un PIC16F84 ...mais bon..
.
Je pensais aussi pouvoir utiliser l'espace FLASH .. 116K dispo ! pour y loger plusieurs petits fichiers
exemple vocal de 0.wav à 9.wav ou autre joyeusetés.
MikroC ne gere pas la flash en page ! .. donc à suivre avec MPLABX ?

Il me semble avoir lu (en diagonale) que le DMA ne jouait qu'en lecture et non en ecriture
du genre lecture fichier -> via DMA -> Flash

tout ça pour en venir à ma question :
L'un de vous aurait-il experimenté le DMA ... avec PIC18 evolué
(semble courant avec PIC32 ou DSP)

lien sur mes tests lecture fichier Wav et restitution PWM
Aide toi, le ciel ou FantasPic t'aidera

18F27K42 et DMA ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#2 Message par satinas » sam. 3 sept. 2022 18:46

Bonjour,

Toujours accroc au contrôle de flux :) Pour moi c'est envoi de paquets et acquittement, 2 fils suffisent, et pas de Xon/Xoff à problème.

Le DMA, oui c'est courant, mais c'est un peu lourd à programmer et à mettre au point. On automatise le transfert de paquets de données entre flash, eeprom, ram et registres. Pour cela il y a un tas de registres à renseigner : interruptions DMA, adresse buffers source et destination, taille buffers source et destination, qui peuvent être différentes, le transfert se fait alors en plusieurs fois.

Pour le 18F, dont je viens de parcourir la doc, le transfert DMA se déclenche soit pas soft, bit DGO, soit par un flag d'interruption au choix, RXIF par exemple. Tu peux donc programmer un remplissage auto de buffer UART, en copiant un à un les octets reçus vers un buffer auto-incrémenté, avec arrêt auto. Une interruption DMA se produit lorsque le buffer est plein, on peut quand même à tout moment lire compteur et adresse destination, pour savoir ou en est le transfert DMA, et l'arrêter en cours si nécessaire.

On évite ainsi un bon paquet de code, et on fonctionne en parallèle avec les main/isr, moyennant l'arbitration des priorités CPU/DMA, qui est redéfinissable. Par défaut la priorité est isr > main > dma1 > dma2 > scanner_crc. Le DMA fait ses lectures ou écritures quand il le peut, c'est à dire quand la cpu n'est pas en accès mémoire.
Il y a un exemple dans le datasheet.

18F27K42 et DMA ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#3 Message par paulfjujo » sam. 3 sept. 2022 19:31

bonsoir à tous,

j'ai vu aujourd'hui , que , y a pas photo ... laisser tomber MikroC pour les nouveaux PIC EST LA SOLUTION optimale ..
MPLABX sait mieux gérer le 18F27K42 ou 18F27Q10 , et avec moult explications,... sur l'usage de la FLASH et du DMA
:sifflotte: il suffit de mettre une bouée , pour ne pas s'y noyer .. en Apnée ,c'est trop dur !

d'autant que maintenant MikroE veut faire payer mensuellement l'usage de Necto Studio 29€/mois !
je vais pouvoir faire de la place sur mon disque C: .. qui sera bouffée par les mises à jour de MPLAB !

Bref, un peu de jardinage ,ça fait aussi du bien aux neurones.
Aide toi, le ciel ou FantasPic t'aidera

18F27K42 et DMA ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#4 Message par satinas » lun. 5 sept. 2022 20:08

Bonsoir,

Il n'est jamais trop tard pour se convertir, ou plutôt se déconvertir :)

La liste des registres DMA est parlante :
SMR/SMODE/DMODE pour sélectionner les mémoires et la post incrémentation/décrémentation éventuelle des adresses.
SSA/DSA/SSZ/DSZ adresses et tailles source et destination.
SIRQEN/AIRQEN/SIRQ/AIRQ pour autoriser et déclarer les flags int éventuels pour lancer et arrêter le transfert.
SSTP/DSTP si l'on veut remettre à zéro SIRQEN lorsque un des compteurs arrive à 0.
EN/DGO/XIP pour autoriser/arrêter le transfert, le lancer, et flag transfert d'un octet en cours.
Ensuite il y a 4 interruptions DMA disponibles -> SCNT=0, DCNT=0, Abort, Overrun

Variables BUF/SCNT/DCNT/SPTR/DPTR dernier octet lu - compteurs - adresses, le tout mis à jour par le contrôleur DMA en cours de transfert, tous ces registres sont Readonly comme le flag XIP..
Pour le PRLOCK j'ai pas bien compris, il semble nécessaire d'autoriser le contrôleur à accéder à la mémoire. On le fait une seule fois ?

18F27K42_DMA_Regs.png
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.

18F27K42 et DMA ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#5 Message par paulfjujo » jeu. 8 sept. 2022 14:45

Avant de continuer sur l'aspect DMA .....

je regarde en ce moment l'usage de la flash pour y stocker des DATAS
(.... un fichier wav entier de 100Ko maxi ou plusieurs fichiers de 10K) vu les 131K dispo
au fait si c'est modulo word ...
je risque de ne pouvoir y stocker que la moitié ?
1 word flash pour 1 byte ?

il est fait mention d'un bloc special de 128 bytes en fin de memoire flash Special DATA
que l'on peut protéger par le bit SAF ...
mais tout l'espace peut bien etre utilisé ( apres le programme) pour y stocker des datas
car à priori le test suivant en @0x7D00 le prouve.

:!!: or Dans Memory.c de MCC on voit que :
#define WRITE_FLASH_BLOCKSIZE 128
#define ERASE_FLASH_BLOCKSIZE 128
#define END_FLASH 0x020000

alors que dans l'exemple donné

Code : Tout sélectionner


int8_t FLASH_WriteBlock
(uint32_t writeAddruint8_t *flashWrBufPtr)
{
    
uint32_t blockStartAddr  = (uint32_t )(writeAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
    
uint8_t GIEBitValue INTCON0bits.GIE;     // Save interrupt enable
    
uint8_t i;

    
// Flash write must start at the beginning of a row
    
if( writeAddr != blockStartAddr )
    {
        return -
1;
    }

    
// Block erase sequence
    
FLASH_EraseBlock(writeAddr);

    
// Block write sequence
    
TBLPTRU = (uint8_t)((writeAddr 0x00FF0000) >> 16);    // Load Table point register
    
TBLPTRH = (uint8_t)((writeAddr 0x0000FF00)>> 8);
    
TBLPTRL = (uint8_t)(writeAddr 0x000000FF);

    
// Write block of data
    
for (i=0i<WRITE_FLASH_BLOCKSIZEi++)
    {
        
TABLAT flashWrBufPtr[i];  // Load data byte

        
if (== (WRITE_FLASH_BLOCKSIZE-1))
        {
            
asm("TBLWT");
        }
        else
        {
            
asm("TBLWTPOSTINC");
        }
    }

    
NVMCON1bits.NVMREG 2;
    
NVMCON1bits.WREN 1;    
    
INTCON0bits.GIE 0// Disable interrupts    
    
NVMCON2 0x55;
    
NVMCON2 0xAA;
    
NVMCON1bits.WR 1// Start program
    
INTCON0bits.GIE GIEBitValue// Restore interrupt enable
    
NVMCON1bits.WREN 0// Disable writes to memory
    
return 0;
}
 


blocksize est de 128

alors que dans Memory.h , l' exemple porte sur 64 bytes de data (wrBlockData)

Code : Tout sélectionner

@Example
    <code>
    #define FLASH_ROW_ADDRESS     0x7D00

    uint8_t wrBlockData[] =
    {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
    };

    // write to Flash memory block
    FLASH_WriteBlock((uint32_t)FLASH_ROW_ADDRESS, (uint8_t *)wrBlockData);
    </code>
*/
int8_t FLASH_WriteBlock(uint32_t writeAddr, uint8_t *flashWrBufPtr);


or j'ai fait le test suivant
Lecture à partir de Zone flash 7D00 .. 64 datas
Ecriture du tableau montré dans l'exemple à partir de 7D00 ..+ 64
La relecture 7D00 de 64 datas , restitue bien le tableau de 64 bytes
Pourquoi alors definir
#define WRITE_FLASH_BLOCKSIZE 128
l'indice i est-il multiplié par 2 pour tomber sur des adresses paires ( donc modulo word )
mais par quel artifice ?

Test Lecture Flash at @ 0x7D00 soit 32000
0x00.0x01.0x02.0x03.0x04.0x05.0x06.0x07.0x08.0x09.0x0a.0x0b.0x0c.0x0d.0x0e.0x0f.
0x10.0x11.0x12.0x13.0x14.0x15.0x16.0x17.0x18.0x19.0x1a.0x1b.0x1c.0x1d.0x1e.0x1f.
0x20.0x21.0x22.0x23.0x24.0x25.0x26.0x27.0x28.0x29.0x2a.0x2b.0x2c.0x2d.0x2e.0x2f.
0x30.0x31.0x32.0x33.0x34.0x35.0x36.0x37.0x38.0x39.0x3a.0x3b.0x3c.0x3d.0x3e.0x3f.

Test ecriture Bloc 64 data en Flash at @ 0x7D00 soit 32000
retour k= 0

Test Re-Lecture Flash at @ 0x7D00 soit 32000
0x00.0x01.0x02.0x03.0x04.0x05.0x06.0x07.0x08.0x09.0x0a.0x0b.0x0c.0x0d.0x0e.0x0f.
0x10.0x11.0x12.0x13.0x14.0x15.0x16.0x17.0x18.0x19.0x1a.0x1b.0x1c.0x1d.0x1e.0x1f.
0x20.0x21.0x22.0x23.0x24.0x25.0x26.0x27.0x28.0x29.0x2a.0x2b.0x2c.0x2d.0x2e.0x2f.
0x30.0x31.0x32.0x33.0x34.0x35.0x36.0x37.0x38.0x39.0x3a.0x3b.0x3c.0x3d.0x3e.0x3f.
fin de Test Flash



le code associé:

Code : Tout sélectionner


  CRLF1
();
     
CPrint(" Test Lecture Flash at @ 0x7D00 soit 32000 \r\n"); 
    for (
i=0;i<64;i++)
    {    if((
i%16==0)&&(i>0)) CRLF1();
        
cxFLASH_ReadByte(FLASH_ROW_ADDRESS+i);
        
sprintf(CRam1,"0x%02x.",cx);
        
My_Print(CRam1);
      
    }    
    
CRLF1();CRLF1();
    
CPrint(" Test ecriture Bloc 64 data en Flash at @ 0x7D00 soit 32000 \r\n"); 
  
//  int8_t FLASH_WriteBlock(uint32_t writeAddr, uint8_t *flashWrBufPtr)
    
k=FLASH_WriteBlock(FLASH_ROW_ADDRESSwrBlockData);
    
sprintf(txt," retour k=%5d\r\n",k);
    
My_Print(txt);
    
CRLF1();
    
CPrint(" Test Re-Lecture Flash at @ 0x7D00 soit 32000 \r\n"); 
    for (
i=0;i<64;i++)
    {   if((
i%16==0)&&(i>0)) CRLF1();
        
cxFLASH_ReadByte(FLASH_ROW_ADDRESS+i);
        
sprintf(CRam1,"0x%02x.",cx);
        
My_Print(CRam1);
       
    }    
    
CRLF1();
    
      
CPrint(" Test ecriture Bloc 64 data en Flash at @ 0x7D00 soit 32000 \r\n"); 
  
//  int8_t FLASH_WriteBlock(uint32_t writeAddr, uint8_t *flashWrBufPtr)
    
k=FLASH_WriteBlock(FLASH_ROW_ADDRESSwrBlockData);
    
sprintf(txt," retour k=%5d\r\n",k);
    
My_Print(txt);
    
CRLF1();
    
    
CPrint(" Test Re-Lecture Flash at @ 0x7D00 soit 32000 \r\n"); 
    for (
i=0;i<64;i++)
    {   if((
i%16==0)&&(i>0)) CRLF1();
        
cxFLASH_ReadByte(FLASH_ROW_ADDRESS+i);
        
sprintf(CRam1,"0x%02x.",cx);
        
My_Print(CRam1);
       
    }    
    
CRLF1();
      
CPrint(" fin de Test Flash \r\n");
 



La flash est bien organisée maintenant en mot de 16 bits ?
Pas facile de retouver cette info simpliste dans la datasheet .
Aurais-tu un indice, une piste pour éclairer ma lanterne (... à Led , ecolo oblige)
On ecrirerai par bloc de 128 bytes , mais la lecture se fait ( modulo word )..donc 64 positions par bloc ?
par quel mechanisme (word alignement) , puisque mon indice dans la boucle de lecture va de 0 à 63 ?

d'ailleurs sur un 16F147 user ID config word ,
Mot de 14 bits en flash, et non pas 16 ..
j'avais fait un test pour pou pouvoir écrire 2 valeurs ascii <64 concaténés dans 1 mot !...
14 bits 111111 111111
ascii#1 ascii#2
Aide toi, le ciel ou FantasPic t'aidera

18F27K42 et DMA ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#6 Message par satinas » jeu. 8 sept. 2022 14:54

Le temps que j'ingurgite tout ton post, cela va me prendre un certain temps :) voilà ce que j'ai écrit dans le source du bootloader 18F27K42 et autres 18F high perf.

; la flash contient des mots de 2 octets, l'eeprom des mots de 1 octet
; on lit la flash et l'eeprom de la même façon
; on renseigne l'adresse du mot, et on lit le mot (2 octets programme ou 1 octet eeprom)
; on efface la flash par secteurs de 32 ou 128 mots selon pic
; on renseigne l'adresse du premier mot du secteur, et on efface
; on écrit la flash par pages de 64 ou 128 mots, on renseigne l'adresse du premier
; mot de la page, on renseigne les latches (128 ou 256 octets), et on écrit
; on écrit l'eeprom mot pat mot, avec effacement auto
; on renseigne l'adresse du mot, on renseigne le latch (1 octet), et on écrit

Les adresses sont toujours exprimées en octets.

Bon, dans le bootloader que j'ai testé et retesté en son temps, il y a pour le 18F27K42 :

Code : Tout sélectionner

ESCTP_WSIZ  equ     64            ; taille secteur erase flash en mots
WPAGP_WSIZ  equ     64            ; taille page write flash en mots
ESCTD_WSIZ  equ     -1            ; effacement auto mot eeprom
WPAGD_WSIZ  equ     1             ; écriture mot eeprom

Donc pour le 18F27K42, on efface puis on écrit des blocs flash de 64 mots / 128 octets.

On parle de mots de 2 octets, mais la lecture de la flash et l'écriture des latches se fait octet par octet, avec le pointeur TBLPTR et les ins TBLRD et TBLWR.
La lecture se fait de façon linéaire octet par octet, on peut lire qu'un seul octet (à vérifier ...). C'est le bootloader qui parle de lire des mots car lui il lit toute la flash. Pour l'écriture c'est différent car on lance l'écriture de la page, c'est les 64 mots / 128 octets en latch qui sont stockés en une seule fois dans la flash.

La flash est organisée en mots de 16 bits, ce n'est peut être pas explicite, il faut le déduire :
PIC18(L)F27/47/57K42: 128 Kbytes of Flash memory, up to 65,536 single-word instructions. The program memory is addressed in bytes. Instructions are stored as either two bytes or four bytes in program memory.
Eeprom -> The data EEPROM allows byte read and write.

Pour lire/écrire la flash, en fin de compte il faut oublier la notion de mot, on lit des octets, et on écrit une table latch de 128 octets alignés. Mon bootloader est universel et modulable, il traite des mots de 8 bits (eeprom) à 32 bits (pic32), c'est pourquoi il aime bien cette notion de mot :)
Et pour finir, si t'es arrivé jusque là :)
- tu peux bien sûr stocker 2 octets du fichier WAV dans 1 mot de la flash.
- dans ton programme, tu n'écris pas 64 data, tu écris WRITE_FLASH_BLOCKSIZE data, et WRITE_FLASH_BLOCKSIZE est égal à 128

18F27K42 et DMA ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#7 Message par paulfjujo » ven. 9 sept. 2022 15:09

bonjour Satinas , et à tous,

- dans ton programme, tu n'écris pas 64 data, tu écris WRITE_FLASH_BLOCKSIZE data, et WRITE_FLASH_BLOCKSIZE est égal à 128


OUI, d'accord .. mais ça ne definit que la taille et ce n'est évident que pour la RAZ du bloc., ou l'écriture par bloc.
je n'ai pas vu de Flash_Read blocs dans la bibliotheque Memory.
j'ai un tableau de 64 data byte .. inferieur à 128 .... mais un indice d'index : adress de depart + i<<1
ou alors parcourir de 0 à 127 modulo 2..

Probleme résolu ...
testé avec 2 tables , une de 64 bytes et une de 64 mots (128 bytes)

en fait la lecture Flash ne se fait qu'en mode 8 bits !
puisque la lecture Flash Word se fait en 2 operations MSB<<8+ LSB
si je manipule des Bytes, stocké dans le LSB de la flash => 64 bytes par bloc flash de 128 bytes
si je manipule des Word , stocké dans MSB et LSB => 64 words par bloc de 128 bytes

verifié ici

Test_ecriture_lecture_Flash_2022-0909.jpg


et le code de test


les 2 tables

Code : Tout sélectionner



#include "memory.h" 
 
 
#define FLASH_ROW_ADDRESS     0x7D00

 uint8_t wrBlockByte[] =
    {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
    
};
 uint16_t wrBlockWord[] =
    {
        0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, 0x10C, 0x100D, 0x100E, 0x100F,
        0x7F10, 0x7F11, 0x7F12, 0x7F13, 0x7F14, 0x7F15, 0x7F16, 0x7F17, 0x7F18, 0x7F19, 0x7F1A, 0x7F1B, 0x7F1C, 0x7F1D, 0x7F1E, 0x7F1F,
        0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029, 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F,
        0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F
    
};




le code dans le main ...

Code : Tout sélectionner


   CRLF1
();
   CPrint(" Test1 Lecture 64 Bytes Flash at @ 0x7D00 soit 32000 \r\n"); 
    for 
(i=0;i<64;i++)
    {   if(i%16==0)
        {
            CRLF1();
            sprintf(CRam1," %u -> ",FLASH_ROW_ADDRESS+(i<<1));
            My_Print(CRam1);
        }
        cx= FLASH_ReadByte(FLASH_ROW_ADDRESS+(i<<1));
        sprintf(CRam1,"0x%02x.",cx);
        My_Print(CRam1);
    }    
    CRLF1
();CRLF1();
          
    CPrint
(" Test2 ecriture Bloc 64 Bytes data en Flash at @ 0x7D00 soit 32000 \r\n"); 
  
//  int8_t FLASH_WriteBlock(uint32_t writeAddr, uint8_t *flashWrBufPtr)
    k=FLASH_WriteBlock(FLASH_ROW_ADDRESS, wrBlockByte);
    sprintf(txt," retour k=%5d\r\n",k);
    My_Print(txt);
    CRLF1();
     
    
    CPrint
(" Test3 Re-Lecture Bytes en  Flash at @ 0x7D00 soit 32000 \r\n"); 
    for 
(i=0;i<64;i++)
    {  if (i%16==0)
         {
           CRLF1();
           sprintf(CRam1," %u -> ",FLASH_ROW_ADDRESS+(i<<1));
           My_Print(CRam1);
         }
        cx= FLASH_ReadByte(FLASH_ROW_ADDRESS+i);
        sprintf(CRam1,"0x%02x.",cx);
        My_Print(CRam1);
    }    
    CRLF1
();
    
  
    CRLF1
();
    CPrint(" Test5 : Efface Bloc 128 Bytes  en Flash at @ 0x7D00 soit 32000 \r\n");
    FLASH_EraseBlock(FLASH_ROW_ADDRESS);
     CRLF1();
    
     CPrint
(" Test6 : Lecture 64 Word Flash at @ 0x7D00 soit 32000 \r\n"); 
    for 
(i=0;i<64;i++)
    {   if(i%16==0)
        {
            CRLF1();
            sprintf(CRam1," %u -> ",FLASH_ROW_ADDRESS+(i<<1));
            My_Print(CRam1);
        }
        k = FLASH_ReadWord(FLASH_ROW_ADDRESS+(i<<1));
        sprintf(CRam1,"0x%04x.",k);
        My_Print(CRam1);
    }    
    CRLF1
();CRLF1();
    
    
     CPrint
(" Test7 : ecriture Bloc 64  WORD data en Flash at @ 0x7D00 soit 32000 \r\n"); 
     
//  int8_t FLASH_WriteBlock(uint32_t writeAddr, uint8_t *flashWrBufPtr)
    k=FLASH_WriteBlock(FLASH_ROW_ADDRESS,wrBlockWord);
    sprintf(txt," retour k=%5d\r\n",k);
    My_Print(txt);
    CRLF1(); 
    
    CPrint
(" Test8 : Re-Lecture 64 WORD en  Flash at @ 0x7D00 soit 32000 \r\n"); 
    for 
(i=0;i<64;i++)    
    
{ 
         if 
(i%16==0)
         {
           CRLF1();
           sprintf(CRam1," %u -> ",FLASH_ROW_ADDRESS+(i<<1));
           My_Print(CRam1);
         }
       k= FLASH_ReadWord(FLASH_ROW_ADDRESS+(i<<1));
        sprintf(CRam1,"0x%04x.",k);
        My_Print(CRam1);
    }    
    CRLF1
();
    
    
     CPrint
(" fin de Test Flash \r\n");
     CRLF1();
    __delay_ms(3000);


:sifflotte: idea ! on est donc gagnant si on travaille en Word , d 'ou stockage de 2 bytes fichier datas WAV par flash word ...
je devrais pouvoir y loger un fichier de 100Ko !
:!!: d'accord ?

par contre il faut que je verifie la vitesse de lecture Flash ..
recours au SMT1 pour chronometrer ceci...
pour la restitution Flash -> PWM 8b consigne dans une boucle tournant à 11025 Hz .. ( WAV mono PCM 8 bits à 11025Hz)
...à suivre ...
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Aide toi, le ciel ou FantasPic t'aidera

18F27K42 et DMA ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#8 Message par satinas » ven. 9 sept. 2022 15:56

Bonjour,

Code : Tout sélectionner

CPrint(" Test2 ecriture Bloc 64 Bytes data en Flash at @ 0x7D00 soit 32000 \r\n");

Nein, tu écris 128 bytes data, les 64 octets de wrBlockByte[] suivis de la moitié de wrBlockWord[]
00 01 02 03 04 05 ... 3C 3D 3E 3F (64 octets de wrBlockByte[])
00 10 01 10 02 10 ... 1E 7F 1F 7F (64 octets de wrBlockWord[] stockés en little endian par le compilateur C)

Code : Tout sélectionner

CPrint(" Test3 Re-Lecture Bytes en  Flash at @ 0x7D00 soit 32000 \r\n");
Là tu lis les 64 premiers octets écrits, pas de problème.

Code : Tout sélectionner

CPrint(" Test5 : Efface Bloc 128 Bytes  en Flash at @ 0x7D00 soit 32000 \r\n");
ok, effacement de la page de 128 octets.

Code : Tout sélectionner

CPrint(" Test6 : Lecture 64 Word Flash at @ 0x7D00 soit 32000 \r\n");
ok, page de 128 octets effacée.

Code : Tout sélectionner

CPrint(" Test7 : ecriture Bloc 64  WORD data en Flash at @ 0x7D00 soit 32000 \r\n");
ok, écriture des 128 octets de wrBlockWord[]

Code : Tout sélectionner

CPrint(" Test8 : Re-Lecture 64 WORD en  Flash at @ 0x7D00 soit 32000 \r\n");
ok, lecture des 128 octets

Je ne comprends pas ce que tu veux faire, à quoi bon écrire des octets uniquement à des adresse paires. On stocke de façon linéaire dans la flash. Il n' y a pas à parler de word, à moins de se compliquer la vie. Le datasheet parle d'instruction word, cela ne va plus loin.
Rien ne t'empêche de faire des fonctions ReadWord() WriteWord() qui traitent n octets consécutifs, pas forcément alignés sur une adresse précise, mais cela ne concerne pas la cpu qui elle ne travaille qu'en octets.
OUI, d'accord .. mais ça ne definit que la taille et ce n'est évident que pour la RAZ du bloc., ou l'écriture par bloc.

On peut écrire autrement que par bloc ?

Je me pose une autre question. Que se passe t-il si on envoie la commande d'écriture sans avoir rempli le latch de 128 octets. La flash reste inchangée, ou on écrit des valeurs incorrectes, ou que des FF, rendez-vous en terre inconnue :)
La réponse est là :
The default value of the holding registers on device Resets and after write operations is FFh. A write of FFh to a holding register does not modify that byte. This means that individual bytes of program memory may be modified, provided that the change does not attempt to change any bit from a ‘0’ to a ‘1’. When modifying individual bytes, it is not necessary to load all holding registers before executing a long write operation.


Ok, le latch est à 0xFF par défaut, donc il suffit de modifier dans le latch juste les octets qui doivent être écrits, les autres octets de la page resteront inchangés dans la flash. Lors de l'écriture dans la flash, un bit peut passer de '1' à '0', l'inverse n'est pas possible, donc un FF dans le latch ne change rien dans la flash.
Tu peux créer la fonction suivante permettant d'écrire soit toute la page (n=128) soit n<128 octets dans une partie effacée de la page, sans toucher au reste de la page.

Code : Tout sélectionner

int8_t FLASH_WriteBlock(uint32_t writeAddr, uint8_t *flashWrBufPtr, uint8_t n)
{
  if (n == WRITE_FLASH_BLOCKSIZE) [FLASH_EraseBlock(writeAddr);
  writeAddr -> TBLPTR
  for (i=0, i<n, i++) {
    TABLAT = flashWrBufPtr[i];
    if (i == n-1) asm("TBLWT");
    else asm("TBLWTPOSTINC");
  }
  write page
}

Ou alors modifier dans le latch un par un les octets à écrire, puis lancer le write de la page. C'est ce genre de choses qui permet de mettre une fat dans la flash.

18F27K42 et DMA ?
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2589
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#9 Message par paulfjujo » sam. 10 sept. 2022 09:28

satinas a écrit :Bonjour,

Code : Tout sélectionner

CPrint(" Test2 ecriture Bloc 64 Bytes data en Flash at @ 0x7D00 soit 32000 \r\n");

Nein, tu écris 128 bytes data, les 64 octets de wrBlockByte[] .


Jawoll,mein Herr !
E ffectivement, puisque le bloc fait 128 bytes, je m'etais mal exprimé sur le commentaire :
CPrint(" Test2 ecriture 64 Bytes data dans un bloc de 128 bytes Flash at @ 0x7D00 soit 32000 \r\n");

Merci ! En fait , merçi de m'avoir ré-aiguillé par rapport à une idée préconçue que j'avais
pêchéé je ne sais plus où ? ( peut etre avec les ESP32 ?)
concernant l'obligation d' etre aligné sur un word au niveau adressage Flash..
de plus mon exemple de 64 bytes au lieu de 128 bytes ( because paquets de data ...WAV) etait mal approprié.

j'ai repris les test ,cette fois avec une table de 128 bytes ..

Code : Tout sélectionner


uint8_t wrBlockByte
[] =
    {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
        0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F                     
    
};
 




Code : Tout sélectionner

---- 2em  Test Flash .. adressage Flash modulo Byte -------

 Test 1A : Efface Bloc 128 Bytes  en Flash at @ 0x7D00 soit 32000 


 Test 2A Lecture 128 Bytes Flash at 
@ 0x7D00 soit 32000 

 32000 
-> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32016 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32032 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32048 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32064 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32080 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32096 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.
 32112 -> 0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.0xff.

 Test 3A ecriture Bloc 128 Bytes data en Flash at @ 0x7D00 soit 32000 
 retour k
=    0


 Test 4A Re
-Lecture Bytes en  Flash at @ 0x7D00 soit 32000 

 32000 
-> 0x00.0x01.0x02.0x03.0x04.0x05.0x06.0x07.0x08.0x09.0x0a.0x0b.0x0c.0x0d.0x0e.0x0f.
 32016 -> 0x10.0x11.0x12.0x13.0x14.0x15.0x16.0x17.0x18.0x19.0x1a.0x1b.0x1c.0x1d.0x1e.0x1f.
 32032 -> 0x20.0x21.0x22.0x23.0x24.0x25.0x26.0x27.0x28.0x29.0x2a.0x2b.0x2c.0x2d.0x2e.0x2f.
 32048 -> 0x30.0x31.0x32.0x33.0x34.0x35.0x36.0x37.0x38.0x39.0x3a.0x3b.0x3c.0x3d.0x3e.0x3f.
 32064 -> 0x40.0x41.0x42.0x43.0x44.0x45.0x46.0x47.0x48.0x49.0x4a.0x4b.0x4c.0x4d.0x4e.0x4f.
 32080 -> 0x50.0x51.0x52.0x53.0x54.0x55.0x56.0x57.0x58.0x59.0x5a.0x5b.0x5c.0x5d.0x5e.0x5f.
 32096 -> 0x60.0x61.0x62.0x63.0x64.0x65.0x66.0x67.0x68.0x69.0x6a.0x6b.0x6c.0x6d.0x6e.0x6f.
 32112 -> 0x70.0x71.0x72.0x73.0x74.0x75.0x76.0x77.0x78.0x79.0x7a.0x7b.0x7c.0x7d.0x7e.0x7f.
---
 fin du 2em Test Flash .. adressage Flash modulo Byte------

 


et ce code, adressage byte par byte

Code : Tout sélectionner


 CRLF1
();
    CPrint(" Test 2A Lecture 128 Bytes Flash at @ 0x7D00 soit 32000 \r\n"); 
    for 
(i=0;i<128;i++)
    {   if(i%16==0)
        {
            CRLF1();
            sprintf(CRam1," %u -> ",FLASH_ROW_ADDRESS+i);
            My_Print(CRam1);
        }
        cx= FLASH_ReadByte(FLASH_ROW_ADDRESS+i);
        sprintf(CRam1,"0x%02x.",cx);
        My_Print(CRam1);
    }    
    CRLF1
();CRLF1();
 



effacement => 0xFF de partout
ecriture de la table dan le block
:+1: relecture du bloc de 128 bytes -> restitue bien le contenu de la table..OK
Aide toi, le ciel ou FantasPic t'aidera

18F27K42 et DMA ?
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#10 Message par satinas » sam. 10 sept. 2022 17:10

Je vais vendre tous mes livres d'école, enfin la richesse et l'opulence.
https://www.ebay.fr/itm/394199244913?ha ... R7qikv_kYA


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 34 invités