Arduino, AT*’s, AVR Studio/AVRdude, ISP, JTAG, debugWIRE e afins
Boa noite amiguinhos!
A pedido de algumas familias, volto para monologar um pouco sobre algumas inutilidades que me ocuparam o fim de semana. Penso que também poderá ser util para o patrão deste blog!
Aqui há algum tempo falei com nosso amiguinho fALSO sobre o facto de ele utilizar o AVR Studio para brincar com o seu arduino. Na altura a conversa ficou um bocado por ali, não falamos muito sobre o caso, mas hoje vou blolar sobre isso com um mini-how-to inútil.
Resumindo o conteúdo, irei apresentar algumas alternativas para a programação do arduino, passando por avr studio e avrdude, utilizando alguns programadores/debuggers.
Ora bem, primeiro que tudo, os únicos arduinos que andam aqui por casa perdidos são os "duemilanove"... existem varias versões do arduino, embora a mais conhecida/usada penso que seja a "mega".
Duas grandes diferenças entre a "mega" e a "duemilanove" são a expansibilidade (dado que a versão "mega" traz um atmega1280 e a "duemilanove" traz um atmega168...). Resumindo: "mega" is better.
Embora este how-to se baseie na versão "duemilanove", irei referir os procedimentos para a versão "mega" quando estes diferirem do que for dito, a fim de quem tenha esta versão possa seguir os passos.
Existem para já duas grandes diferenças no que toca a debugging entre o ATmega1280 e o ATmega168:
- o ATmega1280 na versão "mega" suporta JTAG para debugging/programming, que no caso do chip instalado no arduino mega, o JTAG vem desabilitado por defeito para que existam mais ADC's (Analog/Digital Converters) disponíveis. Ou seja, com JTAG habilitado, teremos menos quatro analog inputs no arduino.
- o ATmega168 na versão "duemilanove" suporta debugWIRE para debugging, que vem desabilitado por defeito, a fim de o ISP programming interface (SPI) esteja habilitado dado que as duas tecnologias partilham o pin RESET(debugWIRE)/RESET(SPI) (que é o pin nr 1 do chip). Ou seja, se um estiver habilitado, o outro não está. Isto pode ser especialmente perigoso, mas mais à frente vou dar mais uma palavrinha sobre isto, mas para já vamos prosseguir com outras coisas ainda menos úteis que isto. O facto do ATmega168 ter debugWIRE em vez de JTAG é unica e exclusivamente devido a ter menos pins disponiveis. Isto acontece com todos os chips da ATmel. Todos aqueles que tenham poucos pinos, utilizam debugWIRE uma vez que esta interface apenas utiliza um pin bidirecional, ao contrario de JTAG que no minimo necessita de 4.
Arduino, Bus Pirate & avrdude
Para habilitarmos JTAG ou debugWIRE nos respectivos arduinos, passa pela alteração do estado dos Fuses. Os fuses são basicamente flag registers que controlam o comportamento do chip. No caso dos chips da atmel existem 3 familias de fuses nos ATmega: lfuse, hfuse e efuse (Low, High e Extended Fuse Bytes)... portanto poderemos ter até 24 configurações on/off nesta familia de chips.
Cada ATmegaXxx têm o sua propria configuração de fuses. Digo isto pois o mapa de bits da configuração dos fuses pode n coincidir de modelo para modelo dentro da familia ATmega. Cada chip tem o seu datasheet que deverá ser consultado antes de se efectuar qualquer configuração nos fuses. Alerto que pode ser fácil brickar um chip através das configurações dos fuses e, sem as ferramentas certas, pode ser dificil voltar ao estado anterior.
Uma das formas mais economicas de ler/programar os fuses nestes chips, é usando o Bus Pirate e o avrdude.
Actualmente o avrdude suporta o bus pirate, mas ontem tive alguns problemas com o driver (da versão avrdude 5.10) pois não é compativel com a nova versão de firmware 5.7 (latest até à data do bus pirate), portanto tive que fazer um pequeno patch:
---BOF---
--- ./buspirate.c 2010-01-19 10:39:11.000000000 +0000
+++ ../avrdude-5.10-new/buspirate.c 2010-09-04 03:01:06.000000000 +0100
@@ -257,7 +257,7 @@
static int buspirate_is_prompt(char *str)
{
/* Prompt ends with '>' all other input probably ends with '\n' */
- return (str[strlen(str) - 1] == '>');
+ return (str[strlen(str) - 2] == '>');
}
static int buspirate_expect(struct programmer_t *pgm, char *send,
@@ -533,7 +533,7 @@
static void buspirate_enable(struct programmer_t *pgm)
{
- unsigned char *reset_str = "#\n";
+ unsigned char *reset_str = "#\ny";
char *rcvd;
int fw_v1 = 0, fw_v2 = 0;
int rc, print_banner = 0;
@@ -600,7 +600,7 @@
serial_recv_timeout = 100;
buspirate_reset_from_binmode(pgm);
} else
- buspirate_expect(pgm, "#\n", "RESET", 1);
+ buspirate_expect(pgm, "#\ny", "RESET", 1);
}
static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p)
---EOF---
Atenção que este patch torna o avrdude incompativel com as versões de firmware < 5.x pois não tive paciencia para manter a retrocompatibilidade... mas penso q era mais uma inutilidade inútil para ocupar tempo.
As sources do avrdude podem ser downloaded here: http://download.savannah.gnu.org/releases/avrdude/avrdude-doc-5.10.tar.gz
Depois de se instalar o avrdude com a patch anterior, está na hora de ligar cabinhos:
Ora bem, o que aqui foi feito foi o seguinte:
1 - Interligou-se o bus pirate à interface SPI do arduino "duemilanove", cujo pinout do arduino é:
MISO (1) +Vcc (2)
SCK (3) MOSI (4)
RESET (5) GND (6)
2 - E as cores dos cabos (e não dos aligators, pois diferem) do Bus Pirate que correspondem ao SPI são:
MOSI - Cinzento
MISO - Preto
SCK (CLK) - Rosa/Violeta
RESET (CS) - Branco
+5V (+Vcc) - Laranja
GND - Castanho
3 - Colocar uma resistencia de 10k entre o RESET e Vcc
4 - Embora o Bus Pirate possa alimentar o arduino, o avrdude não vai permitir que a PSU fique enabled, uma vez que é feito um reset sempre que se faz uma operação. Uma opção é mais uma vez alterar o driver do avrdude para o buspirate não fazer reset, no entanto, é mais facil alimentar externamente o arduino com uma PSU externa. Portanto deverão ligar o pin 2 (+) e 6 (-) a algo que forneça +5VDC.
5 - Ligar o bus pirate por usb à maquina onde se encontra o avrdude e efectuar o seguinte comando (verificar a path para o ficheiro de configuração do avrdude):
ATmega1280 (arduino "mega"):
# avrdude -C./avrdude.conf -pm1280 -cbuspirate -P/dev/ttyUSB0 -b115200 -v
ATmega168 (arduino "duemilanove"):
# avrdude -C./avrdude.conf -pm168 -cbuspirate -P/dev/ttyUSB0 -b115200 -v
Isto vai largar alguma tralha que neste momento não interessa ao menino jesus... o mais importante aparece mais para o fim:
(O dump seguinte refere-se ao ATmega168 [duemilanove])
Reading | ################################################## | 100% 0.10s
avrdude: Device signature = 0x1e9406
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DD
avrdude: safemode: efuse reads as 0
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DD
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK
A partir daqui já temos alguma informação que nos interessa. De acordo com a datasheet do ATmega168, poderiamos activar o debugWIRE activando o 6º bit do hfuse. Neste caso, mudariamos o valor de 0xDD para 0xFD e ficariamos com uma meio de debugar o chip no avr studio. No entanto, isto também iria causar que o SPI fosse desabilitado, e não teriamos forma de programar o chip por SPI nem de alterar o hfuse por este meio. Teriamos de reabilitar o SPI por outros meios. Resumindo, o ATmega168 não é um bom chip se a nossa intenção for efectuar debugs, a menos que se tenham uma serie de ferramentas que facilitem o processo (alguns programadores da atmel) mas isso já não seria uma solução barata.
Se, por outro lado, fizermos um fetch do state dos fuses no ATmega1280 ("mega") teriamos o seguiunte valor do hfuse:
avrdude: safemode: hfuse reads as 9A
Segundo a datasheet do ATmega1280, se activarmos o 7º bit do hfuse, activaremos o JTAG sem desabilitar o SPI, o que nos permite ter DUAS interfaces de programação (JTAG e SPI) e uma de debugging (JTAG) em simultaneo. No entanto, iremos perder quatro ADC's, significando que o arduino ficará com menos 4 analog inputs -> ADC4, ADC5, ADC6 e ADC7 que correspondem respectivamente aos JTAG pins -> TCK, TDO, TMS e TDI.
Ora para isto ser concluido, temos de alterar o valor de 0x9A (10011010b) para 0xDA (11011010b). Para isso teremos de executar o seguinte:
# avrdude -C./avrdude.conf -pm1280 -cbuspirate -P/dev/ttyUSB0 -b115200 -v -U hfuse:w:0xda:m
Após isto, temos novas ferramentas para desenvolver, programar e debugar o arduino. Para aproveitar-mos o JTAG, necessitamos de um JTAG programmer para, pelo menos, a familia ATmega*. Existem um mini-avr jtag programmers no ebay baratuxos, que custam à volta de 18 dollares com free shipping, vindos dos confins do mundo. Demoram uns 15 dias a chegar, mas n se paga alfandega dado que o valor é inferior a 22 (ou 25) euros.
Estes mini-avr jtag programmers têm um pequeno senão! Não funcionam bem (pelo menos cmg não funcionam de todo) em win7 64-bits. O problema reside no chip que faz a conversão usbserie, que é um PL3203. Os drivers para estes chips em 64-bits não são flor que se cheire. Se contactarem o seller do ebay, ele vai-vos enviar um driver que diz que funciona, mas eu nunca o usei pq não está assinado. A minha solução passou por alterar o chip. Retirei o PL3203 e coloquei um FT232RL que, na minha opinião, são muito superiores a nível de suporte e efeciencia e o pinout é *quase* igual ao PL3203 (existe um ground no PL3203 que não está connected no FT232RL, mas esse ground não é usado no mini-avr jtag programmer, portanto o FT232RL torna-se assim um substituto directo neste caso). Se estiverem dispostos a fazer o mesmo, poderão adquirir o chip na farnell ou no ebay (FT232RL vem com package SSOP28 (atenção as letras RL)) e para o substituir deverão verificar se têm o material seguinte:
1 - Uma infrared soldering station OU uma hot air gun (se usarem uma hot air gun, podem abdicar do masking com folha de aluminio, no entanto se colocarem, só fará bem e não mal pois ajudará um pouco na dissipação do calor ao longo da folha).
2 - Flux em pasta
3 - Kapton tape E folha de aluminio (se possivel, que se possa colar tipo fita cola. podem comprar aqueles rolos de junção e isolamento de escapes de esquentadores que se vende no AKI).
4 - Um pincel e uma pinça
Aqui vão algumas photos do procedimento (algumas não estão muito focadas pq sou um troglodita a tirar fotos... depois parecem-me estar bem no ecrã minusculo da camara, mas depois qd passo pro PC tão uma merda valente):
Resumindo os passos efectuados:
1 - Mask de kapton tape em volta do chip. A kapton tape é uma "fita cola" que suporta cerca de 400ºC. A maioria não a usa quando utiliza folha de aluminio, mas eu uso como uma camada extra just in case.
2 - Mask de folha de aluminio em torno do chip. Isto irá simultaneamente refletir parte da radiação infrared e agir como um (ligeiro) dissipador, fazendo com que o q está na periferia do chip não seja tão aquecido como o chip.
3 - Aplicação de flux nas leads do chip. É um desoxidante poderoso quando activado a altas temperaturas. Irá impedir que os contactos não oxidem e irá facilitar o processo de soldadura.
4 - Colocar o pre-heater a 90ºC (mais não, devido aos plasticos que se encontram na board poderão deformar) e aplicar de radiação infrared. Programar a station para 270 ou 280ºC.
5 - Após remover o chip com uma pinça, deixar arrefecer e limpar toda a area onde se encontrava o chip com Isopropanol (IPA).
6 - Colocar um pouco de flux nos contactos do novo chip FT232RL, alinhar com os contactos da board e aplicar novamente infrared a 270/280ºC durante 6 ou 7 segundos.
7 - Verificar se o chip está fixo, deixar arrefecer e limpar novamente a area das leads com IPA.
Alternativamente, pode-se usar uma hot air gun para desoldar/soldar os chips, mas é um processo mais demorado e mais perigoso para os chips.
ATENÇÃO: A radiação infrared da estação é muito prejudicial para os olhos (e mãos se as la meterem). Utilizar SEMPRE oculos de protecção infrared, para alem do filtro que vem com a estação. O efeito é mais ou menos o mesmo que estarem a olhar para o sol.
Se tudo for feito sem espinhas, o resultado esperado será este:
O pinout deste mini-programmer é exactamente o mesmo do programador JTAGICE da ATmel. Basta verem o manual e interligar os pinos analogicos do arduino (referidos em cima com a correspondencia JTAG) aos pinos do mini-programador (Um site útil com pinouts de alguns fabricantes: http://www.jtagtest.com/pinouts/) . No AVR Studio deverão selecionar o programador JTAGICE. Mais à frente neste post encontrarão algumas ilustrações de como usar um programador no AVR studio (não será o mini-programador, pois quero poupar espaço e demonstrar outras coisas, mas os procedimentos são os mesmos).
AVRISP / AVR JTAG ICE e AVRstudio
Agora vamo-nos focar no AVRISP / AVR JTAG ICE programmer e as maravilhas (ou inutilidades) que esta peça de hardware faz juntamente com o AVRstudio.
Este programador é mais caro que o mini-avr jtag programmer, mas também suporta muitos mais familias de chips da Atmel (não só da familia mega) e tem dois modos de operação -> ISP ou JTAG (que é podem ser activados por um switch no programador -> para a direita activa ISP, para a esquerda activa JTAG). Existem alguns programadores da Atmel, cada um com a sua função. Poderão ser todos consultados no site da atmel. Este é um dos que suporta grande parte dos chips excepto a familias XMEGA e AT32* (e mais algumas). Caso pretendam um programador com suporte as familias xmega e a AT32*, deverão optar por uma versão do mkII.
Como já foi visto anteriormente, tanto o arduino "mega" como o "duemilanove" tem uma interface ISP, que são os 6 pins que se podem encontrar no caso do "mega" +/- a meio da board, e no caso do "duemilanove" na extremidade da board.
Agora vamos ligar este programmer ao arduino, utilizando um adaptador ISP de 10pin para 6pin (para atmel pinout):
Podemos utilizar uma bateria de 9V ligada directamente ao arduino, mas APENAS se esta for ligada no socket de alimentação. Pois à entrada deste socket, existe um regulador que irá fornecer os +5VDC ao atmega. Se ligarem directamente uma bateria de 9V no pinout do ISP, arriscam-se a chamuscar a coisa.
Verificar se o switch do programador está na posição da direita, e caso afirmativo, estamos prontos para brincar com o AVRstudio.
Tudo aquilo que fizemos com o avrdude, pode ser feito com uma interface bem mais simpatica no AVRStudio. Verificar e alterar fuses, efectuar backups de flash, eeprom, fuse states, enfim, uma serie de inutilidades. Seguem alguns screenshots:
Conectar ao programador em ISP mode:
Fuses:
Backups:
E pronto, não vou fazer um how-to também do avrstudio, pois não é esse o intuito do post, mas sim mostrar como se pode usar o AVRstudio para programar o arduino, a fim de expandir os meios (ou ferramentas, ou como lhe queiram chamar) de desenvolvimento.
Falta-me acrescentar que caso não tenham nenhum programador da atmel (ou equivalente) nem o mini-avr programmer, podem sempre usar o buspirate e o avrdude para programar os chips. Podem desenvolver tudo no AVRStudio e compilar, depois para flashar utilizam o avrdude com o seguinte comando (neste caso para programar a flash. No caso da eeprom deverão substituir a -U flash por -U eeprom, pro caso dos fuses -U hfuse ou lfuse ou efuse. Consultar o manual do avrdude para uma lista detalhada da flag -U):
# avrdude -C./avrdude.conf -pm168 -cbuspirate -P/dev/ttyUSB0 -b115200 -v -U flash:w:/path/para/o/file.hex:i
ou para o ATmega1280:
# avrdude -C./avrdude.conf -pm1280 -cbuspirate -P/dev/ttyUSB0 -b115200 -v -U flash:w:/path/para/o/file.hex:i
Bom, penso que já falei de inutilidades suficientes por hoje, espero que dentro desta tralha toda, isto motive o fALSO a mexer mais no seu arduino :D
A minha alma está parva... trocar o chip dum adaptador série-usb? Não fazia ideia que tal coisa era realizável por humanos sem fábricas.
Apercebi-me que tanto neste post como no anterior a parte do arduino em si não envolve soldaduras malucas, só crocodilos... isso deixa-me alguma esperança! ;)
Grande post.