Página 1 de 1

Dúvida em usar Page Write nas memórias I2C

MensagemEnviado: 28 Fev 2012 17:44
por alessandro
Pessoal, estou usando a memória 24LC1025 e estou tendo problemas quando tento gravar um pagina de 128 bytes.

Não sei se estou entendendo errado, mas posso gravar no modo "Page Write " 128 bytes, ok?

fiz um teste e tentei gravar do endereço 0x100~0x17F em seguida 0x180~0x1FF e depois 0x200~0x27F.

Os primeiro seguimentos (0x100~0x17F e 0x180~0x1FF) grava corretamente, mas toda vez que tento gravar algum segmento seguinte a endereços terminados em FF (0x200~0x27F) da problema, simplesmente não grava após endereços terminados FF.

Alguém tem alguma sugestão do que poderia ser? Teria eu errado nos endereços das páginas? (inicio e fim).


Alessandro

MensagemEnviado: 29 Fev 2012 00:02
por barboza
Você esta testando o ACK retornado pela memória?

Esta fazendo o polling para verificar o tempo interno de gravação ou esta esperando o tempo entre as escritas das páginas???

MensagemEnviado: 29 Fev 2012 08:27
por alessandro
Oi barboza,

Estou verificando o ACK retornado pela memória e estou fazendo o polling (na forma de delay, acredito que poderia melhorar fazendo da forma sugerida pelo fabricante de fazer testes na linha durante o ciclo de gravação).

No modo de gravação de um byte somente, se gravar os 128 bytes nesse modo, grava certinho.

Vou implementar o polling descrito no datasheet, talvez o tempo que estava utilizando no polling para escrita de um byte não dê conta de realizar a gravação dos 128 bytes (apesar de ter aumentando o tempo).

Quanto as páginas, tenho que sempre começar no endereço inicial e terminar no endereço final de cada pagina? Ou posso começar no meio da página e terminar no final?

Cada endereço inicial das paginas começam sempre em múltiplos de 128? 0, 128, 256, 384,....?


Alessandro

MensagemEnviado: 29 Fev 2012 09:05
por MOR_AL
alessandro escreveu:Oi barboza,

Estou verificando o ACK retornado pela memória e estou fazendo o polling (na forma de delay, acredito que poderia melhorar fazendo da forma sugerida pelo fabricante de fazer testes na linha durante o ciclo de gravação).

No modo de gravação de um byte somente, se gravar os 128 bytes nesse modo, grava certinho.

Vou implementar o polling descrito no datasheet, talvez o tempo que estava utilizando no polling para escrita de um byte não dê conta de realizar a gravação dos 128 bytes (apesar de ter aumentando o tempo).

Quanto as páginas, tenho que sempre começar no endereço inicial e terminar no endereço final de cada pagina? Ou posso começar no meio da página e terminar no final?

Cada endereço inicial das paginas começam sempre em múltiplos de 128? 0, 128, 256, 384,....?


Alessandro

Quando fiz I2C em assembler para uma memória, descobri que o chip colocava os dados provisoriamente em uma memória com menor capacidade, porém mais rápida. Após algum evento, que já não me lembro, os dados eram transferidos para a memória destino. Isso porque para gravar nelas era necessário um tempo maior.
Já respondi a um tópico desses com muito mais detalhes. Só não me lembro se foi nesse fórum ou no da LabTools. Procure que lá tem muita informação útil que pode ser a resposta para o seu problema.
MOR_AL

MensagemEnviado: 01 Mar 2012 17:42
por alessandro
MOR_AL

Vou dar uma olhada no forum.

Pelo visto aqui, meu problema é fazer o polling. O datasheet diz que quando você termina a escrita via I2C dando um STOP, neste momento a memória entra em ciclo de escrita. Diz que, neste momento, se ficar enviando START+COMANDO WRITE, posso aguarda o ACK quando a memória estiver liberada e então continuar outros processos.

Pelo visto, isso esta vazando de alguma forma, porque quanto coloco um beak point nesta rotina de polling, os dados são gravados corretamente.

Vou continuar fazendo ajustes aqui para ver se resolvo isso, mas qualquer sugestão é bem vinda.

Grato,

Alessandro

MensagemEnviado: 02 Mar 2012 00:52
por barboza
Alessandro, algumas respostas:

Sim, você começar a escrita no meio da página e escrever até o seu final...

Sim, se sua memória tem 128 bytes por página, o acesso ao inicio de cada página será em múltiplos de 128.

O que normalmente faço, é colocar o polling antes de uma escrita, assim se seu driver da EEPROM for chamado para escrever 1 byte ou 1 página, ele não fica preso no final esperando o tempo da memória, seu programa continua normalmente.

Não sei como seu software esta organizado, mas poderia ter escrita em background também, sem ficar preso no driver...

Veja abaixo um código que usei para gerenciar os comandos recebidos pelo driver da EEPROM para acesso as páginas da EEPROM. Depois os comandos são passados para o driver da I2C.

Código: Selecionar todos

// Quantidade de bytes da pagina na escrita
#define DEF_EEP_MSC_PAGE_I2C   (128-1)



/************************************************************************
   FUNCAO:      p_eep_cmd
   PARAMETROS: flag_rw   -   DEFINE SE É LEITURA(1) OU ESCRITA(0) NA EEPROM
            u32_e_eeprom   -   ENDEREÇO NA EEPROM
            *ptr_buf   -   PONTEIRO ONDE OS DADOS SERAO SALCOS OU LIDOS
                        NA RAM
            qtd_bytes   -   QUANTIDADE DE BYTES TRANSFERIDOS
   RETORNO:   NENHUM
   DESCRICAO:   RECEBE OS PARAMETROS PASSADOS E EXECUTA A TRANFERENCIA DOS
            DADOS PARA A EEPROM DE ACORDO SO DADOS RECEBIDOS.
            SE JÁ HOUVER ALGUMA EXECUÇÃO, ESPERA O FIM PARA INICIAR
            O COMANDO PASSADO
*************************************************************************/
void p_eep_cmd   (en_bool flag_rw,   U32   u32_e_eeprom,   U8   *ptr_u8_buf,   U32   u32_qtd_bytes)
{
   // Comando leitura, escreva o endereço primeiro
   if ( flag_rw == EEP_READ )
   {
      // Verifique e espere espaço no buffer para salvar
      while ( !(p_put_cmd_eep   (EEP_WRITE, u32_e_eeprom,   NULL,   0)) );
      // Verifique e espere espaço no buffer para salvar
      while ( !(p_put_cmd_eep   (EEP_READ, u32_e_eeprom,   ptr_u8_buf,   u32_qtd_bytes)) );
   }
   else
   // Comando de escrita (subdividido em páginas)
   {
   U32   ptr_e_eep_fim,   ptr_e_eep_fim_pag;

       ptr_e_eep_fim = u32_e_eeprom + u32_qtd_bytes - 1;

       do
       {
         ptr_e_eep_fim_pag = u32_e_eeprom | DEF_EEP_MSC_PAGE_I2C;

         // Salve o menor
         ptr_e_eep_fim_pag = ( (ptr_e_eep_fim_pag < ptr_e_eep_fim) ? ptr_e_eep_fim_pag : ptr_e_eep_fim );
         
         u32_qtd_bytes = ptr_e_eep_fim_pag - u32_e_eeprom + 1;

         // Verifique e espere espaço no buffer para salvar
         while ( !(p_put_cmd_eep   (EEP_WRITE, u32_e_eeprom, ptr_u8_buf, u32_qtd_bytes)) );

         // Atualize o endereço da EEPROM
         u32_e_eeprom = ptr_e_eep_fim_pag + 1;

         // Atualize o endereço da RAM
         ptr_u8_buf += u32_qtd_bytes;
       }
       while (ptr_e_eep_fim_pag != ptr_e_eep_fim);
   }
}

MensagemEnviado: 02 Mar 2012 09:24
por MOR_AL
Dá uma olhada nesse arquivo.
Eu fiz um I2C em assembler. Com isso tive que verificar os mínimos detalhes.
Tem muita descrição e exemplos de como gravar várias quantidade de dados. Praticamente fiz exemplos de todas as opções.
Pule os detalhes e se concentre nas explicações e nos fluxogramas.
... E me diga se foi útil.

http://www.datafilehost.com/download-f15c7928.html

MOR_AL

MensagemEnviado: 02 Mar 2012 11:13
por RobL
Sua memo não tem mais que 128K bytes. Os endereços não podem estar acima disto.
Normalmente, endereços maior que o tamanho da memo faz ela gravar no seu início. Portanto, para endereços maiores que 128Kb, por exemplo, endereço 0x80 vair gravar no endereço zero.

Nota1 : sua página é de 128bytes mas o total de bits é de 128Kb x 8 = 1024.
Nota 2: O tempo de gravação de uma página é o mesmo de um byte, pois na verdade estas memos só gravam páginas. Em outras palavras, quando se grava um byte o processo interno é o mesmo que gravar uma página, onde somente um byte difere dos demais 0xFF.

MensagemEnviado: 02 Mar 2012 11:31
por barboza
RobL escreveu:Sua memo não tem mais que 128K bytes. Os endereços não podem estar acima disto.
Normalmente, endereços maior que o tamanho da memo faz ela gravar no seu início. Portanto, para endereços maiores que 128Kb, por exemplo, endereço 0x80 vair gravar no endereço zero.

Nota1 : sua página é de 128bytes mas o total de bits é de 128Kb x 8 = 1024.
Nota 2: O tempo de gravação de uma página é o mesmo de um byte, pois na verdade estas memos só gravam páginas. Em outras palavras, quando se grava um byte o processo interno é o mesmo que gravar uma página, onde somente um byte difere dos demais 0xFF.



O endereço 0x80 endereça o byte 128 e não o bit 128K.

A memória em questão é de 1024K bits ou 128K bytes.

O endereço final dela é 0x1FFFF.

MensagemEnviado: 02 Mar 2012 12:11
por RobL
Viajei no endereço do exemplo. A princípio, erradamente, vi gravar fora da faixa de endereço. Não é o caso.

MensagemEnviado: 02 Mar 2012 22:08
por RobL
Os primeiro seguimentos (0x100~0x17F e 0x180~0x1FF) grava corretamente, mas toda vez que tento gravar algum segmento seguinte a endereços terminados em FF (0x200~0x27F) da problema, simplesmente não grava após endereços terminados FF.


Se grava desde zero até o endereço 0x1FF (511d), até 65535, a única mudança é que em 0x200 seta o bit1 do endereço alto(hi).
Veja que em 0x1FF temos H:0000_0001 L:1111_1111 e com 0x200
H:0000_0010 L:0000_0000.
Só se seu SW não está setando o bit1 em diante, ou seja, está limitado a 0x1FF, sendo este o maior valor de endereço.
Estaria usando algum SW que vai até somente 512bytes para uma memo
24LC04 (de 512bytes) ?

Lembre: para endereços acima de 65535, terá que setar o bit16 que fica no byte de controle. Observe que ele não é o bit zero, ou seja, ao estourar 65535, somar 1, seta o bit errado. O SW tem que analisar o endereço se > 65535 e setar o bit para o bloco 2, pois são dois blocos com 64Kb cada.

MensagemEnviado: 03 Mar 2012 13:30
por vtrx
Faça a gravação e leitura sequencialmente,é mais fácil,voce escolhe o endereço inicial e final.

MensagemEnviado: 04 Mar 2012 08:32
por RobL
O objetivo é gravar páginas para ser mais rápido.
Numa gravação sequencial, cada byte levaria o tempo de uma página.
Por exemplo, se for gravar 128 bytes, levaria o tempo de 128 x Tempo de gravação. Se gravar uma página, com 128 bytes, o tempo de gravação será igual ao de um byte, gravado sequencialmente.
Exemplo: Se o tempo de escrita for de 6ms, gravar 128bytes sequencialmente seria Tw=128 x 6 ms = 768 ms . Gravar uma página com 128bytes leva apenas Tw = 6 ms, ou seja, um tempo 128 vezes menor !!!

Gravar sequencialmente, "abre e fecha" a comunicação, de forma completa, a cada byte. Gravar página, primeiro enche um buffer rápido de 128bytes. Após fechar a comunicação, inicia a gravação internamente.
Isto acontece também com qualquer outra forma de gravação, mas a cada byte.

Novamente relembro que gravar um byte ou uma página, com 128bytes, nestas memórias, leva o mesmo tempo.

Faça a gravação e leitura sequencialmente,é mais fácil,voce escolhe o endereço inicial e final.

MensagemEnviado: 04 Mar 2012 09:18
por vtrx
Me expressei errado,a leitura é chamada de sequencial ja a gravação é chamada de 'por páginas'.
Oque muda na verdade e agiliza é o fato do micro não precisar enviar o 'stop' depois do primeiro dado,mas sim 127 bytes de dados após receber cada acknowledge.
Na prática,eu não conseguí medir o desempenho da gravação por páginas pois de qualquer modo a Eeprom tem um tempo mínimo para terminar o cilco de gravação a cada 127 bytes,ja na leitura a diferença é enorme.
Alessandro,poste o fragmento do código.
Voce está setando corretamente o byte de controle?