NGW100

From Linux A Bordo

Jump to: navigation, search

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.

Imagem:ngw100-placa.jpg

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:

  1. Testes com TCP
    1. Taxa de entrada (PC --> NGW100)
    2. Taxa de saída (NGW --> PC)
    3. 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.

Desempenho da interface LAN da NGW100
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:

  1. 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.
  2. 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:

Desempenho da interface WAN da NGW100
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:

  1. 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.
  2. 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.
  3. 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.

http://www.avrfreaks.net/wiki/index.php/Documentation:AVR32_General/Installing_tools_on_Ubuntu_Linux#Creating_a_local_repository_from_BSP_CD

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.

Produtos