Fábio Olivé's Random Bits
Infrequent thoughts about Technology, and sometimes about Consciousness and its infinite forms of expression.
Thursday, June 04, 2015
Sunday, March 22, 2015
Programando pra Atari 2600 no Fedora
Como todo cara old school que começou nos 8 bits, eu sempre gostei de estudar e mexer em máquinas antigas ou emuladores. Eu curto a nostalgia de ter instalados no meu Fedora todos os computadores ou sistemas antigos que marcaram a minha vida digital, como o Atari 2600 (através do stella, via RPMFusion Free), o MSX Expert (através do openmsx), o Amiga 500 (através do e-uae, infelizmente via RPMFusion Non-Free) e, claro, um DOSBox pra não perder o costume. Eu costumava ter uma VM rodando FreeDOS, mas acabei me rendendo à comodidade do DOSBox prontinho. Só cuido pra instalar no DOSBox também o NASM e um bom debugger, como o debug do FreeDOS. O Insight também é bem interessante pra demonstrar a execução passo a passo de programas x86 16 bits (que eu insisto em "infligir" aos meus alunos).
Há mais de 10 anos eu tenho vontade de estudar um pouco mais sobre o processador 6502 e sobre programação pro Atari 2600, já que o 6502 era o "outro" processador de 8 bits que "estragou" a infância de muita gente na minha geração. Eu cresci com o MSX e o processador Z80, e nunca tive muito contato com o 6502, enquanto muita gente (principalmente na América do Norte e Europa) cresceu com o 6502 (Apple IIe, Commodore 64, e até o TK 3000 IIe aqui no Brasil) e não conheceu o Z80. A idéia era matar a vontade de conhecer o 6502 e já brincar de programar pro Atari 2600 como um desafio divertido.
Na época em que bateu essa vontade, eu baixei tudo o que achei de referências, datasheets, tutoriais, listas de opcodes e etc sobre 6502 e Atari 2600, imprimi tudo e... guardei. :-( Nunca tive tempo de voltar nesse material, nem de instalar assemblers pra 6502 e realmente meter a mão na massa. Passados uns dez anos, há alguns meses, estávamos conversando sobre realizar oficinas no Hackerspace de Chapecó, e de repente todo aquele contexto acima me veio à cabeça e pensei: é agora que eu me afundo no Atari! :-) Nada melhor do que me jogar de cabeça na responsabilidade de ter que preparar uma oficina pra finalmente "fazer tempo" e colocar a mão na massa. Pois bem, aqui está o primeiro passo.
O ferramental é simples: precisa do emulador stella, um assembler pra família 6502 (o Atari 2600 usa o 6507, uma versão capada do 6502) e um bom editor de textos (vim, claro). O Fedora tem alguns assemblers de 6502, dentre os quais eu escolhi o atasm por ser o que me pareceu mais simples e direto (pra não dizer tosco). Ajuda também baixar o arquivo vcs.h, do tutorial "2600 101" do site AtariAge, com as constantes usadas para identificar mais facilmente os registradores e endereços mágicos do hardware. 20 anos de uso de Software Livre me ensinaram a sempre verificar a licença dos códigos encontrados por aí, e esse vcs.h não tem licença nenhuma, o que indicaria que não poderíamos usá-lo. Mas na boa, é só um monte de constantes que qualquer pessoa poderia digitar por si mesma lendo os manuais da arquitetura, então não tem stress. Na minha interpretação não constitui um trabalho relevante, então é meramente uma comodidade.
O que eu gostei no atasm é que ele vem com um PDF (eu sou da Geração Manual, não da Geração Tutorial) que explica bem as opções de linha de comando, a sintaxe de assembly e diretivas que ele usa, dá exemplos e não é totalmente estranho (alguns outros eram). :-) Usando a opção "-r" o atasm gera uma imagem "raw" (ao invés de um arquivo objeto pra linkar depois), que é exatamente o que precisamos pra criar um "cartucho" do Atari. Uma linha típica pra compilar (tecnicamente é "montar", mas esse termo nunca me soou bem) um arquivo chamado "oficina-1.asm" e gerar um binário "oficina-1.bin" seria "atasm -r -ooficina-1.bin oficina-1.asm". Pra testar dá pra chamar o stella direto, com "stella oficina-1.bin". Mais barbada que isso não tem! :-) Usando a opção "-v" o atasm também gera uma listagem do código compilado na saída padrão. As demais mensagens do atasm vão pra saída de erro padrão, então dá pra capturar a listagem e ainda ver as mensagens no terminal com uma linha tipo "atasm -v -r -ooficina-1.bin oficina-1.asm > oficina-1.lst".
Dei uma refrescada rápida em alguns tutoriais, e rabisquei o meu primeiro código pra Atari 2600, que só faz um scroll contínuo de todas as cores que ele pode gerar, usando uma cor diferente para cada linha na tela (notem que tem copyright e licença, que chique!):
; Primeiro teste de kernel simples pra Atari 2600
; Copyright © 2015 Fábio Olivé Leite
; Licença: Faça o que quiser com este código fonte.
.INCLUDE "vcs.h"
*= $f000
reset sei ; Inicializa flags.
cld
ldx #255 ; Inicializa pilha.
txs
lda #0
zero sta $00, x ; Zera a RAM e o TIA.
dex
bne zero
start lda #0 ; Inicia o frame zerando VBLANK ...
sta VBLANK
lda #2
sta VSYNC ; ... e ligando VSYNC.
sta WSYNC ; 3 linhas de VSYNC.
sta WSYNC
sta WSYNC
lda #0 ; Desliga VSYNC.
sta VSYNC
ldx #34 ; Espera mais 34 linhas de VBLANK.
vblank0 sta WSYNC ; Muitos lugares falam em 37 linhas
dex ; mas no Stella o 34 alinhou melhor
bne vblank0 ; com o topo da janela.
ldx #210 ; Desenha 210 linhas visíveis.
tya ; Era pra ser 192, mas 210 fecha até
draw sta COLUBK ; embaixo da janela do Stella.
sta WSYNC ; Um dia eu testo em um Atari real.
clc
adc #1 ; Este "desenho" só vai variando a cor
dex ; de fundo nas linhas. :-)
bne draw
lda #2 ; Liga VBLANK porque acabou o frame.
sta VBLANK
ldx #30 ; São mais 30 linhas de overscan.
ovscan sta WSYNC ; Acabou ficando com 277 linhas no frame.
dex
bne ovscan
iny ; Incrementa a próxima cor inicial.
jmp start ; Volta pro início pra começar a próxima tela.
*= $fffa
.WORD reset ; NMI
.WORD reset ; Reset
.WORD reset ; IRQ
Não cabe aqui explicar os detalhes de como se programa pra Atari 2600, ou o porquê do código precisar ser da forma que é. Isso fica pra um próximo artigo, mas adiantando só um detalhe pra assustar: o Atari 2600 só tem "memória de vídeo" pra uma linha da imagem (da TV) de cada vez, então precisamos montar o "frame de vídeo" uma linha por vez durante o retraço horizontal, e processar a lógica do jogo durante o retraço vertical. Seja bem-vindo à programação pra Atari! ;-)
Os cartuchos simples pra Atari têm 4KiB que são mapeados na parte superior da memória do 6507, que na verdade só tem 13 pinos de endereços, embora o seu núcleo 6502 interno tenha todos os 16 pinos, o que faz com que o 6507 enxergue 8 blocos de 8KiB repetidos (que maravilha). O código então geralmente é gerado para começar no endereço 0xF000, e segundo o datasheet do 6502 as três últimas palavras de 16 bits (little-endian) na memória indicam os endereços para os quais o processador vai saltar em caso de NMI (interrupção não mascarável, cujo pino está faltando no 6507), em caso de Reset (ou quando é ligado) e em caso de IRQ (que também não tem no 6507, ô lasquera). Basicamente o costume é repetir nos seis últimos bytes da memória o endereço onde inicia o código do cartucho.
Compilando (tá, montando) o código acima com o atasm, ele nos conta que gerou 71 bytes de código de máquina. São 65 bytes de código mais os 6 dos endereços no final, e o binário gerado fica com exatos 4096 bytes, como deveria ser.
$ atasm -v -r -ooficina-1.bin oficina-1.asm > oficina-1.lst
ATasm 1.07 (A mostly Mac65 compatible 6502 cross-assembler)
Pass 1: Success. (0 warnings)
Pass 2:
Assembly successful
Compiled 71 bytes (~0k)
Writing raw binary image:
f000-ffff
Compiled to binary file 'oficina-1.bin'
É legal olhar a listagem gerada pelo atasm, pra ver os opcodes e os endereços.
00:F0 78 reset sei ; Inicializa flags.
01:F0 D8 cld
02:F0 A2 FF ldx #255 ; Inicializa pilha.
04:F0 9A txs
05:F0 A9 00 lda #0
07:F0 95 00 zero sta $00, x ; Zera a RAM e TIA.
09:F0 CA dex
0A:F0 D0 FB bne zero
0C:F0 A9 00 start lda #0 ; Inicia o frame zerando VBLANK ...
0E:F0 85 01 sta VBLANK
10:F0 A9 02 lda #2
12:F0 85 00 sta VSYNC ; ... e ligando VSYNC.
14:F0 85 02 sta WSYNC ; 3 linhas de VSYNC.
16:F0 85 02 sta WSYNC
18:F0 85 02 sta WSYNC
1A:F0 A9 00 lda #0 ; Desliga VSYNC.
1C:F0 85 00 sta VSYNC
1E:F0 A2 22 ldx #34 ; Espera mais 34 linhas de VBLANK.
20:F0 85 02 vblank0 sta WSYNC ; Muitos lugares falam em 37 linhas
22:F0 CA dex ; mas no Stella o 34 alinhou melhor
23:F0 D0 FB bne vblank0 ; com o topo da janela.
25:F0 A2 D2 ldx #210 ; Desenha 210 linhas visíveis.
27:F0 98 tya ; Era pra ser 192, mas 210 fecha até
28:F0 85 09 draw sta COLUBK ; embaixo da janela do Stella.
2A:F0 85 02 sta WSYNC ; Um dia eu testo em um Atari real.
2C:F0 18 clc
2D:F0 69 01 adc #1 ; Este "desenho" só vai variando a cor
2F:F0 CA dex ; de fundo nas linhas. :-)
30:F0 D0 F6 bne draw
32:F0 A9 02 lda #2 ; Liga VBLANK porque acabou o frame.
34:F0 85 01 sta VBLANK
36:F0 A2 1E ldx #30 ; São mais 30 linhas de overscan.
38:F0 85 02 ovscan sta WSYNC ; Acabou ficando com 277 linhas no frame.
3A:F0 CA dex
3B:F0 D0 FB bne ovscan
3D:F0 C8 iny ; Incrementa a próxima cor inicial.
3E:F0 4C 0C F0 jmp start ; Volta pro início do frame.
FA:FF 00 F0 .WORD reset ; NMI
FC:FF 00 F0 .WORD reset ; Reset
FE:FF 00 F0 .WORD reset ; IRQ
Confirmando que temos um "cartucho" corretamente montado, agora é só chamar o stella e testar (basta rodar "stella oficina-1.bin"). A emocionante :-D captura de tela abaixo mostra que deu certo!
Agora que meu primeiro teste funcionou, estou fadado a passar o resto dos meus minutos livres tentando fazer algo que preste, ou melhor, tentando programar um excitante jogo onde um quadrado verde tenta pegar uma bola azul enquanto foge de um borrão amarelo, ou algo do tipo. ;-) Talvez ao invés de continuar postando no blog eu comece a escrever um material legal sobre 6502, sobre Atari 2600 e contendo exemplos cada vez mais elaborados lá no xap-hacks.org. Por mais que o Inglês seja uma obrigação básica pra nós que trabalhamos com tecnologia, eu sinto que criar material original e de qualidade em Português Brasileiro cobrindo conceitos fundamentais como Arquitetura de Computadores, especialmente usando processadores que existem de verdade ao invés de processadores "didáticos" que só existem no papel, é um esforço que vale a pena.
Vamos ver no que dá! :-)
Há mais de 10 anos eu tenho vontade de estudar um pouco mais sobre o processador 6502 e sobre programação pro Atari 2600, já que o 6502 era o "outro" processador de 8 bits que "estragou" a infância de muita gente na minha geração. Eu cresci com o MSX e o processador Z80, e nunca tive muito contato com o 6502, enquanto muita gente (principalmente na América do Norte e Europa) cresceu com o 6502 (Apple IIe, Commodore 64, e até o TK 3000 IIe aqui no Brasil) e não conheceu o Z80. A idéia era matar a vontade de conhecer o 6502 e já brincar de programar pro Atari 2600 como um desafio divertido.
Na época em que bateu essa vontade, eu baixei tudo o que achei de referências, datasheets, tutoriais, listas de opcodes e etc sobre 6502 e Atari 2600, imprimi tudo e... guardei. :-( Nunca tive tempo de voltar nesse material, nem de instalar assemblers pra 6502 e realmente meter a mão na massa. Passados uns dez anos, há alguns meses, estávamos conversando sobre realizar oficinas no Hackerspace de Chapecó, e de repente todo aquele contexto acima me veio à cabeça e pensei: é agora que eu me afundo no Atari! :-) Nada melhor do que me jogar de cabeça na responsabilidade de ter que preparar uma oficina pra finalmente "fazer tempo" e colocar a mão na massa. Pois bem, aqui está o primeiro passo.
O ferramental é simples: precisa do emulador stella, um assembler pra família 6502 (o Atari 2600 usa o 6507, uma versão capada do 6502) e um bom editor de textos (vim, claro). O Fedora tem alguns assemblers de 6502, dentre os quais eu escolhi o atasm por ser o que me pareceu mais simples e direto (pra não dizer tosco). Ajuda também baixar o arquivo vcs.h, do tutorial "2600 101" do site AtariAge, com as constantes usadas para identificar mais facilmente os registradores e endereços mágicos do hardware. 20 anos de uso de Software Livre me ensinaram a sempre verificar a licença dos códigos encontrados por aí, e esse vcs.h não tem licença nenhuma, o que indicaria que não poderíamos usá-lo. Mas na boa, é só um monte de constantes que qualquer pessoa poderia digitar por si mesma lendo os manuais da arquitetura, então não tem stress. Na minha interpretação não constitui um trabalho relevante, então é meramente uma comodidade.
O que eu gostei no atasm é que ele vem com um PDF (eu sou da Geração Manual, não da Geração Tutorial) que explica bem as opções de linha de comando, a sintaxe de assembly e diretivas que ele usa, dá exemplos e não é totalmente estranho (alguns outros eram). :-) Usando a opção "-r" o atasm gera uma imagem "raw" (ao invés de um arquivo objeto pra linkar depois), que é exatamente o que precisamos pra criar um "cartucho" do Atari. Uma linha típica pra compilar (tecnicamente é "montar", mas esse termo nunca me soou bem) um arquivo chamado "oficina-1.asm" e gerar um binário "oficina-1.bin" seria "atasm -r -ooficina-1.bin oficina-1.asm". Pra testar dá pra chamar o stella direto, com "stella oficina-1.bin". Mais barbada que isso não tem! :-) Usando a opção "-v" o atasm também gera uma listagem do código compilado na saída padrão. As demais mensagens do atasm vão pra saída de erro padrão, então dá pra capturar a listagem e ainda ver as mensagens no terminal com uma linha tipo "atasm -v -r -ooficina-1.bin oficina-1.asm > oficina-1.lst".
Dei uma refrescada rápida em alguns tutoriais, e rabisquei o meu primeiro código pra Atari 2600, que só faz um scroll contínuo de todas as cores que ele pode gerar, usando uma cor diferente para cada linha na tela (notem que tem copyright e licença, que chique!):
; Primeiro teste de kernel simples pra Atari 2600
; Copyright © 2015 Fábio Olivé Leite
; Licença: Faça o que quiser com este código fonte.
.INCLUDE "vcs.h"
*= $f000
reset sei ; Inicializa flags.
cld
ldx #255 ; Inicializa pilha.
txs
lda #0
zero sta $00, x ; Zera a RAM e o TIA.
dex
bne zero
start lda #0 ; Inicia o frame zerando VBLANK ...
sta VBLANK
lda #2
sta VSYNC ; ... e ligando VSYNC.
sta WSYNC ; 3 linhas de VSYNC.
sta WSYNC
sta WSYNC
lda #0 ; Desliga VSYNC.
sta VSYNC
ldx #34 ; Espera mais 34 linhas de VBLANK.
vblank0 sta WSYNC ; Muitos lugares falam em 37 linhas
dex ; mas no Stella o 34 alinhou melhor
bne vblank0 ; com o topo da janela.
ldx #210 ; Desenha 210 linhas visíveis.
tya ; Era pra ser 192, mas 210 fecha até
draw sta COLUBK ; embaixo da janela do Stella.
sta WSYNC ; Um dia eu testo em um Atari real.
clc
adc #1 ; Este "desenho" só vai variando a cor
dex ; de fundo nas linhas. :-)
bne draw
lda #2 ; Liga VBLANK porque acabou o frame.
sta VBLANK
ldx #30 ; São mais 30 linhas de overscan.
ovscan sta WSYNC ; Acabou ficando com 277 linhas no frame.
dex
bne ovscan
iny ; Incrementa a próxima cor inicial.
jmp start ; Volta pro início pra começar a próxima tela.
*= $fffa
.WORD reset ; NMI
.WORD reset ; Reset
.WORD reset ; IRQ
Não cabe aqui explicar os detalhes de como se programa pra Atari 2600, ou o porquê do código precisar ser da forma que é. Isso fica pra um próximo artigo, mas adiantando só um detalhe pra assustar: o Atari 2600 só tem "memória de vídeo" pra uma linha da imagem (da TV) de cada vez, então precisamos montar o "frame de vídeo" uma linha por vez durante o retraço horizontal, e processar a lógica do jogo durante o retraço vertical. Seja bem-vindo à programação pra Atari! ;-)
Os cartuchos simples pra Atari têm 4KiB que são mapeados na parte superior da memória do 6507, que na verdade só tem 13 pinos de endereços, embora o seu núcleo 6502 interno tenha todos os 16 pinos, o que faz com que o 6507 enxergue 8 blocos de 8KiB repetidos (que maravilha). O código então geralmente é gerado para começar no endereço 0xF000, e segundo o datasheet do 6502 as três últimas palavras de 16 bits (little-endian) na memória indicam os endereços para os quais o processador vai saltar em caso de NMI (interrupção não mascarável, cujo pino está faltando no 6507), em caso de Reset (ou quando é ligado) e em caso de IRQ (que também não tem no 6507, ô lasquera). Basicamente o costume é repetir nos seis últimos bytes da memória o endereço onde inicia o código do cartucho.
Compilando (tá, montando) o código acima com o atasm, ele nos conta que gerou 71 bytes de código de máquina. São 65 bytes de código mais os 6 dos endereços no final, e o binário gerado fica com exatos 4096 bytes, como deveria ser.
$ atasm -v -r -ooficina-1.bin oficina-1.asm > oficina-1.lst
ATasm 1.07 (A mostly Mac65 compatible 6502 cross-assembler)
Pass 1: Success. (0 warnings)
Pass 2:
Assembly successful
Compiled 71 bytes (~0k)
Writing raw binary image:
f000-ffff
Compiled to binary file 'oficina-1.bin'
É legal olhar a listagem gerada pelo atasm, pra ver os opcodes e os endereços.
00:F0 78 reset sei ; Inicializa flags.
01:F0 D8 cld
02:F0 A2 FF ldx #255 ; Inicializa pilha.
04:F0 9A txs
05:F0 A9 00 lda #0
07:F0 95 00 zero sta $00, x ; Zera a RAM e TIA.
09:F0 CA dex
0A:F0 D0 FB bne zero
0C:F0 A9 00 start lda #0 ; Inicia o frame zerando VBLANK ...
0E:F0 85 01 sta VBLANK
10:F0 A9 02 lda #2
12:F0 85 00 sta VSYNC ; ... e ligando VSYNC.
14:F0 85 02 sta WSYNC ; 3 linhas de VSYNC.
16:F0 85 02 sta WSYNC
18:F0 85 02 sta WSYNC
1A:F0 A9 00 lda #0 ; Desliga VSYNC.
1C:F0 85 00 sta VSYNC
1E:F0 A2 22 ldx #34 ; Espera mais 34 linhas de VBLANK.
20:F0 85 02 vblank0 sta WSYNC ; Muitos lugares falam em 37 linhas
22:F0 CA dex ; mas no Stella o 34 alinhou melhor
23:F0 D0 FB bne vblank0 ; com o topo da janela.
25:F0 A2 D2 ldx #210 ; Desenha 210 linhas visíveis.
27:F0 98 tya ; Era pra ser 192, mas 210 fecha até
28:F0 85 09 draw sta COLUBK ; embaixo da janela do Stella.
2A:F0 85 02 sta WSYNC ; Um dia eu testo em um Atari real.
2C:F0 18 clc
2D:F0 69 01 adc #1 ; Este "desenho" só vai variando a cor
2F:F0 CA dex ; de fundo nas linhas. :-)
30:F0 D0 F6 bne draw
32:F0 A9 02 lda #2 ; Liga VBLANK porque acabou o frame.
34:F0 85 01 sta VBLANK
36:F0 A2 1E ldx #30 ; São mais 30 linhas de overscan.
38:F0 85 02 ovscan sta WSYNC ; Acabou ficando com 277 linhas no frame.
3A:F0 CA dex
3B:F0 D0 FB bne ovscan
3D:F0 C8 iny ; Incrementa a próxima cor inicial.
3E:F0 4C 0C F0 jmp start ; Volta pro início do frame.
FA:FF 00 F0 .WORD reset ; NMI
FC:FF 00 F0 .WORD reset ; Reset
FE:FF 00 F0 .WORD reset ; IRQ
Confirmando que temos um "cartucho" corretamente montado, agora é só chamar o stella e testar (basta rodar "stella oficina-1.bin"). A emocionante :-D captura de tela abaixo mostra que deu certo!
Agora que meu primeiro teste funcionou, estou fadado a passar o resto dos meus minutos livres tentando fazer algo que preste, ou melhor, tentando programar um excitante jogo onde um quadrado verde tenta pegar uma bola azul enquanto foge de um borrão amarelo, ou algo do tipo. ;-) Talvez ao invés de continuar postando no blog eu comece a escrever um material legal sobre 6502, sobre Atari 2600 e contendo exemplos cada vez mais elaborados lá no xap-hacks.org. Por mais que o Inglês seja uma obrigação básica pra nós que trabalhamos com tecnologia, eu sinto que criar material original e de qualidade em Português Brasileiro cobrindo conceitos fundamentais como Arquitetura de Computadores, especialmente usando processadores que existem de verdade ao invés de processadores "didáticos" que só existem no papel, é um esforço que vale a pena.
Vamos ver no que dá! :-)
Thursday, November 20, 2014
CONVOCAÇÃO: Reunião de Colaboradores do Projeto Fedora de Chapecó e Região
Bora fuçar no Fedora, pessoal!
CONVOCAÇÃO: Reunião de Colaboradores do Projeto Fedora
QUANDO: Sábado 29/Novembro, das 14h às 18h
ONDE: Lab B202 (Bloco B) da UNOESC Chapecó
Chamamos todos os atuais colaboradores do Projeto Fedora de Chapecó e região, bem como os interessados em se tornarem contribuidores deste grande projeto, para uma reunião de trabalho e habilitação de novos contribuidores, a se realizar no Lab B202 da UNOESC Chapecó, na tarde do sábado dia 29 de Novembro, a partir das 14h.
Se você já é colaborador e anda meio parado, venha encontrar seus colegas e receber uma nova dose de motivação! Se você tem vontade de participar de uma grande comunidade global de desenvolvimento de Software Livre, crescendo como pessoa e como profissional, venha aprender os primeiros passos conosco, e encontrar novos amigos!
A proposta de trabalho e estudo é a seguinte:
Tragam seus laptops, pendrives (para criação de imagens Live de uso e instalação) e a vontade de realizar algo novo.
CONVOCAÇÃO: Reunião de Colaboradores do Projeto Fedora
QUANDO: Sábado 29/Novembro, das 14h às 18h
ONDE: Lab B202 (Bloco B) da UNOESC Chapecó
Chamamos todos os atuais colaboradores do Projeto Fedora de Chapecó e região, bem como os interessados em se tornarem contribuidores deste grande projeto, para uma reunião de trabalho e habilitação de novos contribuidores, a se realizar no Lab B202 da UNOESC Chapecó, na tarde do sábado dia 29 de Novembro, a partir das 14h.
Se você já é colaborador e anda meio parado, venha encontrar seus colegas e receber uma nova dose de motivação! Se você tem vontade de participar de uma grande comunidade global de desenvolvimento de Software Livre, crescendo como pessoa e como profissional, venha aprender os primeiros passos conosco, e encontrar novos amigos!
A proposta de trabalho e estudo é a seguinte:
- O que é, como se organiza e como funciona o Projeto Fedora;
- Como instalar e utilizar o Sistema Operacional Fedora;
- Como contribuir para o desenvolvimento do Fedora;
- "Prática" com criação de contas no Fedora Account System, apresentação nas listas de emails dos grupos de trabalho de interesse dos presentes, canais de IRC onde a comunidade se encontra, etc.
Tragam seus laptops, pendrives (para criação de imagens Live de uso e instalação) e a vontade de realizar algo novo.
Saturday, October 11, 2014
Conversa: Como participar do Projeto Fedora, 16/Outubro 19h
Estou começando a organizar encontros que visam orientar os interessados da região oeste de Santa Catarina sobre como começar a participar do Projeto Fedora, através do laboratório Garagem Tecnológica da UNOESC Chapecó. Minha idéia é trazer periodicamente profissionais da área de TI que atuam no Fedora, com funções variadas, para que eles possam nos contar como iniciaram, por onde podemos entrar e o que é que os vários times como QA, empacotamento, tradutores e etc fazem para o Projeto.
Nesta quinta-feira, dia 16 de Outubro às 19h, teremos no Bloco B da UNOESC Chapecó o primeiro encontro desta série, com o Bruno Zanuzzo. Ele começou recentemente a atuar no time Fedora QA, que basicamente realiza testes e controle de qualidade no Fedora. A idéia é que o encontro dure mais ou menos 1h, e que possamos sair de lá já com contas criadas no FAS e nos "alistando" nos times de teste e QA. O enfoque é "teático": teoria aliada à prática. :-)
TODOS ESTÃO CONVIDADOS, INDEPENDENTE DE ONDE ESTUDAM OU TRABALHAM. :-)
Vamos lá gente! Venham conhecer mais sobre o processo de QA do Projeto Fedora e como podemos participar e ajudar a melhorar ainda mais este ótimo Sistema Operacional Livre!
Já estou conversando também com o Marcelo Barbosa, que é empacotador e tradutor do Fedora, para uma próxima conversa daqui mais algumas semanas, em um sábado. Fiquem ligados. :-)
Nesta quinta-feira, dia 16 de Outubro às 19h, teremos no Bloco B da UNOESC Chapecó o primeiro encontro desta série, com o Bruno Zanuzzo. Ele começou recentemente a atuar no time Fedora QA, que basicamente realiza testes e controle de qualidade no Fedora. A idéia é que o encontro dure mais ou menos 1h, e que possamos sair de lá já com contas criadas no FAS e nos "alistando" nos times de teste e QA. O enfoque é "teático": teoria aliada à prática. :-)
TODOS ESTÃO CONVIDADOS, INDEPENDENTE DE ONDE ESTUDAM OU TRABALHAM. :-)
Vamos lá gente! Venham conhecer mais sobre o processo de QA do Projeto Fedora e como podemos participar e ajudar a melhorar ainda mais este ótimo Sistema Operacional Livre!
Já estou conversando também com o Marcelo Barbosa, que é empacotador e tradutor do Fedora, para uma próxima conversa daqui mais algumas semanas, em um sábado. Fiquem ligados. :-)
Tuesday, July 01, 2014
Acompanhando a "limpeza" da LibReSSL
Quem me conhece sabe que, apesar de usar e promover o uso do Fedora, que é o meu Sistema Operacional favorito, eu também gosto bastante do OpenBSD (que usei de forma quase exclusiva por uns 3 anos, entre 2003 e 2006). Como não curto muito jogar no celular, minha distração digital é ler os commits do OpenBSD lá no MARC.info, e ocasionalmente olhar alguns diffs no FreshBSD, quando a commit message parece particularmente interessante ou divertida.
Desde o fork da OpenSSL, que se tornou a LibReSSL, venho lendo com atenção os commits nessa parte do repositório, e fiquei bem impressionado acompanhando as atividades de limpeza e refatoração do código, correção de bugs, eliminação de arquivos inúteis ou abandonados, opções de compilação de benefício duvidoso e o "estancamento" de muitos memory leaks. Eu já tinha medido de forma bem "crua" e nada científica a extensão do trabalho, medindo o número de arquivos antes e depois da limpeza, e o espaço em disco ocupado pela lib/libssl no meu checkout local do OpenBSD src. Tinha chegado à conclusão de que um terço do código já tinha ido pro /dev/null, mas muita coisa lá não era exatamente código, então sempre ficava aquela sensação de que tinha que achar uma maneira mais apropriada de medir essa limpeza.
Estes dias, lendo um post sobre o Minecraft feito em 500 linhas de Python, me deparei pela primeira vez com o comando "cloc", que calcula as LOCs de um ou mais arquivos fonte. Quando vi o cloc imediatamente lembrei da LibReSSL. Pode não ser perfeito nem exato, mas certamente já é uma aproximação muito melhor do que simplesmente medir o espaço em disco ocupado, hehehe. Obviamente o cloc está empacotado no Fedora, então é só procurar por ele no Softwares, ou abrir um terminal e rodar "sudo yum install cloc".
Aqui está o relatório do cloc no lib/libssl do OpenBSD src, com o checkout do que havia lá no início de abril, antes do fork:
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 911 32917 68531 234548
Perl 166 8455 7874 67187
C/C++ Header 189 5689 14741 32212
make 80 1818 561 15623
Assembly 14 1356 1405 11067
C++ 26 1860 760 4041
Bourne Shell 62 777 702 3411
m4 1 514 0 1585
DOS Batch 33 413 133 1241
Lisp 1 2 19 24
HTML 1 2 2 3
-------------------------------------------------------------------------------
SUM: 1484 53803 94728 370942
-------------------------------------------------------------------------------
No total eram 1484 arquivos fonte (reconhecidos pelo cloc) com um total de 370 KLOCs. Agora vamos ver o mesmo relatório com os fontes mais atuais:
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 674 23730 53766 171050
Perl 116 7275 6966 60669
C/C++ Header 125 4577 11686 25786
Assembly 12 1154 1350 8660
Bourne Shell 19 365 301 1850
m4 1 514 0 1585
make 3 19 4 301
-------------------------------------------------------------------------------
SUM: 950 37634 74073 269901
-------------------------------------------------------------------------------
Uma bela limpeza! Mais de 500 arquivos e 100 KLOCs foram pro /dev/null até agora, e a LibReSSL continua compatível com a OpenSSL, sem quebrar a API e, a princípio, funcionando melhor, com menos bugs e leaks. É interessante ver também, nos commits, que mais gente tem começado a contribuir, o que parece ser um resultado positivo da limpeza e refatoração do código.
Se mais gente entende o código, mais gente sente vontade de contribuir. Obviamente reinventar a roda só por reinventar é uma perda de tempo, porém se o objetivo é chegar numa roda melhor, mais leve e com menos defeitos, certamente vale a pena. Alguns projetos de roda livre "coopetindo" entre si certamente levam a mais Software Livre de qualidade para todos. Boa sorte, LibReSSL!
Desde o fork da OpenSSL, que se tornou a LibReSSL, venho lendo com atenção os commits nessa parte do repositório, e fiquei bem impressionado acompanhando as atividades de limpeza e refatoração do código, correção de bugs, eliminação de arquivos inúteis ou abandonados, opções de compilação de benefício duvidoso e o "estancamento" de muitos memory leaks. Eu já tinha medido de forma bem "crua" e nada científica a extensão do trabalho, medindo o número de arquivos antes e depois da limpeza, e o espaço em disco ocupado pela lib/libssl no meu checkout local do OpenBSD src. Tinha chegado à conclusão de que um terço do código já tinha ido pro /dev/null, mas muita coisa lá não era exatamente código, então sempre ficava aquela sensação de que tinha que achar uma maneira mais apropriada de medir essa limpeza.
Estes dias, lendo um post sobre o Minecraft feito em 500 linhas de Python, me deparei pela primeira vez com o comando "cloc", que calcula as LOCs de um ou mais arquivos fonte. Quando vi o cloc imediatamente lembrei da LibReSSL. Pode não ser perfeito nem exato, mas certamente já é uma aproximação muito melhor do que simplesmente medir o espaço em disco ocupado, hehehe. Obviamente o cloc está empacotado no Fedora, então é só procurar por ele no Softwares, ou abrir um terminal e rodar "sudo yum install cloc".
Aqui está o relatório do cloc no lib/libssl do OpenBSD src, com o checkout do que havia lá no início de abril, antes do fork:
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 911 32917 68531 234548
Perl 166 8455 7874 67187
C/C++ Header 189 5689 14741 32212
make 80 1818 561 15623
Assembly 14 1356 1405 11067
C++ 26 1860 760 4041
Bourne Shell 62 777 702 3411
m4 1 514 0 1585
DOS Batch 33 413 133 1241
Lisp 1 2 19 24
HTML 1 2 2 3
-------------------------------------------------------------------------------
SUM: 1484 53803 94728 370942
-------------------------------------------------------------------------------
No total eram 1484 arquivos fonte (reconhecidos pelo cloc) com um total de 370 KLOCs. Agora vamos ver o mesmo relatório com os fontes mais atuais:
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 674 23730 53766 171050
Perl 116 7275 6966 60669
C/C++ Header 125 4577 11686 25786
Assembly 12 1154 1350 8660
Bourne Shell 19 365 301 1850
m4 1 514 0 1585
make 3 19 4 301
-------------------------------------------------------------------------------
SUM: 950 37634 74073 269901
-------------------------------------------------------------------------------
Uma bela limpeza! Mais de 500 arquivos e 100 KLOCs foram pro /dev/null até agora, e a LibReSSL continua compatível com a OpenSSL, sem quebrar a API e, a princípio, funcionando melhor, com menos bugs e leaks. É interessante ver também, nos commits, que mais gente tem começado a contribuir, o que parece ser um resultado positivo da limpeza e refatoração do código.
Se mais gente entende o código, mais gente sente vontade de contribuir. Obviamente reinventar a roda só por reinventar é uma perda de tempo, porém se o objetivo é chegar numa roda melhor, mais leve e com menos defeitos, certamente vale a pena. Alguns projetos de roda livre "coopetindo" entre si certamente levam a mais Software Livre de qualidade para todos. Boa sorte, LibReSSL!
Saturday, June 28, 2014
Atualizou o Fedora e o touchpad ficou lento? [FIXED]
tl;dr: Não se assuste! Já já vai sair um update pro pacote xorg-x11-server-common que corrige isso. Aqui está o bugzilla deste problema.
Ontem de noite cometi aquele erro clássico: atualizei uns 200 pacotes no meu Fedora 20, desliguei o laptop e fui dormir. Quando fui dar uma geral nas internerds hoje de tarde, percebi que o touchpad estava incrivelmente lento, tendo que passar o dedo umas 15 vezes pro cursor ir de um canto a outro da tela. Na hora pensei "Putz! Nem vi o que atualizei ontem!".
Mas tudo bem, nada que uma googlada não resolva. Procurei por "fedora 20 update mouse slower" e achei posts e bugs descrevendo o problema. O pacote xorg-x11-server-common-1.14.4-10.fc20.x86_64 inclui uma mudança que deveria ser uma melhoria em algumas situações usando dois ou mais monitores, porém para muita gente acabou "estragando" o uso do touchpad e o QA não pegou essa regressão. Mas logo logo sai o release -11.fc20.x86_64 corrigindo isso (já está no updates-testing).
Por enquanto eu rodei o workaround que foi comentado no post e no bug: rodei "synclient MinSpeed=6" em um terminal e o touchpad ficou "aceitável" por enquanto.
Update 2014-06-29: Já está disponível a atualização que resolve o problema:
$ rpm -q --changelog xorg-x11-server-common | head -3
* Sex Jun 27 2014 Peter Hutterer 1.14.4-11
- Revert the previous fix, it breaks a couple of touchpads (#1104789)
Ontem de noite cometi aquele erro clássico: atualizei uns 200 pacotes no meu Fedora 20, desliguei o laptop e fui dormir. Quando fui dar uma geral nas internerds hoje de tarde, percebi que o touchpad estava incrivelmente lento, tendo que passar o dedo umas 15 vezes pro cursor ir de um canto a outro da tela. Na hora pensei "Putz! Nem vi o que atualizei ontem!".
Mas tudo bem, nada que uma googlada não resolva. Procurei por "fedora 20 update mouse slower" e achei posts e bugs descrevendo o problema. O pacote xorg-x11-server-common-1.14.4-10.fc20.x86_64 inclui uma mudança que deveria ser uma melhoria em algumas situações usando dois ou mais monitores, porém para muita gente acabou "estragando" o uso do touchpad e o QA não pegou essa regressão. Mas logo logo sai o release -11.fc20.x86_64 corrigindo isso (já está no updates-testing).
Por enquanto eu rodei o workaround que foi comentado no post e no bug: rodei "synclient MinSpeed=6" em um terminal e o touchpad ficou "aceitável" por enquanto.
Update 2014-06-29: Já está disponível a atualização que resolve o problema:
$ rpm -q --changelog xorg-x11-server-common | head -3
* Sex Jun 27 2014 Peter Hutterer 1.14.4-11
- Revert the previous fix, it breaks a couple of touchpads (#1104789)
Thursday, June 19, 2014
Programando um Arduino em estilo old-school
Talvez o nome mais apropriado fosse "Programando um Arduino da maneira errada" ou "... da maneira mais difícil", mas o fato é que desde que comecei a brincar com Arduinos eu queria "meter a mão na massa" e programar ele à moda antiga, sem IDEs e tal, usando assembly e pior, codificando os opcodes binários manualmente. Sei lá, acho que é cacoete de quem começou com os processadores de 8bits e acostumou a "assemblar" seus próprios programas. Eu sei bem que o objetivo do Projeto Arduino não é esse, que o código não será compatível com outras placas, que será incrivelmente mais difícil, etc etc etc. Não interessa, um fuçador tem que fuçar. :-)
Para começar, a gente precisa olhar a plaquinha Arduino (neste caso, a Uno) pelo que ela realmente é: uma forma simplificada e prática de usar o microcontrolador ATmega328P. Então o próximo passo é ir lá no site da Atmel e baixar o datasheet do microcontrolador (aqui em versão completa, são 36MB), e depois disso baixar também a referência do conjunto de instruções da família AVR (à qual o Atmega328P pertence). Com estes dois documentos, já conseguimos entender bem como é que o bichinho funciona, e como são as suas instruções. Imprima e leia algumas vezes.
O próximo passo é instalar as ferramentas que serão usadas para gravar o programa na plaquinha e para manipular os arquivos de código. O bom é que elas são as mesmas ferramentas usadas pela interface IDE do Arduino: o avrdude para gravar na flash do ATmega328 e as GNU binutils (cross-compilando para AVR). Se você tem o ambiente do Arduino instalado (no Fedora, sudo yum install arduino) está tudo pronto. Uma maneira legal de começar a sujar as mãos com bits crus devagarinho é compilar um programa de exemplo qualquer na interface do Arduino, e depois ir no /tmp olhar os arquivos intermediários no diretório de build. Arrisque-se a digitar "avr-objdump -d foobar.elf" e olhar o código gerado pelo compilador. :-)
Para o meu primeiro teste eu quis fazer um pouco mais do que o tradicional Hello World do Arduino, que é piscar um led. Então resolvi fazer um programa que pisque 8 leds em zigue-zague, usando 8 pinos digitais. Decidi usar os primeiros 8 pinos, D0 a D7, porque eles são todos bits da mesma porta D para o ATmega328, o que facilita a programação. O programa basicamente seta um bit em um registrador e o envia para a porta, esperando um delay rápido e depois deslocando o registrador um bit para a direita e escrevendo na porta, em laço até zerar o registrador. Depois disso, recarrega um valor com um bit setado no registrador e faz o mesmo deslocando para a esquerda, até zerar (quando o bit "cair fora" do registrador:-).
Li algumas páginas relacionadas a sintaxe padrão de assembly AVR, e depois resolvi fazer tudo manualmente, em um formato livre. Então abri o vim e criei este arquivo, que chamei de teste.asm.
Aqui cabem duas observações interessantes:
Feita a tradução dos mnemônicos para os opcodes binários (e calcular os offsets de branches contando em hexa em complemento de 2 nos dedos), agora a tarefa é digitar todos os opcodes em um arquivo, que será o "binário compilado" desse nosso esforço manual. Eu uso o hexedit, que é simples e direto, mas qualquer editor hexadecimal serve. Lembre-se de digitar os opcodes convertendo para little-endian. Fazendo um hexdump do "código compilado" teste.bin fica assim:
Um passo interessante, agora, é transformar esse arquivo contendo opcodes de AVR em um arquivo que o avr-objdump entenda e possa desassemblar, para que a gente confira o código e principalmente os offsets de branches, que o objdump nos ajuda a entender. Não é um passo necessário, mas é bom pra ter certeza que o código que montamos está realmente fazendo o que pretendemos que ele faça. Eu não consegui achar uma maneira de convencer o objdump a desmontar o binário "cru" diretamente, então usei o objcopy para transformá-lo em um ELF comum:
$ avr-objcopy -I binary -O elf32-avr --rename-section .data=.text,contents,code teste.bin \
teste.elf
$ avr-objdump -d teste.elf
teste.elf: file format elf32-avr
Disassembly of section .text:
00000000 _binary_teste_bin_start:
0: 0f ef ldi r16, 0xFF ; 255
2: 0a b9 out 0x0a, r16 ; 10
4: 00 e0 ldi r16, 0x00 ; 0
6: 10 e0 ldi r17, 0x00 ; 0
8: 40 e4 ldi r20, 0x40 ; 64
a: 4b b9 out 0x0b, r20 ; 11
c: 24 e0 ldi r18, 0x04 ; 4
e: 03 95 inc r16
10: f1 f7 brne .-4 ; 0xe _binary_teste_bin_start+0xe
12: 13 95 inc r17
14: e1 f7 brne .-8 ; 0xe _binary_teste_bin_start+0xe
16: 2a 95 dec r18
18: d1 f7 brne .-12 ; 0xe _binary_teste_bin_start+0xe
1a: 46 95 lsr r20
1c: b1 f7 brne .-20 ; 0xa _binary_teste_bin_start+0xa
1e: 42 e0 ldi r20, 0x02 ; 2
20: 4b b9 out 0x0b, r20 ; 11
22: 24 e0 ldi r18, 0x04 ; 4
24: 03 95 inc r16
26: f1 f7 brne .-4 ; 0x24 _binary_teste_bin_start+0x24
28: 13 95 inc r17
2a: e1 f7 brne .-8 ; 0x24 _binary_teste_bin_start+0x24
2c: 2a 95 dec r18
2e: d1 f7 brne .-12 ; 0x24 _binary_teste_bin_start+0x24
30: 44 0f add r20, r20
32: b1 f7 brne .-20 ; 0x20 _binary_teste_bin_start+0x20
34: e5 cf rjmp .-54 ; 0x0 _binary_teste_bin_start
...
Legal, com isso já consigo verificar que eu calculei os opcodes corretamente, e que meus offsets de branches e jumps estavam certos. Agora só falta gravar no Arduino. Para isso, temos que converter o binário em um arquivo no formato Intel Hex, com extensão .hex. Este é o formato usado pelo avrdude, que é quem conversa com o bootloader do Arduino e grava o nosso programa lá. Os comandos abaixo deram conta do recado:
$ avr-objcopy -I binary -O ihex teste.bin teste.hex
$ avrdude -P /dev/ttyUSB0 -p ATmega328P -b 115200 -c arduino -U flash:w:teste.hex:i
O avrdude gera bastante saída na tela, dá pra ir acompanhando os passos da gravação. Note que eu usei um Garagino com uma porta serial FTDI que o acompanha, e ela é detectada como /dev/ttyUSB0. Uma plaquinha Arduino Uno, por exemplo, é detectada como /dev/ttyACM0, então o comando acima deverá ser adaptado. Feita a programação e montado o circuito, voilà! Está tudo funcionando como esperado, em apenas 27 instruções de código!
Estou muito feliz de finalmente ter escovado estes bits, que estavam me esperando desde que comprei a primeira Arduino Uno. Só não tinha dado tempo ainda de pensar num projetinho simples porém não tão trivial, sentar e começar a codar. Levei horas codificando os opcodes manualmente, e é claro que não pretendo mais fazer isso. Meus próximos testes serão utilizando o GNU Assembler para facilitar as coisas. Estou commitando estes e outros testes com Arduino neste repositório no github, para facilitar a publicação e utilização pelos interessados.
Ah, antes que me esqueça: desde que a gente não sobrescreva o bootloader do Arduino, que ocupa os últimos 512 bytes da flash, vai continuar funcionando tudo normalmente, e a placa continua compatível com a IDE do Arduino. Continua sendo possível criar e gravar um programa pelas vias normais, usando a IDE e clicando botõezinhos. :-) Se o nosso programa tiver menos do que 32256 bytes não vai sobrescrever o bootloader e tá tudo certo.
Update 2014-06-20: Na verdade nem precisa converter o arquivo binário para ihex. O avrdude também pode ler arquivos binários sem formato, especificando a opção "raw". Agora mesmo eu mudei um pouco o padrão dos leds e escrevi o teste.bin direto usando "-U flash:w:teste.bin:r". O ":r" no final é que indica o tipo, sendo 'i' Intel Hex, e 'r' raw. Só o que se perde com isso é a possibilidade de especificar o endereço de carga. O ihex pode especificar endereços, para o caso de querermos gravar um conteúdo na flash a partir de um ponto específico. O raw sempre vai ser gravado a partir de 0 na flash. Bom saber que nem precisa fazer a dança do objcopy, embora seja mais reconfortante fazer um objdump e confirmar o código antes de gravar. :-)
Para começar, a gente precisa olhar a plaquinha Arduino (neste caso, a Uno) pelo que ela realmente é: uma forma simplificada e prática de usar o microcontrolador ATmega328P. Então o próximo passo é ir lá no site da Atmel e baixar o datasheet do microcontrolador (aqui em versão completa, são 36MB), e depois disso baixar também a referência do conjunto de instruções da família AVR (à qual o Atmega328P pertence). Com estes dois documentos, já conseguimos entender bem como é que o bichinho funciona, e como são as suas instruções. Imprima e leia algumas vezes.
O próximo passo é instalar as ferramentas que serão usadas para gravar o programa na plaquinha e para manipular os arquivos de código. O bom é que elas são as mesmas ferramentas usadas pela interface IDE do Arduino: o avrdude para gravar na flash do ATmega328 e as GNU binutils (cross-compilando para AVR). Se você tem o ambiente do Arduino instalado (no Fedora, sudo yum install arduino) está tudo pronto. Uma maneira legal de começar a sujar as mãos com bits crus devagarinho é compilar um programa de exemplo qualquer na interface do Arduino, e depois ir no /tmp olhar os arquivos intermediários no diretório de build. Arrisque-se a digitar "avr-objdump -d foobar.elf" e olhar o código gerado pelo compilador. :-)
Para o meu primeiro teste eu quis fazer um pouco mais do que o tradicional Hello World do Arduino, que é piscar um led. Então resolvi fazer um programa que pisque 8 leds em zigue-zague, usando 8 pinos digitais. Decidi usar os primeiros 8 pinos, D0 a D7, porque eles são todos bits da mesma porta D para o ATmega328, o que facilita a programação. O programa basicamente seta um bit em um registrador e o envia para a porta, esperando um delay rápido e depois deslocando o registrador um bit para a direita e escrevendo na porta, em laço até zerar o registrador. Depois disso, recarrega um valor com um bit setado no registrador e faz o mesmo deslocando para a esquerda, até zerar (quando o bit "cair fora" do registrador:-).
Li algumas páginas relacionadas a sintaxe padrão de assembly AVR, e depois resolvi fazer tudo manualmente, em um formato livre. Então abri o vim e criei este arquivo, que chamei de teste.asm.
; Teste de programação do Arduino "assemblando" manualmente os opcodesClaro que eu não saí digitando tudo direto. Eu comecei cada linha com dois tabs, e comecei a listar as instruções aos poucos, pensando em como ia usar os registradores. Acabei decidindo usar os registradores "altos" (r16 em diante) para poder usar a instrução LDI (Load Immediate), que só manipula de r16 a r31. Quando eu tiver mais experiência com o conjunto de instruções acho que vou começar a usar mais os registradores baixos também. Depois de prontas as instruções, preenchi a primeira coluna com os endereços, e então fui aos poucos olhando cada uma das instruções na referência do AVR Instruction Set.
; DDRD = 0a
; PORTD = 0b
; Os opcodes precisam ser convertidos para little-endian no .bin
addr opcode instruction
0000 ef0f ldi r16, 0xff ; programa porta D como saídas
0001 b90a out DDRD, r16
0002 e000 ldi r16, 0x00 ; limpa registradores de contagem dos delays
0003 e010 ldi r17, 0x00
0004 e440 ldi r20, 0x40 ; inicio
0005 b94b out PORTD, r20 ; loop1, led para a direita
0006 e024 ldi r18, 0x04
0007 9503 inc r16 ; delay1
0008 f7f1 brne delay1
0009 9513 inc r17
000a f7e1 brne delay1
000b 952a dec r18
000c f7d1 brne delay1
000d 9546 lsr r20
000e f7b1 brne loop1
000f e042 ldi r20, 0x02
0010 b94b out PORTD, r20 ; loop2, led para a esquerda
0011 e024 ldi r18, 0x04
0012 9503 inc r16 ; delay2
0013 f7f1 brne delay2
0014 9513 inc r17
0015 f7e1 brne delay2
0016 952a dec r18
0017 f7d1 brne delay2
0018 0f44 lsl r20
0019 f7b1 brne loop2
001a cfe5 rjmp inicio
Aqui cabem duas observações interessantes:
- O AVR é um processador RISC de 8 bits, e os opcodes têm um tamanho fixo de 16 bits (algumas instruções precisam 32, mas isso fica como tema para casa). Embora na referência eles sejam demonstrados como números binários de 16 bits, na hora de gravar na flash eles precisam ser convertidos para little-endian. Minha primeira tentativa de criar o arquivo "binário" com o código acabou dando errado, e tive que digitar tudo de novo invertendo os bytes de cada opcode. :-)
- Embora cada instrução ocupe 2 bytes, o Program Counter do AVR aponta para instruções, e não para bytes. Isso significa que os offsets de branches e jumps são offsets em instruções, e não em bytes. Então para pular 4 instruções pra cima, se usa um offset de -4, mesmo que na verdade se esteja pulando 8 bytes para trás. Pra completar a confusão, o objdump mostra o disassembly com endereços de bytes, e ele mostra os opcodes invertidos, já em formato little-endian.
Feita a tradução dos mnemônicos para os opcodes binários (e calcular os offsets de branches contando em hexa em complemento de 2 nos dedos), agora a tarefa é digitar todos os opcodes em um arquivo, que será o "binário compilado" desse nosso esforço manual. Eu uso o hexedit, que é simples e direto, mas qualquer editor hexadecimal serve. Lembre-se de digitar os opcodes convertendo para little-endian. Fazendo um hexdump do "código compilado" teste.bin fica assim:
$ hexdump -C teste.binNo total são 54 bytes, para 27 instruções de máquina. Eu completei com uns zeros no final, só para fechar 64 bytes e ficar tudo alinhado. :) O opcode do NOP em AVR é 0x0000 então tá tranquilo. :-)
00000000 0f ef 0a b9 00 e0 10 e0 40 e4 4b b9 24 e0 03 95 |........@.K.$...|
00000010 f1 f7 13 95 e1 f7 2a 95 d1 f7 46 95 b1 f7 42 e0 |......*...F...B.|
00000020 4b b9 24 e0 03 95 f1 f7 13 95 e1 f7 2a 95 d1 f7 |K.$.........*...|
00000030 44 0f b1 f7 e5 cf 00 00 00 00 00 00 00 00 00 00 |D...............|
Um passo interessante, agora, é transformar esse arquivo contendo opcodes de AVR em um arquivo que o avr-objdump entenda e possa desassemblar, para que a gente confira o código e principalmente os offsets de branches, que o objdump nos ajuda a entender. Não é um passo necessário, mas é bom pra ter certeza que o código que montamos está realmente fazendo o que pretendemos que ele faça. Eu não consegui achar uma maneira de convencer o objdump a desmontar o binário "cru" diretamente, então usei o objcopy para transformá-lo em um ELF comum:
$ avr-objcopy -I binary -O elf32-avr --rename-section .data=.text,contents,code teste.bin \
teste.elf
$ avr-objdump -d teste.elf
teste.elf: file format elf32-avr
Disassembly of section .text:
00000000 _binary_teste_bin_start:
0: 0f ef ldi r16, 0xFF ; 255
2: 0a b9 out 0x0a, r16 ; 10
4: 00 e0 ldi r16, 0x00 ; 0
6: 10 e0 ldi r17, 0x00 ; 0
8: 40 e4 ldi r20, 0x40 ; 64
a: 4b b9 out 0x0b, r20 ; 11
c: 24 e0 ldi r18, 0x04 ; 4
e: 03 95 inc r16
10: f1 f7 brne .-4 ; 0xe _binary_teste_bin_start+0xe
12: 13 95 inc r17
14: e1 f7 brne .-8 ; 0xe _binary_teste_bin_start+0xe
16: 2a 95 dec r18
18: d1 f7 brne .-12 ; 0xe _binary_teste_bin_start+0xe
1a: 46 95 lsr r20
1c: b1 f7 brne .-20 ; 0xa _binary_teste_bin_start+0xa
1e: 42 e0 ldi r20, 0x02 ; 2
20: 4b b9 out 0x0b, r20 ; 11
22: 24 e0 ldi r18, 0x04 ; 4
24: 03 95 inc r16
26: f1 f7 brne .-4 ; 0x24 _binary_teste_bin_start+0x24
28: 13 95 inc r17
2a: e1 f7 brne .-8 ; 0x24 _binary_teste_bin_start+0x24
2c: 2a 95 dec r18
2e: d1 f7 brne .-12 ; 0x24 _binary_teste_bin_start+0x24
30: 44 0f add r20, r20
32: b1 f7 brne .-20 ; 0x20 _binary_teste_bin_start+0x20
34: e5 cf rjmp .-54 ; 0x0 _binary_teste_bin_start
...
Legal, com isso já consigo verificar que eu calculei os opcodes corretamente, e que meus offsets de branches e jumps estavam certos. Agora só falta gravar no Arduino. Para isso, temos que converter o binário em um arquivo no formato Intel Hex, com extensão .hex. Este é o formato usado pelo avrdude, que é quem conversa com o bootloader do Arduino e grava o nosso programa lá. Os comandos abaixo deram conta do recado:
$ avr-objcopy -I binary -O ihex teste.bin teste.hex
$ avrdude -P /dev/ttyUSB0 -p ATmega328P -b 115200 -c arduino -U flash:w:teste.hex:i
O avrdude gera bastante saída na tela, dá pra ir acompanhando os passos da gravação. Note que eu usei um Garagino com uma porta serial FTDI que o acompanha, e ela é detectada como /dev/ttyUSB0. Uma plaquinha Arduino Uno, por exemplo, é detectada como /dev/ttyACM0, então o comando acima deverá ser adaptado. Feita a programação e montado o circuito, voilà! Está tudo funcionando como esperado, em apenas 27 instruções de código!
Estou muito feliz de finalmente ter escovado estes bits, que estavam me esperando desde que comprei a primeira Arduino Uno. Só não tinha dado tempo ainda de pensar num projetinho simples porém não tão trivial, sentar e começar a codar. Levei horas codificando os opcodes manualmente, e é claro que não pretendo mais fazer isso. Meus próximos testes serão utilizando o GNU Assembler para facilitar as coisas. Estou commitando estes e outros testes com Arduino neste repositório no github, para facilitar a publicação e utilização pelos interessados.
Ah, antes que me esqueça: desde que a gente não sobrescreva o bootloader do Arduino, que ocupa os últimos 512 bytes da flash, vai continuar funcionando tudo normalmente, e a placa continua compatível com a IDE do Arduino. Continua sendo possível criar e gravar um programa pelas vias normais, usando a IDE e clicando botõezinhos. :-) Se o nosso programa tiver menos do que 32256 bytes não vai sobrescrever o bootloader e tá tudo certo.
Update 2014-06-20: Na verdade nem precisa converter o arquivo binário para ihex. O avrdude também pode ler arquivos binários sem formato, especificando a opção "raw". Agora mesmo eu mudei um pouco o padrão dos leds e escrevi o teste.bin direto usando "-U flash:w:teste.bin:r". O ":r" no final é que indica o tipo, sendo 'i' Intel Hex, e 'r' raw. Só o que se perde com isso é a possibilidade de especificar o endereço de carga. O ihex pode especificar endereços, para o caso de querermos gravar um conteúdo na flash a partir de um ponto específico. O raw sempre vai ser gravado a partir de 0 na flash. Bom saber que nem precisa fazer a dança do objcopy, embora seja mais reconfortante fazer um objdump e confirmar o código antes de gravar. :-)
Friday, May 02, 2014
Encontro de LibreOffice, Arduino Day e FLISoL: OeSC-Livre em movimento!
Mas bah! Fazem semanas que eu queria vir postar alguma coisa, pelo menos desde o Arduino Day. Os últimos meses foram de muito movimento divertido aqui no Oeste Catarinense, começando pelo 3º Encontro Catarinense de LibreOffice que aconteceu no dia 15 de Março lá na UnC em Concórdia. O Klaibson Ribeiro e o Jackson Laskoski estão de parabéns pela iniciativa de trazer este evento pra cá. Aliás, é muito legal ver eventos cada vez mais diferenciados e específicos acontecendo aqui no bom e velho oeste. Acredito que estamos colhendo os frutos de sementes que vêm sendo plantadas nos últimos anos, com otimismo, tranquilidade e perseverança.
O Arduino Day organizado lá na UNOESC Chapecó foi um sucesso total. Tivemos laboratórios lotados e muita gente fuçando nas plaquinhas, aprendendo a lidar com bits físicos. Desde os piscadores de LED até gente fazendo sensores de temperatura e mexendo com displays LCD, tinha de tudo e todos os envolvidos saíram de lá tendo aprendido muita coisa. Valeu muito a pena participar. Pra variar eu apresentei uma daquelas palestras que acaba em um terminal aberto cheio de números hexadecimais, e o público adorou! Hahahah evento nerd é assim: projeta uma tela preta com letras e números enigmáticos e o pessoal fica maluco. Eu queria ter melhorado um pouco os slides antes de disponibilizar aqui, já que o código em si eu mostrei no terminal, mas faltou tempo. Fica pra próxima palestra deste assunto.
No sábado passado tivemos o segundo FLISoL realizado em Chapecó, desta vez sediado pela UNOESC. Foi um sucesso novamente. Muita gente que já conhecia Software Livre (e Hardware Livre, que tem estado sempre presente) aproveitou pra trocar idéias e renovar conhecimentos, e também muita gente nova nesse mundo aproveitou pra instalar uma distribuição de Linux pela primeira vez com a ajuda dos mais experientes. O Álisson Bertochi e o Tiago Zonta estão de parabéns pelo excelente evento, muito bem organizado. Também foi muito legal o engajamento de pessoas como o Éderson Szlachta (que fez o layout dos crachás) e o Eliezer Bernart, que falou sobre FirefoxOS, apresentou oficina de desenvolvimento pra esse novo Sistema Operacional, e ainda trouxe muitos swags da Mozilla pra distribuir pra gurizada.
No FLISoL eu apresentei uma palestra sobre Software e Hardware Livres, para dar uma base conceitual às conversas, palestras e oficinas que viriam depois, e mais tarde como é de praxe apresentei o Projeto Fedora. No InstallFest da tarde ajudei uma pessoa a instalar Fedora 20 em seu laptop em dual-boot com o Windows 8. Tive um pouco de medo no início, e é claro que deu um probleminha (o Fedora bootava legal, mas o Windows não queria mais ligar), mas desabilitando o SecureBoot deu tudo certo. Deve ter uma maneira de deixar os dois funcionando bem com SecureBoot, mas não deu tempo de investigar mais. Distribuimos mídias de Fedora e criamos pendrives para alguns que iam instalar em casa. No geral foi tudo muito legal.
Fico muito feliz de ver que já podemos dizer que temos uma comunidade de Software e Hardware Livre estabelecida e ativa na região. Muitos eventos, encontros e outros movimentos interessantes vêm acontecendo, como os Hackerspaces que estão tomando forma e se concretizando. Também é muito legal ver que todos estes eventos tiveram apoios variados, inclusive com a Editora Novatec se fazendo presente em todos eles, com códigos promocionais e itens para sorteio. Tanto no Arduino Day quanto no FLISoL a empresa local Fazolo Componentes Eletrônicos também apoiou, com kits de componentes a preços promocionais e sortendo um kit por evento.
Agora vem o FISL e fechamos o primeiro semestre do ano com chave de ouro. Teremos muita gente do grupo lá, pra celebrarmos juntos e representarmos nossa região, que cada vez mais demonstra que está caminhando com passos firmes no mundo da tecnologia.
O Arduino Day organizado lá na UNOESC Chapecó foi um sucesso total. Tivemos laboratórios lotados e muita gente fuçando nas plaquinhas, aprendendo a lidar com bits físicos. Desde os piscadores de LED até gente fazendo sensores de temperatura e mexendo com displays LCD, tinha de tudo e todos os envolvidos saíram de lá tendo aprendido muita coisa. Valeu muito a pena participar. Pra variar eu apresentei uma daquelas palestras que acaba em um terminal aberto cheio de números hexadecimais, e o público adorou! Hahahah evento nerd é assim: projeta uma tela preta com letras e números enigmáticos e o pessoal fica maluco. Eu queria ter melhorado um pouco os slides antes de disponibilizar aqui, já que o código em si eu mostrei no terminal, mas faltou tempo. Fica pra próxima palestra deste assunto.
No sábado passado tivemos o segundo FLISoL realizado em Chapecó, desta vez sediado pela UNOESC. Foi um sucesso novamente. Muita gente que já conhecia Software Livre (e Hardware Livre, que tem estado sempre presente) aproveitou pra trocar idéias e renovar conhecimentos, e também muita gente nova nesse mundo aproveitou pra instalar uma distribuição de Linux pela primeira vez com a ajuda dos mais experientes. O Álisson Bertochi e o Tiago Zonta estão de parabéns pelo excelente evento, muito bem organizado. Também foi muito legal o engajamento de pessoas como o Éderson Szlachta (que fez o layout dos crachás) e o Eliezer Bernart, que falou sobre FirefoxOS, apresentou oficina de desenvolvimento pra esse novo Sistema Operacional, e ainda trouxe muitos swags da Mozilla pra distribuir pra gurizada.
No FLISoL eu apresentei uma palestra sobre Software e Hardware Livres, para dar uma base conceitual às conversas, palestras e oficinas que viriam depois, e mais tarde como é de praxe apresentei o Projeto Fedora. No InstallFest da tarde ajudei uma pessoa a instalar Fedora 20 em seu laptop em dual-boot com o Windows 8. Tive um pouco de medo no início, e é claro que deu um probleminha (o Fedora bootava legal, mas o Windows não queria mais ligar), mas desabilitando o SecureBoot deu tudo certo. Deve ter uma maneira de deixar os dois funcionando bem com SecureBoot, mas não deu tempo de investigar mais. Distribuimos mídias de Fedora e criamos pendrives para alguns que iam instalar em casa. No geral foi tudo muito legal.
Fico muito feliz de ver que já podemos dizer que temos uma comunidade de Software e Hardware Livre estabelecida e ativa na região. Muitos eventos, encontros e outros movimentos interessantes vêm acontecendo, como os Hackerspaces que estão tomando forma e se concretizando. Também é muito legal ver que todos estes eventos tiveram apoios variados, inclusive com a Editora Novatec se fazendo presente em todos eles, com códigos promocionais e itens para sorteio. Tanto no Arduino Day quanto no FLISoL a empresa local Fazolo Componentes Eletrônicos também apoiou, com kits de componentes a preços promocionais e sortendo um kit por evento.
Agora vem o FISL e fechamos o primeiro semestre do ano com chave de ouro. Teremos muita gente do grupo lá, pra celebrarmos juntos e representarmos nossa região, que cada vez mais demonstra que está caminhando com passos firmes no mundo da tecnologia.
Sunday, February 23, 2014
Gambiarra do dia: protoboard com bateria "embutida"
Fazia tempos que eu queria "cometer" algo parecido com isso. Quem usa protoboards pra montar circuitos divertidos ganha muito em agilidade e mobilidade, principalmente pra quem fuça em arduinos, garaginos (meu preferido pra protoboard) e outros inos. Por outro lado, sempre existe o desconforto de andar com uma fonte pra alimentar o circuito à partir da tomada, ou adaptadores de pilhas e outras incomodações. Não seria ótimo se a própria protoboard pudesse ter baterias embutidas, que fornecessem energia pro nosso projeto? Fica muito mais fácil, inclusive pra carregar o projeto na mochila e demonstrar onde for necessário de forma imediata.
Pois bem, hoje eu estava testando um projetinho simples pra configurar e testar o ambiente arduino do Fedora (sudo yum install arduino, pronto), e novamente fiquei de olho em umas baterias velhas de celular que estavam guardadas junto com outras tranqueiras. Dessa vez eu pensei: "quer saber, essa gambiarra vai sair é hoje!". No fim nem ficou tão feio :-), eu só tive um pouco de medo que as baterias aquecessem demais e estragassem na hora em que eu soldei os fios. Pra ficar uma coisa robusta e com boa capacidade, eu soldei duas baterias de 3.7V e 1000mAh em paralelo, colei-as (com fita adesiva mesmo) na parte de baixo da protoboard, e puxei os fios com jacarés através de um dos furos para bornes de alimentação, de forma que fica fácil plugá-los nos bornes que sobraram. A minha idéia original era colocar os fios ligados direto nos bornes, com um interruptor pra ligar, mas não achei um interruptorzinho decente nas minhas sucatas aqui. Por enquanto vai de jacaré mesmo. Inclusive com os jacarés fica fácil plugar no carregador universal de baterias que vou usar nelas.
Elas por enquanto estão fornecendo 4.1V, o que é mais do que suficiente pra alimentar o garagino, que pode receber de 1.8V a 5V. Com os 2000mAh resultantes, acho que ele vai alimentar circuitos simples por alguns dias. :-) Quando der eu faço um teste de deixar um circuito alimentado pelas baterias e cuido até quando ele aguenta. Bem que as fabricantes de protoboard poderiam criar produtos assim, com alimentação embutida (em baterias, nada de fontes que precisem de tomada) e regulada de 3.3V e/ou 5V. Aliás, eu acho que enviei uma sugestão dessas pra ICEL, há algum tempo. Pelo menos isso é o tipo de coisa eu eu faria, hehehe. Não vou abrir uma empresa pra fazer baterias plugáveis em protoboards, porém eu certamente compraria se alguma empresa as fizesse. :-)
Pois bem, hoje eu estava testando um projetinho simples pra configurar e testar o ambiente arduino do Fedora (sudo yum install arduino, pronto), e novamente fiquei de olho em umas baterias velhas de celular que estavam guardadas junto com outras tranqueiras. Dessa vez eu pensei: "quer saber, essa gambiarra vai sair é hoje!". No fim nem ficou tão feio :-), eu só tive um pouco de medo que as baterias aquecessem demais e estragassem na hora em que eu soldei os fios. Pra ficar uma coisa robusta e com boa capacidade, eu soldei duas baterias de 3.7V e 1000mAh em paralelo, colei-as (com fita adesiva mesmo) na parte de baixo da protoboard, e puxei os fios com jacarés através de um dos furos para bornes de alimentação, de forma que fica fácil plugá-los nos bornes que sobraram. A minha idéia original era colocar os fios ligados direto nos bornes, com um interruptor pra ligar, mas não achei um interruptorzinho decente nas minhas sucatas aqui. Por enquanto vai de jacaré mesmo. Inclusive com os jacarés fica fácil plugar no carregador universal de baterias que vou usar nelas.
Elas por enquanto estão fornecendo 4.1V, o que é mais do que suficiente pra alimentar o garagino, que pode receber de 1.8V a 5V. Com os 2000mAh resultantes, acho que ele vai alimentar circuitos simples por alguns dias. :-) Quando der eu faço um teste de deixar um circuito alimentado pelas baterias e cuido até quando ele aguenta. Bem que as fabricantes de protoboard poderiam criar produtos assim, com alimentação embutida (em baterias, nada de fontes que precisem de tomada) e regulada de 3.3V e/ou 5V. Aliás, eu acho que enviei uma sugestão dessas pra ICEL, há algum tempo. Pelo menos isso é o tipo de coisa eu eu faria, hehehe. Não vou abrir uma empresa pra fazer baterias plugáveis em protoboards, porém eu certamente compraria se alguma empresa as fizesse. :-)
Wednesday, February 19, 2014
Ótimo livro: CODE do Charles Petzold
No início de janeiro eu estava pra sair de férias, e perguntei para os meus colegas que livros eles sugeriam para ler. Queria alguma coisa técnica porém leve, que fosse menos bit e mais história. A sugestão do mestre Rafael Aquini não poderia ter sido melhor: CODE, do Charles Petzold. Ao terminar de ler o livro eu cheguei à conclusão que lê-lo equivale a ter nascido na década de 70 e estudado computadores de 8 bits. Sério, é muito bom mesmo!
Vale muito a pena mesmo para quem já domina o lado técnico, pois a contextualização histórica que ele apresenta, na medida certa, enriquece a compreensão de qualquer um a cerca dos bits e seus significados. Não tem como ler este livro e não enxergar os bits. Eles estão lá, nus e crus, esperando que o leitor os apreenda, e de repente toda a computação digital faz sentido.
Você sabia que as raízes da computação binária remontam ao século 19? Os bits são os mesmos, só mudou o substrato. A grande sacada veio no início do século 20, com o Claude Shannon, usando tecnologia de telégrafos do século 19. Eu já tinha lido alguma coisa dele quando estudei algoritmos de compressão, mas agora compreendo o papel muito mais fundamental que ele teve na Grande Sacada de unir no sistema de numeração binário a aritmética, a lógica e a sua expressão automatizada por meio de circuitos elétricos (na época eletromecânicos). A partir daí a tecnologia só se miniaturizou e se tornou mais rápida, mas o princípio é o mesmo.
Claude Shannon agora figura entre Ken Thompson, Dennis Ritchie, Donald Knuth e muitos outros no meu panteão pessoal da Computação. :-)
Vale muito a pena mesmo para quem já domina o lado técnico, pois a contextualização histórica que ele apresenta, na medida certa, enriquece a compreensão de qualquer um a cerca dos bits e seus significados. Não tem como ler este livro e não enxergar os bits. Eles estão lá, nus e crus, esperando que o leitor os apreenda, e de repente toda a computação digital faz sentido.
Você sabia que as raízes da computação binária remontam ao século 19? Os bits são os mesmos, só mudou o substrato. A grande sacada veio no início do século 20, com o Claude Shannon, usando tecnologia de telégrafos do século 19. Eu já tinha lido alguma coisa dele quando estudei algoritmos de compressão, mas agora compreendo o papel muito mais fundamental que ele teve na Grande Sacada de unir no sistema de numeração binário a aritmética, a lógica e a sua expressão automatizada por meio de circuitos elétricos (na época eletromecânicos). A partir daí a tecnologia só se miniaturizou e se tornou mais rápida, mas o princípio é o mesmo.
Claude Shannon agora figura entre Ken Thompson, Dennis Ritchie, Donald Knuth e muitos outros no meu panteão pessoal da Computação. :-)
Subscribe to:
Posts (Atom)