NGW100
From Linux A Bordo
Contents |
Visão geral da NGW100
Recebi, em 07/abril/07, o reference design da Atmel NGW100. Uma caixa relativamente pequena, contendo uma placa baseada no processador AP7000, da linha AVR32 da Atmel. É um processador interessante, com dois controladores ethernet e uma série de periféricos, voltada para aplicações com foco em redes. Lendo a arquitetura, fica clara a semelhança entre o processador da Atmel e um Arm (9 e 11). No entanto, a Atmel fez o próprio projeto e parece realmente disposta a oferecer um produto competitivo. Recomendo a leitura do artigo MCU Architectures for Compute-Intensive Embedded Applications, que faz uma comparação do AP7000 com processadores Arm. Mais detalhes do processador no site da Atmel.
Principais características da placa
- Processador Atmel AVR32, 32AP7000, 150Mhz máximo e 210DMIPS.
- Dois controladores ethernet
- 32MB de SDRAM
- 16MB de flash (8MB paralelo e 8MB serial)
- Conector para cartões SD/MMC
- USB
- JTAG
- Conectores para expansão
- Quatro LEDs: um para power, outro para status e dois para o usuário
A placa mede 12x10 cm e tem um layout muito bem feito, com componentes de um só lado. Em especial, gostei do conector para cartões MMC/SD, dos chips para PHY ethernet (minúsculos!) e dos conectores ethernet com trafo embutido. O processador é BGA, bem pequeno também (17x17 mm).
Outra surpresa boa foi ver que qualquer fonte de 9 a 15 volts DC, que forneça pelo menos 0,5A poderia ser usada. Foi fácil achar uma e ligar. Os pontos negativos foram a ausência de um CD com o BSP da placa e uma folha com instruções iniciais, algo como getting start, contendo os IPs, logins/senhas de acesso, configuração da serial, etc.
Mais detalhes da placa no site da Atmel.
Fotos
Quatro imagens da placa. O comprimento dela é igual ao diâmetro de um CD. Tem bastantes pinos para brincadeiras mais elaboradas.
Inicializando
Eu não tive muita paciência para ir ao site ver os detalhes. Apenas olhei a configuração da serial (115200 8N1) e usuário e senha (root/roota). Como todo bom Linuxer, liguei um cabo serial e dei boot na placa, na expectativa de ter um console serial para logar e investigar a placa. A listagem abaixo diz bem mais que eu:
U-Boot 1.1.4-at0 (Jan 3 2007 - 10:30:09) U-Boot code: 00000000 -> 000144f7 data: 24000000 -> 24002d80 SDRAM: 32 MB at address 0x10000000 Testing SDRAM...OK malloc: Using memory from 0x11fc0000 to 0x12000000 Flash: 8 MB at address 0x00000000 DRAM Configuration: Bank #0: 10000000 32 MB In: serial Out: serial Err: serial Net: macb0, macb1 Press SPACE to abort autoboot in 1 seconds ### JFFS2 loading 'uImage' to 0x10200000 Scanning JFFS2 FS: ......... done. ### JFFS2 load complete: 905936 bytes loaded to 0x10200000 ## Booting image at 10200000 ... Image Name: Linux-2.6.18-at0 Image Type: AVR32 Linux Kernel Image (gzip compressed) Data Size: 905872 Bytes = 884.6 kB Load Address: 10000000 Entry Point: 90000000 Verifying Checksum ... OK Uncompressing Kernel Image ... OK Starting kernel at 90000000 (params at 11fc0040)... pdc pdc.0: Atmel Peripheral DMA Controller enabled EIM: External Interrupt Module at 0xfff00000, IRQ 19 EIM: Handling 4 external IRQs, starting with IRQ 64 smc smc.0: Atmel Static Memory Controller at 0xfff03400 pio0: Atmel Port Multiplexer at 0xffe02800 (irq 13) pio0: Handling 32 external IRQs, starting with IRQ 96 pio1: Atmel Port Multiplexer at 0xffe02c00 (irq 14) pio1: Handling 32 external IRQs, starting with IRQ 128 pio2: Atmel Port Multiplexer at 0xffe03000 (irq 15) pio2: Handling 32 external IRQs, starting with IRQ 160 pio3: Atmel Port Multiplexer at 0xffe03400 (irq 16) pio3: Handling 32 external IRQs, starting with IRQ 192 pio4: Atmel Port Multiplexer at 0xffe03800 (irq 17) pio4: Handling 32 external IRQs, starting with IRQ 224 dmac0: DesignWare DMA controller at 0xff200000 irq 2 NET: Registered protocol family 2 IP route cache hash table entries: 256 (order: -2, 1024 bytes) TCP established hash table entries: 1024 (order: 0, 4096 bytes) TCP bind hash table entries: 512 (order: -1, 2048 bytes) TCP: Hash tables configured (established 1024 bind 512) TCP reno registered JFFS2 version 2.2. (NAND) (C) 2001-2006 Red Hat, Inc. io scheduler noop registered io scheduler cfq registered (default) Serial: Atmel USART3 driver usart.1: ttyS0 at MMIO 0xffe01000 (irq = 7) is a USART3 loop: loaded (max 8 devices) eth0: Atmel MACB at 0xfff01800 irq 25 (00:04:25:1c:51:6c) eth1: Atmel MACB at 0xfff01c00 irq 26 (00:04:25:1c:51:6d) physmap platform flash device: 00800000 at 00000000 physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank Amd/Fujitsu Extended Query Table at 0x0041 number of CFI chips: 1 cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness. RedBoot partition parsing not available Using physmap partition information Creating 3 MTD partitions on "physmap-flash.0": 0x00000000-0x00020000 : "u-boot" 0x00020000-0x007f0000 : "root" 0x007f0000-0x00800000 : "env" atmel_spi atmel_spi.0: Atmel SPI Controller at 0xffe00000 (irq 3) mtd_dataflash spi0.0: AT45DB642x (8448 KBytes) ip_conntrack version 2.4 (256 buckets, 2048 max) - 204 bytes per conntrack ip_tables: (C) 2000-2006 Netfilter Core Team TCP bic registered NET: Registered protocol family 1 NET: Registered protocol family 17 Time: avr32 clocksource has been installed. VFS: Mounted root (jffs2 filesystem). Freeing init memory: 56K (90000000 - 9000e000)
Monitor
Resetei a placa (ela tem um push button chamado RST, muito convidativo) e pressionei uma tecla no início para ter acesso ao monitor. No caso, o uboot foi usado:
U-Boot 1.1.4-at0 (Jan 3 2007 - 10:30:09) U-Boot code: 00000000 -> 000144f7 data: 24000000 -> 24002d80 SDRAM: 32 MB at address 0x10000000 Testing SDRAM...OK malloc: Using memory from 0x11fc0000 to 0x12000000 Flash: 8 MB at address 0x00000000 DRAM Configuration: Bank #0: 10000000 32 MB In: serial Out: serial Err: serial Net: macb0, macb1 Press SPACE to abort autoboot in 1 seconds Uboot>
Primeiro bug: atualizando o file system
Não consegui fazer muita coisa com a placa após dar esta olhadela no uboot. Eu a tinha ligada de tarde e testado várias coisas. Mas agora a noite ela travava durante o boot do kernel, na mensagem Freeing init memory. Olhando no site AVR Freaks, considerei que era melhor atualizar a imagem. Segui a receita de bolo e deu certo, o sistema partiu. O kernel é o mesmo, mas o sistema raiz parece ser bem mais recente, com outro comportamente de partida. O led vermelho da placa acendeu (SYS) e o shell (sem senha) apareceu via serial
U-Boot 1.1.4-at0 (Jan 3 2007 - 10:30:09) U-Boot code: 00000000 -> 000144f7 data: 24000000 -> 24002d80 SDRAM: 32 MB at address 0x10000000 Testing SDRAM...OK malloc: Using memory from 0x11fc0000 to 0x12000000 Flash: 8 MB at address 0x00000000 DRAM Configuration: Bank #0: 10000000 32 MB In: serial Out: serial Err: serial Net: macb0, macb1 Press SPACE to abort autoboot in 1 seconds ### JFFS2 loading 'uImage' to 0x10200000 Scanning JFFS2 FS: ....... done. ### JFFS2 load complete: 904654 bytes loaded to 0x10200000 ## Booting image at 10200000 ... Image Name: Linux-2.6.18-at0 Image Type: AVR32 Linux Kernel Image (gzip compressed) Data Size: 904590 Bytes = 883.4 kB Load Address: 10000000 Entry Point: 90000000 Verifying Checksum ... OK Uncompressing Kernel Image ... OK Starting kernel at 90000000 (params at 11fc0040)... pio: invalid pin 128 Stack: (0x901ebf40 to 0x901ec000) bf40: 900106fa 901ebf54 00000000 00000000 00000000 90002966 901ebf68 00000000 bf60: 00000000 00000000 90002fd6 901ebf8c 00000000 9000ba44 00000000 00000000 bf80: 90017adc 9000e5dc 00000000 900034f8 901ebfa0 9000ba7c 00000000 00000000 bfa0: 9000e63a 901ebfdc 9000b87c 9000d400 00000000 00000000 00400000 90011478 bfc0: 90011478 901ec000 00000000 00000000 00000000 00000000 00000000 90017adc bfe0: 00000000 00000000 00000000 00000000 00000000 90017adc 9000e5dc 00000000 Call trace: [<900106e8>] show_stack+0x3c/0x44 [<900106fa>] dump_stack+0xa/0xc [<90002966>] at32_select_gpio+0xba/0xc4 [<90002fd6>] at32_add_device_mmci+0x62/0x8c [<900034f8>] atngw_init+0x4c/0x60 [<9000e63a>] init+0x5e/0x1c0 [<90017adc>] do_exit+0x0/0x598 pdc pdc.0: Atmel Peripheral DMA Controller enabled EIM: External Interrupt Module at 0xfff00000, IRQ 19 EIM: Handling 4 external IRQs, starting with IRQ 64 smc smc.0: Atmel Static Memory Controller at 0xfff03400 pio0: Atmel Port Multiplexer at 0xffe02800 (irq 13) pio0: Handling 32 external IRQs, starting with IRQ 96 pio1: Atmel Port Multiplexer at 0xffe02c00 (irq 14) pio1: Handling 32 external IRQs, starting with IRQ 128 pio2: Atmel Port Multiplexer at 0xffe03000 (irq 15) pio2: Handling 32 external IRQs, starting with IRQ 160 pio3: Atmel Port Multiplexer at 0xffe03400 (irq 16) pio3: Handling 32 external IRQs, starting with IRQ 192 dmac0: DesignWare DMA controller at 0xff200000 irq 2 NET: Registered protocol family 2 IP route cache hash table entries: 256 (order: -2, 1024 bytes) TCP established hash table entries: 1024 (order: 0, 4096 bytes) TCP bind hash table entries: 512 (order: -1, 2048 bytes) TCP: Hash tables configured (established 1024 bind 512) TCP reno registered JFFS2 version 2.2. (NAND) (C) 2001-2006 Red Hat, Inc. io scheduler noop registered io scheduler cfq registered (default) Serial: Atmel USART3 driver usart.1: ttyS0 at MMIO 0xffe01000 (irq = 7) is a USART3 loop: loaded (max 8 devices) eth0: Atmel MACB at 0xfff01800 irq 25 (00:04:25:1c:51:6c) eth1: Atmel MACB at 0xfff01c00 irq 26 (00:04:25:1c:51:6d) physmap platform flash device: 00800000 at 00000000 physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank Amd/Fujitsu Extended Query Table at 0x0041 number of CFI chips: 1 cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness. cmdlinepart partition parsing not available RedBoot partition parsing not available Using physmap partition information Creating 3 MTD partitions on "physmap-flash.0": 0x00000000-0x00020000 : "u-boot" 0x00020000-0x007f0000 : "root" 0x007f0000-0x00800000 : "env" atmel_spi atmel_spi.0: Atmel SPI Controller at 0xffe00000 (irq 3) mtd_dataflash spi0.0: AT45DB642x (8448 KBytes) ip_conntrack version 2.4 (256 buckets, 2048 max) - 204 bytes per conntrack ip_tables: (C) 2000-2006 Netfilter Core Team TCP bic registered NET: Registered protocol family 1 NET: Registered protocol family 17 Time: avr32 clocksource has been installed. VFS: Mounted root (jffs2 filesystem). Freeing init memory: 56K (90000000 - 9000e000) init started: BusyBox v1.2.2 (2006.12.13-14:13+0000) multi-call binary * mounting virtual filesystems: /proc /sys /dev/pts /dev/ shm /config /var/log /var/log/samba /var/log/ntpstats /tmp * setting hostname ... 'ngw.example.net' * network loopback ... [ OK ] * starting syslogd ... [ OK ] * log messages to syslog ... [ OK ] * starting klogd ... [ OK ] * set mdev hotplug ... [ OK ] * mdev ... [ OK ] * probing modules ... vfat loaded, mmc_block loaded, atmel-mci loaded, [ OK ] * mounting filesystems: /usr * setup eth0 ... [ STATIC ] (10.11.12.1) * setup eth1 ... [ OK ] * network ... [ OK ] * starting telnetd ... [ OK ] * enable ipv4 forwarding ... [ OK ] * iptables postrouting ... [ OK ] * iptables incoming trafic ... [ OK ] * iptables outgoung trafic ... [ OK ] * starting dnsmasq ... [ OK ] * running ntpdate ... [ FAILED ] * generate SSH RSA key ... [ OK ] * generate SSH DSS key ... [ OK ] * starting dropbear ... [ OK ] * starting inted ... [ OK ] * starting nmbd ... [ OK ] * starting smbd ... [ OK ] * starting winbindd ... [ OK ] * starting httpd ... [ OK ] * get board type for GPIO ... 'NGW' * setup GPIO boot LED ... [ OK ] * setup GPIO LED A ... [ OK ] * setup GPIO LED B ... [ FAILED ] Network Gateway ready BusyBox v1.2.2 (2006.12.13-14:13+0000) Built-in shell (ash) Enter 'help' for a list of built-in commands. -sh: can't access tty; job control turned off ~ #
Shell disponível
Bom, finalmente com o shell do busybox, ficou mais fácil explorar o sistema. Notei que existia o arquivo /etc/network/interfaces ... Debian based ? Configurei a rede local (a placa tem uma interface WAN e outra LAN) e loguei via ssh:
/etc/network # ifconfig eth1 192.168.0.100 netmask 255.255.255.0
/etc/network # ifconfig
eth0 Link encap:Ethernet HWaddr 00:04:25:1C:51:6C
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:30 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:10972 (10.7 KiB) TX bytes:2360 (2.3 KiB)
Interrupt:25 Base address:0x1800
eth1 Link encap:Ethernet HWaddr 00:04:25:1C:51:6D
inet addr:192.168.0.100 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:418 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:137920 (134.6 KiB) TX bytes:0 (0.0 B)
Interrupt:26 Base address:0x1c00
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:48 errors:0 dropped:0 overruns:0 frame:0
TX packets:48 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2880 (2.8 KiB) TX bytes:2880 (2.8 KiB)
/etc/network # route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 * 255.255.255.0 U 0 0 0 eth1
/etc/network # route add default gw 192.168.0.1
/etc/network # route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 * 255.255.255.0 U 0 0 0 eth1
default 192.168.0.1 0.0.0.0 UG 0 0 0 eth1
/etc/network # cat /etc/resolv.conf
nameserver 192.168.0.1
/etc/network # ping www.smar.com.br
PING srv0.smar.com.br (200.225.219.189): 56 data bytes
64 bytes from 200.225.219.189: icmp_seq=0 ttl=51 time=106.8 ms
64 bytes from 200.225.219.189: icmp_seq=1 ttl=51 time=101.1 ms
--- srv0.smar.com.br ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 101.1/103.9/106.8 ms
barros@dexter:/media$ ssh root@192.168.0.100
The authenticity of host '192.168.0.100 (192.168.0.100)' can't be established.
RSA key fingerprint is 19:af:53:57:dc:e8:e2:6e:5c:4d:5d:f9:a2:f3:23:1d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.0.100' (RSA) to the list of known hosts.
root@192.168.0.100's password:
BusyBox v1.2.2 (2006.12.13-14:13+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
Alguns saídas interessantes:
~ # uname -a Linux ngw.example.net 2.6.18-at0 #1 Fri Jan 19 14:45:28 CET 2007 avr32 unknown
~ # cat /proc/cpuinfo processor : 0 cpu family : AVR32B revision 1 cpu type : AP7000 revision 0 i-cache : 16K (4 ways x 128 sets x 32) d-cache : 16K (4 ways x 128 sets x 32) bogomips : 260.38
~ # free
total used free shared buffers
Mem: 30964 11536 19428 0 0
Swap: 0 0 0
Total: 30964 11536 19428
~ # ps
PID Uid VmSize Stat Command
1 root 312 S init
2 root SWN [ksoftirqd/0]
3 root SW [watchdog/0]
4 root SW< [events/0]
5 root SW< [khelper]
6 root SW< [kthread]
26 root SW< [kblockd/0]
51 root SW [pdflush]
52 root SW [pdflush]
53 root SW< [kswapd0]
54 root SW< [aio/0]
72 root SW [mtdblockd]
94 root SWN [jffs2_gcd_mtd1]
135 root 180 S /sbin/syslogd
145 root 160 S /sbin/klogd
198 root SWN [jffs2_gcd_mtd3]
225 root 96 S /usr/sbin/telnetd -l /bin/ash
246 root 232 S /usr/sbin/dnsmasq
262 root 220 S /usr/sbin/dropbear
269 root 208 S /usr/sbin/inetd
281 root 1384 S /usr/sbin/smbd -D
285 root 888 S /usr/sbin/smbd -D
286 root 876 S /usr/sbin/winbindd
290 root 820 S /usr/sbin/winbindd
294 root 112 S /usr/sbin/httpd -h /www
328 root 460 S -sh
450 root 108 S udhcpc eth1
460 root 108 S udhcpc eth1
474 root 372 R /usr/sbin/dropbear
475 root 456 S -ash
479 root 300 R ps
Alô mundo !
Como não poderia deixar de ser, fiz o famoso programa "hello world". O CD de instalação permite que tudo seja feito no Linux, que eu acredito ser o caminho mais natural. Entretanto, ele possui também um instalador para o Windows, que coloca o Cygwin e ferramentas de compilação. Resolvi testar o cygwin (não fui muito feliz usando o arm e ele há um tempo atrás).
O programa:
#include <stdio.h>
int main(int argc, char** argv)
{
printf("Hello World from AVR!\n");
return 0;
}
Compilando:
marcelo.barros@est1079 ~/Desktop/AVR $ avr32-linux-gcc -o hello.elf hello.c marcelo.barros@est1079 ~/Desktop/AVR $ ls hello.c hello.elf
Foi bem simples compilar e colocar o programa para rodar, ainda mais que se pode usar o cartão SD, um compartilhamento samba, ftp , ou o wge t da placa. Via samba (\\10.0.0.1\netdisk), copiei o .elf. Depois, loguei via ssh, mudei os direitos para 755 e executei, sem grandes surpresas:
~ # cd /media/sdcard/ /media/sdcard # chmod 755 hello.elf /media/sdcard # ./hello.elf Hello World from AVR!
Avaliando a ethernet
Bom, o hello world é muito bonzinho. Resolvi fazer algo mais pesado e que usasse intensivamente a ethernet. Afinal, a NGW100 é um gateway, não é ? Cross-compilei o programa iperf para testar o desempenho das interfaces de rede da NGW100. Perdi um tempo na cross-compilação porque o script configure do pacote tinha um problema no uso do g++ (ver seção Known Problems). Gerei os makefiles para compilação normal e ajustei na mão pra usar os compiladores e linkers do avr32. Além disso, tive que pedir pra fazer linkagem estática (-static), já que não tinha a biblioteca do c++ no NGW100. Update: descobri a forma certa de fazer. Basicamente, aplique o patch que eu gerei para a versão 2.0.2 do iperf e compile (o iperf será criado dentro do diretório src):
tar xvzf iperf-2.0.2.tar.gz cd iperf-2.0.2 patch -p1 < ../iperf-2.0.2-avr32-diff CFLAGS=-static ./configure --host=avr32-linux make
Problemas superados, iperf compilado e instalado na NGW100, comecei a testar a rede da interface LAN. Eu estava começando a ter os primeiros resultados, dei uma parada para o café e, ao voltar, o sistema não respondia mais. Resetei e não adiantou: a placa não chegava no final do boot (isto é indicado via um led vermelho aceso). Fiquei um pouco decepcionado, já que o segundo problema grave que encontro no sistema. Considero grave porque o equipamento trava, não volta nem depois do reset. Até o momento, tive a indicação de 14Mbits/s para TCP e 17.5 Mbits/s para UDP na interface LAN. Não deu tempo de testar a interface WAN. De qualquer forma, os número pareceram um pouco modestos mas, obviamente, suficiente para roteadores ou firewalls caseiros.
Aparentemente, o problema foi reportado no fórum AVR32. Pela data do post e dos arquivos, poderia ser a solução. Estranhamento, ao tentar fazer o update da imagem via cartão MMC, nada deu certo, mesmo usando comandos exatamente iguais aos já empregados nesta avaliação.
Resolvi mudar de método e fazer uma carga via tftp. Depois de algumas lições para descobrir como isto funciona no uboot, finalmente consegui atualizar a imagem com a seguinte sequência de comandos do uboot:
protect off 0x20000 0x7effff erase 0x20000 0x7effff setenv ipaddr 10.0.0.1 setenv tftpip 10.0.0.100 tftp. 0x90000000 ngw_jffs2_root.img cp.b 0x90000000 0x20000 0x620000 protect on all boot
Ou, incluindo as saídas dos comandos:
Uboot> protect off 0x20000 0x7effff
Un-Protected 125 sectors
Uboot> erase 0x20000 0x7effff
Erasing sector 9...Erasing sector 10...
Uboot> setenv ipaddr 10.0.0.1
Uboot> setenv tftpip 10.0.0.100
Uboot> tftp. 0x90000000 ngw_jffs2_root.img
macb1: Starting autonegotiation...
macb1: Autonegotiation complete
macb1: link up, 100Mbps full-duplex (lpa: 0x41e1)
Using macb1 device
TFTP. from server 10.0.0.100; our IP address is 10.0.0.1
Filename 'ngw_jffs2_root.img'.
Load address: 0x90000000
Loading: T #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
####################
done
Bytes transferred = 6422528 (620000 hex)
Uboot> cp.b 0x90000000 0x20000 0x620000
Copy to Flash... done
Uboot> protect on all
Protect Flash Bank # 1
Uboot> boot
Interface LAN
Basicamente usarei o iperf para testar as cargas máximas de entrada e saída da interface LAN da NGW100 para TCP, como organizado a seguir:
- Testes com TCP
- Taxa de entrada (PC --> NGW100)
- Taxa de saída (NGW --> PC)
- Taxa de entrada e saída simultâneas (PC <--> NGW100)
Para TCP, basta colocar o iperf da NGW no modo servidor (iperf -s) e rodar no PC os comandos iperf -c 10.0.0.1 -r (entrada e saída separadas) e iperf -c 10.0.0.1 -d (teste simultâneo).
Os resultados estão a seguir.
| PC --> NGW100 | NGW100 --> PC | PC <--> NGW100 simul. | |
|---|---|---|---|
| TCP | 34.3 Mbits/s | 34.4 Mbits/s | 17.5 Mbits/s (PC-->NGW) |
| 17.0 Mbits/s (NGW-->PC) |
Notas:
- Nos meus primeiros testes, a conexão passava pelo meu roteador sem fio DLink DI-624. Após usar o iperf um pouco, a comunicação parou inexplicavelmente. Rebootei a NGW100 e mesmo assim não tinha comunicação, apesar de o console serial indicar que tudo estava bem. Só neste momento percebi que estava usando a rede sem fio, que não tem desempenho suficiente para este tipo de teste. Comecei tudo novamente, com um cabo cross e os resultados foram bem melhores, evidenciando que o roteador era o gargalo. Pelo menos serviu pra mostrar que a eficiência do DI-624 é aproximadamente 42%, chegando a 23 Mbits/sec.
- Rodei algumas vezes cada teste e não houve grande variação nos valores, no máximo cerca de 1 ou 2 Mbits/sec. O teste com envio e recepção simultâneo variava um pouco mais, em geral.
Interface WAN
Num teste similar ao realizado para a interface LAN, os resultados obtidos para a interface WAN foram:
| PC --> NGW100 | NGW100 --> PC | PC <--> NGW100 simul. | |
|---|---|---|---|
| TCP | 34.5 Mbits/s | 34.3 Mbits/s | 18.22 Mbits/s (PC-->NGW) |
| 16.72 Mbits/s (NGW-->PC) |
Notas:
- A variação nos resultados pareceu maior que para a interface WAN. Considerei uma média entre seis valores somente. Assim, tudo indica que o resultado é simétrico.
- Em geral, conseguia perceber uma variação de até 4 Mbits/s no teste unidirecional. Já no teste bidirecional, o desvio foi pequeno, sempre menor que 0.5 Mbits/s.
- Não consegui finalizar o teste de repasse entre interfaces WAN e LAN. Alguma coisa estava impedindo parte do teste (não era o iptables ou roteamento estático). Mas testei o caminho PC-->WAN-->LAN, gerando cerca de 34 Mbits/s e indicando que o repasse está muito bom (pelo menos num sentido).
Alterando o file system
De nada adianta uma placa dessas se você não puder personalizar o sistema de arquivos para a sua necessidade. Até o momento, o processo ainda é um pouco trabalhoso e a Atmel não liberou as últimas versões do seu script de geração para a NGW100. O scrip que vem com o CD da placa está apresentando problemas com a NGW100 e um novo deve ser liberado nas próximas semanas. Idealmente, o uso do buildroot seria a melhor saída, já que é algo consolidado e bastante usado no mundo todo, mas não funcionou nos meus testes. Tentei também o [www.t2-project.org/ T2], sem sucesso (eles disseram que irão corrigir os problemas encontrados em breve). A Atmel precisa melhorar este processo, tornando-o mais fácil e de fácil reprodução. Eu iniciei um projeto chamado avr32fs (AVR32 from Scratch) com o objetivo de poder facilitar o processo de criação da imagem do sistema da NGW100. Ainda está numa fase inicial mas funcional. Mais detalhes no site do projeto avr32fs. No entanto, nesta avaliação, será mostrado como fazer o sistema usando as ferramentas da Atmel, para que tenhamos uma referência no processo.
Instalando o toolchain
Na wiki do AVRFreaks existe material suficiente para uso da NGW100:
http://www.avrfreaks.net/wiki/index.php/Documentation:NGW
Especificamente sobre a instalação:
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR32_General/Tools_Installation
Se você usa Ubuntu (ou outra distro baseada em apt), eu adicionei alguns passos para criação de um repositório local à partir dos pacotes que vem com o CD. Assim, você pode baixar/copiar apenas o CD e usá-lo em casa, caso não tenha uma conexão muito rápida.
Particionamento da flash
Basicamente, três devices mtd são criados pelo kernel, em [path_do_kernel]/arch/avr32/boards/atngw100/flash.c, para a flash paralela de 8MB (NOR):
/dev/mtd0 : onde está o u-boot (128k) /dev/mtd1: kernel (8000k) /dev/mtd2: parâmetros do u-boot (64k)
Além disso, existe mais um quarto mtd (mtd3), de 8MB e mapeado numa flash serial. Ele é montado no boot e usado para montagem do diretório /usr. É perceptível ver como a montagem é mais lenta para a flash serial. No entanto, é totalmente transparente para o sistema. Ele é criado em [path_do_kernel]/drivers/mtd/devices/mtd_dataflash.c.
Caso queira economizar memória, apague a wiki do webserver da placa (/www/wiki), liberando 6MB na flash paralela. O kernel atual consome cerca de 1MB, sobrando bastante espaço para uma aplicação nesta flash e ainda ficando com uma flash serial inteira para se fazer o que quiser.
Neste teste, será usado o mtd1, que irá receber o kernel mais o sistema raiz. Note que as faixas de apagamento da flash via u-boot correspondem exatamente ao mtd1.
Gerando o sistema a partir do CD
O CD distribuído pela Atmel contem os programs fontes usados e scripts para geração do sistema de arquivos. O problema encontrado no uso destas ferramentas está relacionado ao fato de tudo ter sido feito para a placa de referência STK1000 e não para a NGW100. Com pequenas correções, é possível superar as dificuldades e gerar a nova imagem.
Vamos supor aqui que o CD da NGW100 está em /media/cdrom0 e iremos gerar o sistema em /media/ngw100/rootfs. Comece copiando os diretórios scripts (scripts para geração) e software (código fonte modificado pela Atmel) do CD.
$ mkdir rootfs $ cd rootfs/ $ cp -r /media/cdrom0/scripts/ . $ cp -r /media/cdrom0/software/ .
A geração vai usar também um esqueleto da árvore do sistema, já com alguns arquivos de inicialização, que será preenchida com os programas criados. Extraia este esqueleto para o diretório local:
$ tar xvzf /media/cdrom0/builds/stk1000/stk1000-linux-image-reference.tar.gz sd-image-reference/
Bom, neste ponto começam as modificações. Eu acabei descobrindo sozinho alguns problemas, mas depois notei que havia uma thread similar no AVRFreaks. Basicamente:
- Altere o file system de referência (sd-image-reference) e crie o device console (cd sd-image-reference/etc; sudo mknod console c 5 1). Sem isto, o kernel irá logar uma mensagem de Warning: unable to open an initial console e não vai criar o processo init. Como isto só pode ser feito pelo root, no processo de geração da imagem foi necessário usar o sudo. Eu fiz outras mudanças no file system de referencia, mas eram de personalização de rede e montagens. Não são necessárias para que o sistema compile e rode.
- Edite o arquivo scripts/build-linux-environment.sh e troque todas as referências de atstk1002_defconfig por atngw_defconfig (são duas). No final do script existem pacotes que podem ser comentados. Eu removi (basta colocar # na frente da linha) toda a parte relacionada a STK1000, ao final do arquivo, deixando apenas o kernel, uclibc, busybox, dropbear e zlib.
- Ainda neste arquivo, troque o valor da variável ROOT_IMAGE_NAME para que exista NGW100 em algum lugar dentro dela. Caso contrário, o sistema não vai executar o script de inicialização correto (ver função create_root).
- Se não quiser ter muito trabalho, compare o original com as minhas alterações.
Existe um bug na versão do kernel relacionada a GPIO e SDRAM de 16MB. E um patch para corrigi-lo. Não é o caso da minha placa NGW100. Caso contrário, faça o seguinte:
- baixa o patch add-pioe-gpio-initialization.patch e salve em software/linux
- Adicione add-pioe-gpio-initialization.patch no final do arquivo software/linux/series. Assim, durante a compilação do kernel, este patch será aplicado.
Finalmente, chegou a hora do café, quer dizer, da compilação. Levou menos de 8 minutos no meu notebook, com este conjunto reduzido de programas.
$ cd scripts/ $ mkdir build $ sudo bash ./build-linux-environment.sh ../software/ ../sd-image-reference/ build
Será gerado um arquivo build/avr32-linux-image-basic.img.gz, que é uma imagem ext2 do sistema, compactada. Dependendo do método que for usado para gravação da imagem, algumas mudanças precisam ser feitas. No meu caso, eu irei fazer o update via tftp, sendo necessária uma imagem de flash, no formato jffs2. Usando o pacote mtd-utils e com modificações no script de build, gerei a imagem para tftp. Basicamente, adicionei a linha a seguir (já incluídas no pacote citado anteriormente):
mkfs.jffs2 --output.=$ROOT.jffs2.img --root=$ROOT --pagesize=4096 --eraseblock=65536 --big-endian
Com a imagem pronta e um servidor de tftp, segui os passos já vistos na atualização do sistema. Na dúvida, adicionei também um comando especificando os parâmetros de partida do Linux. Fique atento pois o tamanho da imagem pode mudar.
protect off 0x20000 0x7effff erase 0x20000 0x7effff setenv ipaddr 10.0.0.1 setenv tftpip 10.0.0.100 tftp. 0x90000000 avr32-linux-image-basic.jffs2.img cp.b 0x90000000 0x20000 0x23e014 <<<<==== tamanho !!! protect on all set bootargs 'console=ttyS0 root=/dev/mtdblock1 rootfstype=jffs2';fsload;bootm boot
Pronto. O primeiro boot é mais lento pois as chaves do ssh são geradas. Mas, no segundo, levou menos de 10 segundos para chegar no prompt. Isto somando o tempo gasto pelo u-boot. Sem ele, o boot é de cerca de 6 segundos e meio !
O boot está a seguir. Note que ainda existem alguns problemas não resolvidos na imagem, provenientes da adaptação ruim da STK1000 para NGW100. Talvez seja melhor começar um sistema de arquivos do zero, usando apenas a compilação do kernel e uclibc.
U-Boot 1.1.4-at0 (Jan 3 2007 - 10:30:09) U-Boot code: 00000000 -> 000144f7 data: 24000000 -> 24002d80 SDRAM: 32 MB at address 0x10000000 Testing SDRAM...OK malloc: Using memory from 0x11fc0000 to 0x12000000 Flash: 8 MB at address 0x00000000 DRAM Configuration: Bank #0: 10000000 32 MB In: serial Out: serial Err: serial Net: macb0, macb1 Press SPACE to abort autoboot in 1 seconds ### JFFS2 loading 'uImage' to 0x10200000 Scanning JFFS2 FS: .... done. ### JFFS2 load complete: 904620 bytes loaded to 0x10200000 ## Booting image at 10200000 ... Image Name: Linux-2.6.18-at1 Image Type: AVR32 Linux Kernel Image (gzip compressed) Data Size: 904556 Bytes = 883.4 kB Load Address: 10000000 Entry Point: 90000000 Verifying Checksum ... OK Uncompressing Kernel Image ... OK Starting kernel at 90000000 (params at 11fc0040)... pio: invalid pin 128 Stack: (0x901ebf40 to 0x901ec000) bf40: 900106ee 901ebf54 00000000 00000000 00000000 90002966 901ebf68 00000000 bf60: 00000000 00000000 90002fd6 901ebf8c 00000000 9000ba44 00000000 00000000 bf80: 90017ad0 9000e5dc 00000000 900034f8 901ebfa0 9000ba7c 00000000 00000000 bfa0: 9000e63a 901ebfdc 9000b87c 9000d400 00000000 00000000 00400000 9001146c bfc0: 9001146c 901ec000 00000000 00000000 00000000 00000000 00000000 90017ad0 bfe0: 00000000 00000000 00000000 00000000 00000000 90017ad0 9000e5dc 00000000 Call trace: [<900106dc>] show_stack+0x3c/0x44 [<900106ee>] dump_stack+0xa/0xc [<90002966>] at32_select_gpio+0xba/0xc4 [<90002fd6>] at32_add_device_mmci+0x62/0x8c [<900034f8>] atngw_init+0x4c/0x60 [<9000e63a>] init+0x5e/0x1c0 [<90017ad0>] do_exit+0x0/0x598 pdc pdc.0: Atmel Peripheral DMA Controller enabled EIM: External Interrupt Module at 0xfff00000, IRQ 19 EIM: Handling 4 external IRQs, starting with IRQ 64 smc smc.0: Atmel Static Memory Controller at 0xfff03400 pio0: Atmel Port Multiplexer at 0xffe02800 (irq 13) pio0: Handling 32 external IRQs, starting with IRQ 96 pio1: Atmel Port Multiplexer at 0xffe02c00 (irq 14) pio1: Handling 32 external IRQs, starting with IRQ 128 pio2: Atmel Port Multiplexer at 0xffe03000 (irq 15) pio2: Handling 32 external IRQs, starting with IRQ 160 pio3: Atmel Port Multiplexer at 0xffe03400 (irq 16) pio3: Handling 32 external IRQs, starting with IRQ 192 dmac0: DesignWare DMA controller at 0xff200000 irq 2 NET: Registered protocol family 2 IP route cache hash table entries: 256 (order: -2, 1024 bytes) TCP established hash table entries: 1024 (order: 0, 4096 bytes) TCP bind hash table entries: 512 (order: -1, 2048 bytes) TCP: Hash tables configured (established 1024 bind 512) TCP reno registered JFFS2 version 2.2. (NAND) (C) 2001-2006 Red Hat, Inc. io scheduler noop registered io scheduler cfq registered (default) Serial: Atmel USART3 driver usart.1: ttyS0 at MMIO 0xffe01000 (irq = 7) is a USART3 loop: loaded (max 8 devices) eth0: Atmel MACB at 0xfff01800 irq 25 (00:04:25:1c:51:6c) eth1: Atmel MACB at 0xfff01c00 irq 26 (00:04:25:1c:51:6d) physmap platform flash device: 00800000 at 00000000 physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank Amd/Fujitsu Extended Query Table at 0x0041 number of CFI chips: 1 cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness. cmdlinepart partition parsing not available RedBoot partition parsing not available Using physmap partition information Creating 3 MTD partitions on "physmap-flash.0": 0x00000000-0x00020000 : "u-boot" 0x00020000-0x007f0000 : "root" 0x007f0000-0x00800000 : "env" atmel_spi atmel_spi.0: Atmel SPI Controller at 0xffe00000 (irq 3) mtd_dataflash spi0.0: AT45DB642x (8448 KBytes) ip_conntrack version 2.4 (256 buckets, 2048 max) - 204 bytes per conntrack ip_tables: (C) 2000-2006 Netfilter Core Team TCP bic registered NET: Registered protocol family 1 NET: Registered protocol family 17 Time: avr32 clocksource has been installed. VFS: Mounted root (jffs2 filesystem). Freeing init memory: 56K (90000000 - 9000e000) init started: BusyBox v1.2.1 (2007.07.04-13:54+0000) multi-call binary * mounting virtual filesystems: /proc /sys /dev/pts /dev/ shm /config /var/log /var/log/samba /var/log/ntpstats /tmp * setting hostname ... 'ngw.example.net' * network loopback ... [ OK ] * starting syslogd ... [ OK ] * log messages to syslog ... [ OK ] * starting klogd ... [ OK ] * set mdev hotplug ... [ OK ] * mdev ... [ OK ] * probing modules ... vfat loaded, mmc_block loaded, atmel-mci loaded, [ OK ] * mounting filesystems: [ FAILED ] * setup eth0 ... * setup eth0 ... [ OK ] * setup eth1 ... [ OK ] * network ... [ OK ] * enable ipv4 forwarding ... [ OK ] * iptables postrouting ... [ MISSING ] * starting dropbear ... [ OK ] * starting inted ... [ OK ] * get board type for GPIO ... NGW100 * no GPIO for this board Network Gateway ready BusyBox v1.2.1 (2007.07.04-13:54+0000) Built-in shell (ash) Enter 'help' for a list of built-in commands. ~ #
Compilando o Kernel mais atual
O kernel Linux fornecido no CD de instalação é um pouco mais antigo que o kernel mantido pela Atmel. Vamos usar o kernel mais recente, que já corrigi alguns problemas encontrados no 2.6.18. O processo de compilação do kernel, uma vez que o toolchain esteja instalado, é bastante simples.
- Baixe uma cópia do kernel, já com patches aplicados, diretamente do repositório git do mantenedor (versão 2.6.21.3.atmel.1):
git clone git://www.atmel.no/~hskinnemoen/linux/kernel/avr32.git/ avr32
Vai demorar bastante. Tenha paciência.
- Entre no diretório, acerte a configuração default para avr32/NGW100 e limpe todo o lixo (caso exista):
cd avr32 make ARCH=avr32 CROSS_COMPILE=avr32-linux- atngw100_defconfig make ARCH=avr32 CROSS_COMPILE=avr32-linux- distclean
- Finalmente, compile com:
make ARCH=avr32 CROSS_COMPILE=avr32-linux-
Vai ser rápido. Talvez não dê tempo para um café mais elaborado.
- kernel será gerado em arch/avr32/boot/images/. No meu caso, o vmlinux.gz tinha 1.1Mb.
Onde comprar ?
Muitas pessoas me perguntaram como comprar a NGW100 já que não é tão fácil comprar este tipo de produto no Brasil. No meu caso, ganhamos uma placa de amostra, direto da AVNet americana. Quem não tem esta opção, irá precisar fazer uma importação mesmo ou contactar representantes locais. No site da Atmel, eles indicam algumas revendas (AVNET, ARROW ELECTRONICS e DIGI-KEY):
http://www.stkcheck.com/evs/atmel/atmelheader2.asp?mfg=atmel&part=ATNGW100
Em especial, a placa estava disponível no site da Arrow (basta pesquisar por ATNGW100 lá) por 69 dólares (73,15 no site da Digi-Key) mais despesas de envio (algo em torno de uns 30 dólares). O email para contato sobre dúvidas (vendas internacionais) é: iccsales<arroba>arrow<ponto>com. Já a Diki-Key tem um chat online para responder dúvidas em:
http://sales.digikey.com/us/en/chat/callFormACD.shtml
Eu sei que a AVNet tem representante local (avnet.com.br). Se souberem uma forma mais prática, por favor mandem um email me avisando: marcelobarrosalmeida<arroba>gmail<ponto>com ou atualizem a Wiki diretamente.
Update: O valor com frete, pelo site da Digi-key, foi de US$ $113,90, segundo o Marcelo Lemos Stoltzenburg. Cerca de uma semana para entrega. Valores bem aceitáveis para uma compra internacional.

