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

Microcontrolador 8051: Gravando um Firmware no AT89S51 (e o AT89S52) com o Avrdude e um Arduino

Uma vez que os comandos de programação serial do AT89S51 são semelhantes aos dos microcontroladores AVR, me pareceu natural que o avrdude poderia ser usado para programá-lo, usando um Arduino Uno com o sketch ArduinoISP. Existem alguns tutoriais sobre isso na internet, mas quando fui tentar surgiram algumas dificuldades...



Hardware

Aqui não tiver surpresas: basta colocar o cristal com seus capacitores no AT89S51 e ligar os pinos SCK, MISO, MOSI e Reset dele aos pinos 13, 12, 11, 10 do Arduino Uno (para outros modelos, veja os comentários no início do sketch):


Um detalhe: as versões mais recentes do avrdude convivem com o auto-reset do Arduino, dispensando a necessidade de desligá-lo.

Sketch do Arduino

O sketch ArduinoISP, que vem como exemplo junto com a versão 1.8.8 da IDE do Arduino, tem uma parte do suporte ao AT89S: ele sabe que o reset tem polaridade invertida neste caso. Falta, porém acertar a leitura da identificação do chip. Um jeito é usar a opção -F do avrdude para ele ignorar isso, mas é claro que eu preferi consertar.

Basta procurar no sketch a rotina read_signature() e substituí-la pela abaixo:
void read_signature() {
  if (CRC_EOP != getch()) {
    error++;
    SERIAL.print((char) STK_NOSYNC);
    return;
  }
  SERIAL.print((char) STK_INSYNC);
  if (param.devicecode >= 0xe0) {
    uint8_t high = spi_transaction(0x28, 0x00, 0x00, 0x00);
    SERIAL.print((char) high);
    uint8_t middle = spi_transaction(0x28, 0x01, 0x00, 0x00);
    SERIAL.print((char) middle);
    uint8_t low = spi_transaction(0x28, 0x02, 0x00, 0x00);
    SERIAL.print((char) low);
  } else {
    uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
    SERIAL.print((char) high);
    uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
    SERIAL.print((char) middle);
    uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
    SERIAL.print((char) low);
  }
  SERIAL.print((char) STK_OK);
}
O 'devicecode' informa o tipo de microcontrolador, os valores acima de 0xE0 correspondem ao AT89S51 e AT89S52.

Use a IDE do Arduino para compilar e carregar este sketch no Arduino Uno.

Configuração do Avrdude

Eu fiz meus testes com a versão 6.3 do avrdude, que você pode baixar (para Windows) deste link. O arquivo ZIP contém o executável e o arquivo de configuração padrão.

A configuração padrão do avrdude não inclui definições para o AT89S51 e AT89S52. Eu parti da configuração contida neste tutorial. Você pode também copiar o avrdude.conf padrão para um arquivo avr51.conf e acrescentar no final as linhas abaixo:
# Configuracoes para AT89S51 e AT89S52
part
    id               = "89s52";
    desc             = "AT89S52";
    stk500_devcode   = 0xE1;
    signature        = 0x1e 0x52 0x06;
    chip_erase_delay = 500000;
    reset            = dedicated;
    pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                       "x x x x  x x x x    x x x x  x x x x";

    chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                       "x x x x  x x x x    x x x x  x x x x";

    memory "flash"
        size            = 8192 ;             # bytes
        read            = "0 0 1 0 0 0 0 0  x x x a12 a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
        write           = "0 1 0 0 0 0 0 0 x x x a12 a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
        ;
    memory "signature"
        size            = 3;
        read            = "0 0 1 0 1 0 0 0  0 0 0 0 0 0 a1 a0",
                          "0 0 0 0 0 0 0 0  o o o o o o  o  o";
        ;
  ;
part parent "89s52"
    id = "89s51";
    desc = "AT89S51";
    signature = 0x1e 0x51 0x06;
    memory "flash"
        size            = 4096 ;             # bytes
        read            = "0 0 1 0 0 0 0 0  x x x x a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
        write           = "0 1 0 0 0 0 0 0 x x x x a11 a10 a9 a8",
                          "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
      ;
    ;
Um detalhe: nestas linhas são definidos corretamente os comandos para leitura da identificação do AT89S51. Entretanto, ao usar com o ArduinoISP estes comandos não são usados.

Usando o Ardude

Estou supondo que você colocou num diretório o avrdude.exe, o avr51.conf e o firmware que você quer gravar (vamos chamar aqui de firmware.hex). Nos comandos abaixo, estou supondo que o seu Arduino aparece no micro como COM8 (substitui pelo port correto).

Abra uma janela de comando e vá para o diretório onde estão os arquivos. O comando abaixo testa se tudo está correto:


Explicando as opções do avrdude:
  • "-C avr51.conf" manda usar a configuração avr51.conf
  • "-p AT89S51" informa que você vai gravar um AT89S51. Para gravar um AT89S52, troque por "-p AT89S52"
  • "-c arduino" diz que você está usando um Arduino como programador
  • "-P COM8" seleciona a porta COM8 para comunicar com o Arduino
  • "-b 19200" seleciona a velocidade de comunicação
Se aparecer uma mensagem de erro, confira as conexões e os passos acima.

Um detalhe que me fez perder muito tempo: se você não colocar o "-b 19200", o avrdude não detecta que tem algo errado mas diz que a identificação do microcontrolador é a do ATmega328p!

Se deu certo, agora é só gravar:


Um outro detalhe é que não funciona usando um USBtinyISP (talvez mexendo no firmware...). Não cheguei a testar com o USBASP.

6 comentários:

Bruno C. Castro Alves disse...

Bastante interessante, não conhecia o avrdude. Estou estudando algumas placas com microcontroladores, como o Arduino Uno/Nano, NodeMcu ESP8266, Raspberry Pi Pico e o BBC micro:bit (pois é, até hoje me pergunto pq não fiz engenharia eletrônica em vez de engenharia civil, mas divago). Como não tenho uma gravadora de EProm, esse post vai ser uma não na roda e agora vou poder estudar também o 8051 (vi os outros posts sobre a gravação através do ESP8266, mas usar o Avrdude é bem mais prático).

Só uma correção, no trecho 'Para gravar um AT89S51, troque por "-p AT89S51"', deveria ser 'Para gravar um AT89S52, troque por "-p AT89S52".

Daniel Quadros disse...

Bruno, corrigido! Obrigado pelo aviso.

Pablo Monteiro disse...

Preciso dizer, me salvou em um pequeno detalhe (acredito eu).

Já venho estudando e programando AVR (atmega328 especificamente, pois tem muito material disponível), mas me interessei pelos 8051 (arquitetura CISC w 'old school'). Eu estava a usar um Arduino Leonardo (as ISP) para programar o atmega328, e estou tentando usá-lo no 89s51, mas não funcionava de jeito nenhum.

Mesmo seguindo tutoriais de todo tipo e estudando a fundo o datasheet. Problemas que tive em ordem:
* Reconhecer o programador (eu executava o avrdude com stk500v1, mas isso eu resolvi rápido);
* 'Arduino as ISP' comunicar, ler e escrever no AT89S51 (no signature);
* Fazer o upload do HEX (eu que vacilei aqui. Estava executando em C:\Windows\System 32, mudei para o local dos arquivos).

O primordial, que salvou, creio que deve ser a configuração da sketch ArduinoISP. Pois todos as outras coisas estavam corretas, e não fazia sentido não funcionar. Pensava ter perdido meu 89s51

Oswañd disse...

ola estimados,
resolvi um problema q nem esperava...
tinha conectado um led via VCC pro pin reset e isso tava me atrapalhando
rsss
no momento q inverti o led e coloquei pra terra resolveu e comecou a programar
só alegria..
valeu pelas correcoes do signature.

Anônimo disse...

não está funcionando para mim. Na hora de gravar aparece:
avrdude: Device signature = 0x000000
avrdude: Yikes! Invalid device signature

Anônimo disse...

Olá, obrigado por compartilhar, encontrei esta lista de videos, um curso para 8051 (AT80S51). Infelizmente estão muito caros os microcontroladores após a pandemia, então pode ser bem procurado esses velhos 8051 com ciclo de máquina de 1/12, segue lista:

https://m.youtube.com/watch?v=AZan-9s49tg&list=PLIPpnPyoo8FksfTDTGmqjGRxhwx5iNog2&index=1