terça-feira, março 02, 2021

Microcontrolador 8051: Usando um ESP32 para Gravar Firmware em um AT89S51 (parte 2)

Neste post vou concluir o projeto começado no post anterior. Os problemas que eu tive? Aparentemente foi principalmente mau contato (notadamente na fonte de 5V), mas acabei fazendo também alguns ajustes no hardware e software.

Funciona!


Hardware

A única mudança foi no acionamento do acoplador ótico que controla os 5V: coloque um resistor de pulldown (para garantir que não é acionado quando o pino do ESP32 estiver como entrada) e mudei o valor do resistor em série (para garantir que vai conduzir). Provavelmente funciona mesmo sem estas mudanças.

O esquema atualizado (mas ainda não muito bonito):


Software: Páginas WEB

O meu código para esta parte se baseou no exemplo de upload de arquivo da biblioteca AutoConnect. As telas e a navegação entre elas estão meio rústicas, mas funciona.

São apenas três páginas (como a animação no início mostra). Na primeira é feito o upload do arquivo hex, na segunda é disparada a gravação e na última é apresentado o resultado.

Na tela de upload eu usei um "custom uploader handler": uma classe personalizada para tratar a recepção de arquivo. A interface desta classe é composta por três métodos: _open, _write e _close (como se fosse escrita em arquivo). O meu método _write examina os dados para ir montando uma linha (finalizada por '\n'). Quando completa a linha, ela é analisada como uma linha de arquivo HEX e os dados a gravar são salvos num vetor global (chamado de 'firmware'). Em seguida volta a montar e tratar a linha seguinte. É bom lembrar que não há garantia que uma chamada ao _write tenham linhas inteiras, portanto o estado da montagem de linha precisa ser preservado pelo objeto.

Software: Gravação do AT89S51

Este era o principal objetivo do projeto, certo? Em princípio é apenas uma questão de enviar os bytes corretos usando SPI, mas tem alguns detalhes:

  • O clock do SPI não pode passar de 1/16 do cristal usado. Acabei usando um clock de 300KHz (por motivo ignorado* não funcionou com 500KHz). Para selecionar o clock do SPI usei o método setFrequency(), no ESP32 o uso de startTransaction() tem efeitos colaterais além de configurar a SPI..
  • Na maioria dos casos (a exceção é a leitura da Flash por pagina) devem ser enviados quatro bytes para o AT89S51. A resposta que interessa é a que é recebida junto com a transmissão do último byte (lembrando, no SPI transmissão e recepção são simultâneas). Em alguns casos o valor enviado é ignorado pelo AT89S51 (usei 0).
  • As leituras da Flash são imediatas e não precisa de intervalo entre elas.
  • Para saber quando uma operação de apagamento ou escrita encerrou eu usei o recurso de "Data Polling" onde a leitura após a escrita retorna um valor forçadamente diferente enquanto a operação está sendo executada.
  • Para verificar a gravação e testar se a Flash está apagada (só contem 0xFF), usei a leitura por página. Nesta operação são enviados dois bytes (o comando e o número da página). Em seguida devem ser enviados exatamente 256 bytes (o conteúdo deles não importa), para cada byte enviado é recebido um byte que corresponde ao conteúdo da página a partir da posição 0. Com isto se ganha tempo em relação à leitura por byte (para cada posição da Flash teria que enviar 4 bytes), mas tem que tomar cuidado de enviar exatamente os 256 bytes (se enviar menos, os comandos seguintes provocarão leitura, se enviar a mais os bytes a mais serão tratados como comando).
No geral,  apagamento, gravação e verificação são bem rápidos, no total cerca de 2 segundos.

O código completo pode ser visto no github: https://github.com/dquadros/GravadorESP51

Aperfeiçoamentos

O AutoConnect suporta também o ESP8266. Não testei com ele, mas pode ser uma opção para deixar o projeto menor e mais barato.

A forma de gravação da Flash de outros microprocessadores da ATmel é bem parecida. Estudando com carinho os datasheets e sofrendo um pouco com a depuração daria para suportar outros modelos, deixando o gravador mais genérico. 


* minha desconfiança é que o conversor de nível não é rápido o suficiente

Atualização 03/03/21: Funcionou a 750KHz substituindo o conversor de nível por um divisor resistivo no MISO e ligando direto MOSI e SCK. Era a montagem que eu tinha feito inicialmente, mas como não estava funcionando sempre (devido ao mau contato) eu coloquei o conversor de nível.

Nenhum comentário: