Oui effectivement, je me suis mélanger un peu, je raisonnais côté pic , alors que le code était côté flash, mais bon ça coïncide bien car je reçois à tout les coup l'ID
Tu reprends le main d'origine du driver, et tu ajoutes UNE PAR UNE les tests et les fonctions manquantes, déblocage secteurs, effacement, écriture de page, ... Et tu t'arrêtes quand il passe aux tests SQI. Bref tu fais ce qu'il fallait faire il y a un mois ...
OK merci
Je vais m'y atteler, je sais ,je me suis un peu obstiné ailleurs en pensant maladroitement à la facilité.
Une question, que veux dire quand on fait un "_" avant la déclaration d'une données ou fonction, comme ce que tu fais pour les #defines des entrées sorties ?
Par contre, a quel moment du main, rentres tu les données à sauvegarder, c'est bien ce qui est détenu dans le tableau data_256[] ?
Bonjour,
chaque processeur a son jeu de defines déclarés dans un fichier include du compilateur, p32mx795f512l.h pour ton pic. Cela permet notamment d'accéder aux registres du pic bit par bit.
le bit 0 du registre LATB a pour synonymes LATBbits.LATB0 et _LATB0
le bit 0 du registre TRISB a pour synonymes TRISBbits.TRISB0 et _TRISB0
le bit 0 du registre PORTB a pour synonymes PORTBbits.RB0 et _RB0
Il écrit puis vérifie une page de la flash en utilisant un tableau déclaré en global data_256[256].
il le remplit avant écriture par int i=0; while (i <= 255) { data_256[i] = 170; i++; }
Est-ce que la lecture des codes Jedec marche en mettant l'horloge à 80 MHz ?
En fait, je suis déjà en 80M interne, mon fichier INIT
Donc la méthode d'écriture consiste à remplir ce tableau globale par les valeurs de ma structure à sauvegarder ?Code:// **************************************************************************** // **************************************************************************** // Section: Configuration Bits // **************************************************************************** // **************************************************************************** // <editor-fold defaultstate="collapsed" desc="Configuration Bits"> /*** DEVCFG0 ***/ #pragma config DEBUG = OFF #pragma config ICESEL = ICS_PGx2 #pragma config PWP = OFF #pragma config BWP = OFF #pragma config CP = OFF /*** DEVCFG1 ***/ #pragma config FNOSC = PRIPLL #pragma config FSOSCEN = ON #pragma config IESO = ON #pragma config POSCMOD = XT #pragma config OSCIOFNC = OFF #pragma config FPBDIV = DIV_1 #pragma config FCKSM = CSECME #pragma config WDTPS = PS1048576 #pragma config FWDTEN = OFF /*** DEVCFG2 ***/ #pragma config FPLLIDIV = DIV_2 #pragma config FPLLMUL = MUL_20 #pragma config FPLLODIV = DIV_1 #pragma config UPLLIDIV = DIV_2 #pragma config UPLLEN = ON
Tu poses les mêmes questions que pour la flash interne du pic, les réponses sont les mêmes.
Les tests sont déjà finis ?
Par contre , en copiant mes fonctions, je m'aperçois d'une en particulier qui fait intervenir du transfert SQI alors qu'elle est intitulé SPI, est-ce une erreur ?
Code:void SPI_Read_Burst(unsigned long Dst, unsigned char burstlength) { unsigned int i; i=0; CE_Low(); /* enable device */ Send_Byte(0xEC); /* read command */ SendSQI_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */ SendSQI_Byte(((Dst & 0xFFFF) >> 8)); SendSQI_Byte(Dst & 0xFF); SendSQI_Byte(Dst & 0xFF); //Dummy cycle SendSQI_Byte(Dst & 0xFF); //Dummy cycle SendSQI_Byte(Dst & 0xFF); //Dummy cycle //if (burstlength>256) // {burstlength=256;} for (i=0;i<(burstlength);i++) { data_256[i]=GetSQI_Byte(); } CE_High(); /* disable device */ }
La dernière fois que tu m'a parlé de SendSqi() j'ai arrêté de te répondre
Je sais bien, que je ne dois pas prendre du SQI puisque je suis en SPI, seulement j'avais juste un doute au vue de l’appellation de la fonction, je l'ai donc repris en modifiant les fonctions par du transfert SPI.
Code:void SPI_Read_Burst(unsigned long Dst, unsigned char burstlength) { unsigned int i; i=0; CE_Low(); /* enable device */ Send_Byte(0xEC); /* read command */ Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */ Send_Byte(((Dst & 0xFFFF) >> 8)); Send_Byte(Dst & 0xFF); Send_Byte(Dst & 0xFF); //Dummy cycle Send_Byte(Dst & 0xFF); //Dummy cycle Send_Byte(Dst & 0xFF); //Dummy cycle //if (burstlength>256) // {burstlength=256;} for (i=0;i<(burstlength);i++) { data_256[i]=Get_Byte(); } CE_High(); /* disable device */ }
dans le processus du main, j'ai donc récupérer
2a. au 4a.
Arrivé au 3a, tu sais effacer le chip, écrire une page, la lire et vérifier, tout ça en spi.
En début de 3a il y a l"effacement d'un secteur par spi.
Que veux tu de plus, modifier pour que ça marche plus ?
OK, non je souhaite rien modifier évidemment, simplement je me poses des questions et bien que je distingue plus ou moins les opérations, j'ai un peu de mal à voir les limites de chacune des opérations et surtout , faut-il obligatoirement effacer avant d'écrire, enfin c'est les différents processus qu'il faut que je fasse.
Je dois donc reprendre (et pas modifie) les processus correspondant pour l'écriture et la lecture avec les vérifications.
On est dans le même cas de figure que la flash interne. On écrit une page de 256 octets, avec au préalable un effacement du secteur de 4096 octets qui la contient.
OK merci pour tes précisions,
Histoire de comprendre ce que fait le main pour les utiliser au mieux, car pour moi tout n'est pas forcement évident comme tu sais (:
en 3a. on vient donc effacer un secteur de 4096 octet, seulement il s'agit d'un exemple et tout n'est pas à utilisé je suppose, car si je dis pas de bétise (ce qui serait rare)
dans cette exemple on viendrait effacer 2 secteurs de 4096 ? un dans lequel on vient mettre FF et l'autre AA , d'ou mon incompression car un secteur effacé c'est plutôt du FF non ?
Il déverrouille tous les blocs protégés.
Ensuite il fait un effacement complet de la flash
Ensuite il écrit 512 pages de 256 octets de 0x00000 à 0x20000, avec l'octet 170 = 0xAA
il a donc écrit 32 secteurs qui contiennent tous 0xAA
Ensuite il efface un seul secteur, le premier, de 0x00000 à 0x01000
Ensuite il lit les 2 premiers secteurs, l'un effacé contient 0xFF, l'autre contient toujours les 0xAA
Bon a priorie, des données transitent
j'ai fais en sorte de laisser le dévérouillage,
effacement complet puis la réécriture
Code:void nvm_write_data_spi (char *buf, int size) { unsigned long i,j,k,highest_address; check=0; highest_address=0x1FFFF; Portassign(); CE_High(); WP_High(); Reset_Hold_High(); init(); SPI_WREN(); block_protection_18[0]=0x00; block_protection_18[1]=0x00; block_protection_18[2]=0x00; block_protection_18[3]=0x00; block_protection_18[4]=0x00; block_protection_18[5]=0x00; block_protection_18[6]=0x00; block_protection_18[7]=0x00; block_protection_18[8]=0x00; block_protection_18[9]=0x00; block_protection_18[10]=0x00; block_protection_18[11]=0x00; block_protection_18[12]=0x00; block_protection_18[13]=0x00; block_protection_18[14]=0x00; block_protection_18[15]=0x00; block_protection_18[16]=0x00; block_protection_18[17]=0x00; SPI_WriteBlockProtection(); SPI_Wait_Busy(); SPI_WREN(); SPI_Chip_Erase(); //Erase the chip SPI_Wait_Busy(); i=0; k=0; SPI_WREN(); while(i<highest_address) // while(i < size) { for (j = 0; j < 256; j++) { data_256[j] = buf[k]; k++; if(k>size)k=0; } SPI_WREN(); SPI_Page_Program(i); SPI_Wait_Busy(); i=i+256; } }
Pour l'instant, je ne sais pas trop ce que ça peut donnée car je n'ai pas encore fait la relecture,
ça te semble pas trop truffé de bétises ?
On ne sait toujours pas si tu l'as écrite cette flash, si la vérification s'est bien passée, si l'effacement des secteurs marche ...
En fait on sait rien
Désolé, j'ai pas pu approfondir pendant une grande partie de l'après midi d'imprévu, je suis actuellement en train de coder les fonctions d'écriture et de lecture.
Mais pour répondre à tous ces questionnement, j'ai besoin de coder les fonctions cité, ci-dessus
Pour savoir si j'écris bien, il faut pouvoir relire derrière pour vérifié, mise à part si j'ai loupé quelques choses.
HA oui, autant pour moi déjà avec les fonctions du main ensemble en testant la variable "tempcheck"
IL FAUT FAIRE MARCHER LE DRIVER DE SST SANS LE MODIFIER !
en augmentant la variable highest_address, le driver peut écrire tout la flash, puis la vérifier.
et quand il aura effacé, écrit et vérifié des mégaoctets sans une seul erreur, alors tu pourras y toucher, et là si ça marche plus, on saura pourquoi ....
ok, j'ai tendance à vouloir aller vite, je sais de la méthode (:IL FAUT FAIRE MARCHER LE DRIVER DE SST SANS LE MODIFIER !
en augmentant la variable highest_address, le driver peut écrire tout la flash, puis la vérifier.
et quand il aura effacé, écrit et vérifié des mégaoctets sans une seul erreur, alors tu pourras y toucher, et là si ça marche plus, on saura pourquoi ....
si je dis pas trop de bétises, je testes les différentes partie du main jusqu'a la fin du 3a. et vérifiant la variable
tempcheck, si celle-ci est à 1 c'est que c'est ok , c'est ça ?
Là j'ai donc repris cette partie là
Code:void write_data (void) { unsigned int tempdatalong; unsigned long i,j,highest_address; //int status; check=0; highest_address=0x1FFFF; status=1; //1 means memory/code works and 0 means fault has occured. Portassign(); CE_High(); WP_High(); Reset_Hold_High(); init(); SPI_WREN(); tempdatalong = SPI_Read_Status_Register(); tempdatalong = tempdatalong<<8; tempdatalong = tempdatalong | 0x82; SPI_Write_Status_Register(tempdatalong, 2); // Test Jedec ID Jedec_ID_Read(); if (Manufacturer_Id == 0xbf && Device_Type == 0x26 && Device_Id == 0x43) { check = 1; } else { check=0; } /************* 2a. Page program whole chip using SPI protocol and verify its OK. *********/ i=0; while (i<=255) { data_256[i]=170; i++; } SPI_WREN(); block_protection_18[0]=0x00; block_protection_18[1]=0x00; block_protection_18[2]=0x00; block_protection_18[3]=0x00; block_protection_18[4]=0x00; block_protection_18[5]=0x00; block_protection_18[6]=0x00; block_protection_18[7]=0x00; block_protection_18[8]=0x00; block_protection_18[9]=0x00; block_protection_18[10]=0x00; block_protection_18[11]=0x00; block_protection_18[12]=0x00; block_protection_18[13]=0x00; block_protection_18[14]=0x00; block_protection_18[15]=0x00; block_protection_18[16]=0x00; block_protection_18[17]=0x00; SPI_WriteBlockProtection(); SPI_Wait_Busy(); SPI_WREN(); SPI_Chip_Erase(); //Erase the chip SPI_Wait_Busy(); i=0; SPI_WREN(); while(i<highest_address) { SPI_WREN(); SPI_Page_Program(i); SPI_Wait_Busy(); i=i+256; } SPI_WREN(); j=0; while(j<highest_address) { // SPI_Set_Burst(0x03); // SPI_Read_Burst(j, 64); //verify that it got programmed. // SPI_Wait_Busy(); SPI_HighSpeed_Read_Cont(j, 64); for (i=0;i<64;i++) { if (data_256[i]==170) {tempcheck&=1; } else { tempcheck=0; } } j=j+64; } if ((tempcheck == 1)&&(status==1)) {check=(check+1); status=status&1;} else {status=0;}
sans rien modifier et tempcheck reste à 0 pour le moment
Bon en conclusion des tests :
Pour le JEDEC, ça fonctionne bien comme annoncé plus haut
Pour l'écriture, ça à l'aire de bien fonctionner également, mon tempcheck=1 et check=1:
Pour l'effacement, fonctionne en partie, c'est à dire que j'efface tout et pas qu'une partie.Code:void write_data_verif (void) { unsigned int tempdatalong; unsigned long i,j; //int tempdata; //int status; tempcheck=1; check=0; status=1; //1 means memory/code works and 0 means fault has occured. SPI_WREN(); tempdatalong=SPI_Read_Status_Register(); tempdatalong = tempdatalong<<8; tempdatalong = tempdatalong |(0x82); // tempdatalong = tempdatalong & ~(0x02); SPI_Write_Status_Register(tempdatalong, 2); tempdata=SPI_Read_Configuration_Register(); i=0; while (i<=255) { data_256[i]=170; i++; } SPI_WREN(); block_protection_18[0]=0x00; block_protection_18[1]=0x00; block_protection_18[2]=0x00; block_protection_18[3]=0x00; block_protection_18[4]=0x00; block_protection_18[5]=0x00; block_protection_18[6]=0x00; block_protection_18[7]=0x00; block_protection_18[8]=0x00; block_protection_18[9]=0x00; block_protection_18[10]=0x00; block_protection_18[11]=0x00; block_protection_18[12]=0x00; block_protection_18[13]=0x00; block_protection_18[14]=0x00; block_protection_18[15]=0x00; block_protection_18[16]=0x00; block_protection_18[17]=0x00; SPI_WriteBlockProtection(); SPI_Wait_Busy(); SPI_WREN(); SPI_Chip_Erase(); //Erase the chip SPI_Wait_Busy(); i=0; SPI_WREN(); while(i<highest_address) { SPI_WREN(); SPI_Page_Program(i); SPI_Wait_Busy(); i=i+256; } SPI_WREN(); j=0; while(j<highest_address) { //SPI_Set_Burst(0x03); //SPI_Read_Burst(j, 64); //verify that it got programmed. //SPI_Wait_Busy(); SPI_HighSpeed_Read_Cont(j, 64); for (i=0;i<64;i++) { if (data_256[i]==170) {tempcheck&=1; } else { tempcheck=0; } } j=j+64; } if ((tempcheck == 1)&&(status==1)) {check=(check+1); status=status&1;} else {status=0;} }
Donc quand je fais ça mon tempcheck=1 et check=2
et pareil pour l'effacement d'un bloc mon tempcheck=1 et check=3 quand je fais çaCode:void sector_erase_verif (void) { //unsigned int tempdatalong; unsigned long k,j; //int status; // tempcheck=1; // check=0; // status=1; //1 means memory/code works and 0 means fault has occured. SPI_WREN(); SPI_Sector_Erase(0); //Do Sector Erase SPI_Wait_Busy(); /* j=0; while (j<(4096)) { SPI_WREN(); SPI_Set_Burst(0x03); SPI_Read_Burst(j, 64); for (k=0;k<63;k++) { if (data_256[k]==0xff) // Verify that the values are correct {tempcheck&=1;} else { tempcheck=0;} } j=j+64; }*/ j=4096; while (j<(4096*2)) { SPI_WREN(); SPI_Set_Burst(0x03); SPI_Read_Burst(j, 64); for (k=0;k<63;k++) { //if (data_256[k]==0xAA) // Verify that the values are correct if (data_256[k]==0xFF) {tempcheck&=1;} else { tempcheck=0;} } j=j+64; } if ((tempcheck == 1)&&(status==1)) {check=(check+1); status=status&1;} else {status=0;} }
Même si c'est pas parfais, on peut dire, que j'écris bien mais j'efface tout au lieu que ce soit par partieCode:void block_erase_verif (void) { //unsigned int tempdatalong; unsigned long k,j; //int status; // tempcheck=1; //check=0; // status=1; //1 means memory/code works and 0 means fault has occured. SPI_WREN(); SPI_Block_Erase(0); //Do Sector Erase SPI_Wait_Busy(); j=0; while (j<(0x2000)) { SPI_WREN(); SPI_Set_Burst(0x03); SPI_Read_Burst(j, 64); for (k=0;k<63;k++) { if (data_256[k]==0xff) // Verify that the values are correct {tempcheck&=1;} else { tempcheck=0;} } j=j+64; } /* j=0x2000; while (j<(0x3000)) { SPI_WREN(); SPI_Set_Burst(0x03); SPI_Read_Burst(j, 64); for (k=0;k<63;k++) { if (data_256[k]==0xAA) // Verify that the values are correct {tempcheck&=1;} else { tempcheck=0;} } j=j+64; }*/ if ((tempcheck == 1)&&(status==1)) {check=(check+1); status=status&1;} else {status=0; check|=0x44;} }
SPI_Read_Burst() est une fonction que tu as modifié ?
quelle est la fréquence sur la pin SCK ?
Je sais bien que tu m'a dis de rien modifier, mais effectivement SPI_Read_Burst() faisait apparaître la fonction SendSQI_Byte, j'ai pensé que c'était une erreur et l'ai corrigé par Send_Byte.
Pour la fréquence, je vais revérifier, Au dernière mesure j'avais autour de 3Mhz Mais j'ai un douteCode:void SPI_Read_Burst(unsigned long Dst, unsigned char burstlength) { unsigned int i; i=0; CE_Low(); /* enable device */ Send_Byte(0xEC); /* read command */ SendSQI_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */ SendSQI_Byte(((Dst & 0xFFFF) >> 8)); SendSQI_Byte(Dst & 0xFF); SendSQI_Byte(Dst & 0xFF); //Dummy cycle SendSQI_Byte(Dst & 0xFF); //Dummy cycle SendSQI_Byte(Dst & 0xFF); //Dummy cycle //if (burstlength>256) // {burstlength=256;} for (i=0;i<(burstlength);i++) { data_256[i]=GetSQI_Byte(); } CE_High(); /* disable device */ }
Tu as la fonction SPI_HighSpeed_Read_Cont() qui marche bien, et tu vas en chercher une seconde qui utilise le SQI.
Je comprends rien à ta démarche.
Je t'avais écrit qu'il fallait s'arrêter au 3a, les blocs et SPI_Read_Burst() on en a rien a faire, à moins de vouloir déposer une thèse sur la SST26VF064B.
Pour la vérification de l'effacement du premier secteur, tu utilises la fonction SPI_HighSpeed_Read_Cont().
Là on modifie un peu, mais ON TOUCHE PAS au contenu des fonctions.
Ton programme s'arrête là. Tu mets 0x7FFFFF dans highest_adress. et tu vérifie que check est égal a 3 à la fin du 3A.
check = read_jedec + write_read_verify + erase_sector_verify
Et je radote en te disant que là tu sais effacer un secteur de 4096 octets, et derrière écrire 1 à 16 pages qu'il contient.
OK, j'ai effectivement été trop loin et m'arret en fin du 3a. et remplacer SPI_Read_Burst() par SPI_HighSpeed_Read_Cont() pour la partie effacement secteur.Tu as la fonction SPI_HighSpeed_Read_Cont() qui marche bien, et tu vas en chercher une seconde qui utilise le SQI.
Je comprends rien à ta démarche.
Je t'avais écrit qu'il fallait s'arrêter au 3a, les blocs et SPI_Read_Burst() on en a rien a faire, à moins de vouloir déposer une thèse sur la SST26VF064B.
Pour la vérification de l'effacement du premier secteur, tu utilises la fonction SPI_HighSpeed_Read_Cont().
Là on modifie un peu, mais ON TOUCHE PAS au contenu des fonctions.
Ton programme s'arrête là. Tu mets 0x7FFFFF dans highest_adress. et tu vérifie que check est égal a 3 à la fin du 3A.
check = read_jedec + write_read_verify + erase_sector_verify
Et je radote en te disant que là tu sais effacer un secteur de 4096 octets, et derrière écrire 1 à 16 pages qu'il contient.
à 0x1FFFFF dans highest_adress, j'ai bien check=3 mais à partir de 3FFFFF check est à 1, je regarde d'ou ça peut provenir, peut-être qu'il faut que je passe sur ma carte directement, car mon starter kit sur lequel je fait actuellement mes tests j'ai du fil pour connecter la flash, ce doit-être perturbant
En fait, jusqu'à 3FFFF CHECK=3
Après avoir exécuté SPI_WriteBlockProtection(), utilise la fonction SPI_ReadBlockProtection() pour lire les 18 octets de protection des blocs.
Il y a peut être un lock quelque part.