ACESSANDO A MEMÓRIA ROM(flash) DO C8051F380 / C8051F382
Olá, bom dia atualmente a maioria dos microcontroladores tem uma memória rom interna. Porém ao trabalhar com o C8051F382 percebi que não tem! isso me causou um certo desconforto. buscando por uma solução observei que é possível usar a memoria flash como se fosse uma memoria ROM.
Porém o uso da flash apresenta algumas características relevantes, como o fato de só poder apagar blocos de memorias(512 bytes por vez) em vez de uma só posição, outro problema é que para escrever numa posição obrigatoriamente vc deve apagar aquele bloco de memoria, ou seja, supondo que eu queira escrever na posição 1024, precisarei apagar o bloco de memoria que vai de 512 a 1024, o que pode ser desastroso se não avaliar bem onde se vai mexer pois corre o risco de apagar trechos de memorias que fazem parte do programa principal, uma recomendação e dar uma olhada nos arquivos ".list" ,gerado após compilar o código fonte, para ver como esta a localização da áreas usadas.
O motivo de obrigatoriamente ter que apagar a memoria flash antes de escrever um novo caracteres é devido ao fato de que quando se trabalha na flash para escrever só aceita escrever "0" nas posições, isso se deve a arquitetura como foi projetado, descobri isso fazendo alguns testes aqui, ou seja supondo que eu queira escrever em hexadecimal o valor "0X11" numa posição, e então eu decida escrever o valor "0X08" , o esperado era ler "0X08" porem isso não acontece e é lido "0X00" ou seja onde é zero ele coloca mas onde é 1 não é colocado, descobri isso num código em assembly dai com esse entendimento apliquei ao código que eu fiz em C.
Veja que é possível depois de apagado o bloco da memoria ir escrevendo nas posições, porém se precisar alterar valores já gravados, terá que apagar o bloco de memoria de 512 bytes, apesar de ser uma característica de alguns microcontroladores da Silicon Labs, pode-se recorrer também para o uso de uma memoria externa .
Uma vez explicado os risco e a limitação de hardware podemos agora passar para o código fonte. Neste código são utilizados 2 leds, um para indicar processamento e outro pra indicar que houve uma gravação num trecho de memória, assim quando ligar pela primeira vez o led não acende e a partir da segunda vez ficara acesso indicando uma leitura valida na memória, apesar do código ser simples é uma mão na roda pra que está passando por este problema. Aqui está usando o PORT P0.
O código fonte :
// Target: C8051F382 // Tool chain: Simplicity Studio / Keil C51 9.51 // Command Line: None // Autor: Aguivone Moretti Fogia // Data: 14/10/2021 // //exemplo de como usar a memoria flash como uma memoria ROM, apesar de não ser muito bom essa ideia pois //caso ocorra um ruido ele pode alterar outras areas de memoria. //----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- #include <SI_C8051F380_Register_Enums.h> #include "F380_FlashPrimitives.h" #include "F380_FlashUtils.h" //----------------------------------------------------------------------------- // Global Constants //----------------------------------------------------------------------------- #define SYSCLK 12000000 // Internal oscillator frequency in Hz //leds vermelho e sinal de saida SI_SBIT(LED_gravado, SFR_P0, 0); // LED='0' Ligado SI_SBIT(LED_pisca, SFR_P0, 1); // LED='1' Desligado //----------------------------------------------------------------------------- // Function Prototypes //----------------------------------------------------------------------------- SI_INTERRUPT_PROTO(PCA0_ISR, PCA0_IRQn); void OSCILLATOR_Init (void); void PORT_Init (void); //----------------------------------------------------------------------------- // SiLabs_Startup() Routine // ---------------------------------------------------------------------------- // This function is called immediately after reset, before the initialization // code is run in SILABS_STARTUP.A51 (which runs before main() ). This is a // useful place to disable the watchdog timer, which is enable by default // and may trigger before main() in some instances. //----------------------------------------------------------------------------- void SiLabs_Startup (void) { PCA0MD = 0x00; // Disable watchdog timer } //----------------------------------------------------------------------------- // main() Routine //----------------------------------------------------------------------------- void main (void) { uint16_t LOOP; uint16_t LOOP_max =65000; PORT_Init (); // Initialize crossbar and GPIO OSCILLATOR_Init (); // Initialize oscillator LOOP =0; IE_EA = 0; if(FLASH_ByteRead(0x5FFE)== 0x12) //olhe o datasheet para escolher um local de memoria existente,se for inexistente ele pode travar. { LED_gravado=0; //liga led indicando que posicão da memoria foi gravada } else { LED_gravado=1; //desliga led FLASH_PageErase(0x5FFE);//apaga bloco de 512bytes por vez (setando tudo para 1) // escreve valor na mmemoria - sempre deve apagar a memoria pois ele so escreve zero //é uma limitação do hardware. FLASH_ByteWrite(0x5FFE, 0x12); //grava 0X12H na memoria //na proxima vez que ligar já busca na memoria este valor } while (1) {//pisca led LOOP++; if(LOOP>LOOP_max) { LED_pisca=0; //liga led (pois esta ligado ao vcc) LOOP=0; } if(LOOP ==(LOOP_max/2)) { LED_pisca=1; //desliga led } } } //----------------------------------------------------------------------------- // OSCILLATOR_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // This function initializes the system clock to use the internal oscillator // at 12 MHz. // //----------------------------------------------------------------------------- void OSCILLATOR_Init (void) { OSCICN = 0x83; // Set internal oscillator to run (desabilitou osc interno) // at its maximum frequency(pois setou os 2 ultimos bit) CLKSEL = 0x00; // Select the internal osc. as (SYSCLK/4) // the SYSCLK source } //----------------------------------------------------------------------------- // PORT_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // This function configures the crossbar and GPIO ports. // // P0.0 digital open-drain PCA0 CEX0 // P0.1 digital push-pull // //----------------------------------------------------------------------------- void PORT_Init (void) { OSCICN = 0X81; // IHFOsc Enable, OpcDiv:3MHz CLKMUL = 0XC0; // talvez nem precise neste microcontrolador -> habilita e inicializa pll CLKSEL = 0X03; // SYSCLK derived from the Internal High-Frequency Oscillator. PFE0CN = 0X20; //(para High Speed) Prefetch Engine Control,otimiza tempo de execução lendo 2 bytes de execução por vez /* FLSCL.FOSE(7) = 0 for < 10MHz and 1 for SYSCLK > 10MHz FLSCL.FLRT(4) = 0 for < 25MHz and 1 for SYSCLK > 25MHz */ FLSCL = 0x90; CKCON = 0x30; SPI0CN = 0x02; //Select Mode 3-Wire pra liberar pino NSS P0MDIN = 0xFF; // are digital P1MDIN = 0xFF; // are digital P2MDIN = 0xFF; // are digital P3MDIN = 0xFF; // are digital P4MDIN = 0xFF; // are digital P0MDOUT = 0x10; // enable Switches as open-drain P1MDOUT = 0x00; // enable Switches as open-drain P2MDOUT = 0x00; // enable Switches as open-drain P3MDOUT = 0x00; // enable Switches as open-drain P4MDOUT = 0x04; // enable Switches as open-drain P0SKIP = 0xCF; // TXeRX precisa do Skip pra funcionar P1SKIP = 0xFF; P2SKIP = 0xFF; P3SKIP = 0xCF; XBR0 = 0x01; // CP1AE,CP1E,CP0AE,CP0E,SYSCKE,SMB0E,SPI0E,(UART0E) XBR2 = 0x00; // RESRV,RSRV,RESRV,RESRV,RESRV,RESRV,SMB1E, UART1E XBR1 = 0xC2; // WEAKPUD,(XBARE),T1E,T0E,ECIE,(PCA0ME):000:Nenhum,001:CEX0,010:CEX0eCEX1,... // VDM0CN -> monitor de tensão de reset VDM0CN = 0x80; //Colocado porque senão da problema na gravacao da flash(já estava isso) P4 = 0 ; //portas de p4 desligadas } //----------------------------------------------------------------------------- // End Of File
formatado por http://hilite.me/ 14/10/2021
Nenhum comentário :
Postar um comentário
olá,digite aqui seu comentário!