FreeBSD/arm runs on the Atmel AT91RM9200, AT91SAM9260, AT91SAM9G20, AT91SAM9G45 and AT91SAM9XE-family. These are fairly flexible chips that allow hardware designers much flexibility in how it is connected to the rest of the system components. This flexibility is quite different than the uniformity found in the Wintel PC world.

How to get going on a KB9202B from Kwikbyte

This section tries to describe how to get going on a KB9202B board from Kwikbyte. The boards usually come with Linux and U-Boot preinstalled. This section will not explain how you replace that software with generic FreeBSD software. List of things we need:

Building the FreeBSD software for ARM

http://people.freebsd.org/~xride/arm/

A tutorial on the AT91SAM9260-EK board for FreeBSD 91.-PRERELEASE can be found here

Fixing the rest

After that the kernel is built you need to install it somewhere that is reachable through TFTP. The following shell commands assume that your FreeBSD source directory is "/usr/src".

mkdir /tftpboot

make -C/usr/src installkernel KERNCONF=custom \
  TARGET_ARCH=arm DESTDIR=/tftpboot

Edit "/etc/inetd.conf" and enable the "tftpd" service on your build machine:

tftp dgram udp  wait root /usr/libexec/tftpd tftpd -l -s /tftpboot
tftp dgram udp6 wait root /usr/libexec/tftpd tftpd -l -s /tftpboot

Restart "inetd":

killall -HUP inetd

Loading the FreeBSD Kernel onto the KB9202B

When you boot the KB9202B board and connect to the serial port at 115200 baud you will eventually reach the U-Boot command prompt. Here you type in the following commands:

setenv serverip 10.0.0.251
setenv ipaddr 10.0.0.4
setenv ethaddr 4
tftpboot 0x20000000 boot/kernel/kernel
go 0x200000E0

"10.0.0.251" is the IP of the computer running the TFTP server. "10.0.0.4" is the IP of the KB9202B board. Make sure that these IP's are on the same subnet.

Resulting messages on the serial console

KB9202B(www.kwikbyte.com) v2.5


U-Boot 1.1.4 (Oct 13 2006 - 15:42:03)

DRAM:  64 MB
Flash: 16 MB
NAND:  32 MiB

In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0 
U-Boot> setenv serverip 10.0.0.251; setenv ipaddr 10.0.0.4; setenv ethaddr 4; \
  tftpboot 0x20000000 boot/kernel/kernel; go 0x200000E0
TFTP from server 10.0.0.251; our IP address is 10.0.0.4
Filename 'boot/kernel/kernel'.
Load address: 0x20000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############################################################
done
Bytes transferred = 3644849 (379db1 hex)
## Starting application at 0x200000E0 ...
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2007 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 8.0-CURRENT #25: Mon Dec  3 21:54:50 CET 2007
    arm_freak@crossbuild.com:/usr/obj/arm/usr/7-current/src/sys/custom
CPU: ARM920T rev 0 (ARM9TDMI core)
  DC enabled IC enabled WB enabled LABT
  16KB/32B 64-way Instruction cache
  16KB/32B 64-way write-back-locking-A Data cache
real memory  = 67108864 (64 MB)                                                 
avail memory = 61485056 (58 MB)   
atmelarm0: <AT91 device bus> on motherboard
at91_st0: <ST> mem 0xdffffd00-0xdffffdff irq 1 on atmelarm0
at91_st0: watchdog registered, timeout intervall max. 64 sec
at91_pio0: <PIOA> mem 0xdffff400-0xdffff5ff irq 1 on atmelarm0
at91_pio0: ABSR: 0x60 OSR: 0 PSR:0x3938001f ODSR: 0
at91_pio0: [FILTER]
at91_pio1: <PIOB> mem 0xdffff600-0xdffff7ff irq 1 on atmelarm0
at91_pio1: ABSR: 0xff301 OSR: 0x2 PSR:0x3fc00cfe ODSR: 0
at91_pio1: [FILTER]
at91_pio2: <PIOC> mem 0xdffff800-0xdffff9ff irq 1 on atmelarm0
at91_pio2: ABSR: 0 OSR: 0x1000000a PSR:0xffffc075 ODSR: 0x10000000
at91_pio2: [FILTER]
at91_pio3: <PIOD> mem 0xdffffa00-0xdffffbff irq 1 on atmelarm0
at91_pio3: ABSR: 0 OSR: 0 PSR:0xfffffff ODSR: 0
at91_pio3: [FILTER]
at91_pmc0: <PMC> mem 0xdffffc00-0xdffffcff irq 1 on atmelarm0
at91_pmc0: Primary: 10000000 Hz PLLA: 180 MHz CPU: 180 MHz MCK: 60 MHz
at91_mci0: <MCI mmc/sd host bridge> mem 0xdffb4000-0xdffb7fff irq 10 on atmelarm0
at91_mci0: [ITHREAD]
mmc0: <mmc/sd bus> on at91_mci0
at91_twi0: <TWI> mem 0xdffb8000-0xdffbbfff irq 12 on atmelarm0
at91_twi0: [ITHREAD]
iicbus0: <Philips I2C bus> on at91_twi0
setting cwgr to 0x1a4a4
iicbus0: <unknown card> at addr 0
iic0: <I2C generic I/O> on iicbus0
icee0: <I2C EEPROM> at addr 0xa0 on iicbus0
ate0: <EMAC> mem 0xdffbc000-0xdffbffff irq 24 on atmelarm0
ate0: No MAC address setdevice_attach: ate0 attach returned 6
uart0: <DBGU> mem 0xdffff200-0xdffff3ff irq 1 on atmelarm0
uart0: [FILTER].]X....½..½±..(115200,n,8,1)
uart1: <USART0> mem 0xdffc0000-0xdffc3fff irq 6 on atmelarm0
uart1: [FILTER]
uart2: <USART1> mem 0xdffc4000-0xdffc7fff irq 7 on atmelarm0
uart2: [FILTER]
uart3: <USART2> mem 0xdffc8000-0xdffcbfff irq 8 on atmelarm0
uart3: [FILTER]
uart4: <USART3> mem 0xdffcc000-0xdffcffff irq 9 on atmelarm0
uart4: [FILTER]
at91_spi0: <SPI> mem 0xdffe0000-0xdffe3fff irq 13 on atmelarm0
at91_spi0: [ITHREAD]
spibus0: <spibus bus> on at91_spi0
ohci0: <AT91 integrated OHCI controller> mem 0xdfe00000-0xdfefffff irq 23 on atmelarm0
ohci0: [ITHREAD]
usb0 on ohci0
Cannot get 100 Hz clock; using 100Hz
at91_st0: [FILTER]
Timecounter "AT91RM9200 timer" frequency 32768 Hz quality 1000
Timecounters tick every 10.000 msec
usb0: 12MBps Full Speed USB v1.0
uhub0: <Atmel OHCI root hub, class 9/0, rev 1.00/1.00, addr 1> on usb0
uhub0: 2 ports with 2 removable, self powered
uhub0:uhub_explore: usb_new_device failed, error=USBD_SET_ADDR_FAILED
uhub0:uhub_explore: device problem (USBD_SET_ADDR_FAILED), disabling port 2
mmc0: setting transfer rate to 30.000MHz
Trying to mount root from ufs:/dev/mmcsd0s1a

Putting the FreeBSD kernel into flash memory

Now that you have test loaded your FreeBSD kernel, maybe you want to burn it into Flash? The following U-Boot commands will do that.

setenv serverip 10.0.0.251
setenv ipaddr 10.0.0.4
setenv ethaddr 4
tftpboot 0x20000000 boot/kernel/kernel

If you type the command "printenv" at the U-Boot command prompt you will see that the variable "$(filesize)" is already set to the size of the last transferred file. The commands below assume the your kernel size is less than 16MB! If your kernel size is greater than that you will have to do some modifications!

erase 0x10040000 0x1043ffff
cp.b 0x20000000 0x10040000 0x$(filesize)
setenv freebsd cp.b 0x10040000 0x20000000 0x$(filesize)\; go 0x200000E0
saveenv

Be aware that the "cp.b" command can take a very long time to complete. Next time the board ends up at the U-Boot prompt you simply have to type in:

run freebsd

Of course you can make your own command in the same manner. Have fun!

How to get USB working

Make sure that the USB port gets +5V power! Read the User Manual PDF for your board to find out what jumpers needs to be changed, if any. With regard to the kernel config you need at least:

device usb # generic USB subsystem
device ohci # USB Host Controller Interface driver
device at91_dci # USB Device Controller Interface driver

Additional useful USB drivers:

device usfs # device side USB flash disk driver
device cdce # device and host side USB CDC ethernet driver
device umass # host side USB flash disk driver

If the kernel config options above do not exist, have a look at src/sys/arm/conf/KB920X in your kernel sources.

The boot Loader

There are three main boot loaders and a bunch of minor ones (that are beyond the scope of this article). Redboot, uboot and FreeBSD's boot loaders are the three. Often times the board comes with one of these boot loaders and it is desirable to use that boot loader with FreeBSD.

FreeBSDat91UBoot contains the same for U-Boot. This is by far the most common boot loader for Atmel boards. Atmel places uboot on all its reference platforms.

FreeBSDat91Boot contains information about FreeBSD's "boot2" boot loader, including how to customize it for your given board. "boot2" is a primary boot loader (meaning it can be placed in the primary boot media and knows how to do the low level bring up of the CPU and memory). As such, it is by far the most primitive of the boot loaders available. However, it is designed to do one task very well and very fast in a minimum of space. This may make it ideal for some applications if you need minimal configuration or flexibility and maximum booting speed. Its use is generally discouraged unless you have a lot of experience writing bootstrap code for the early CPU execution.

Current Status

The FreeBSD/atmel port is being actively maintained. A number of companies have boards based on AT91RM9200 or the AT91SAM9 families of SoCs. Atmel recently gave one of the developers a new reference board for the AT91SAM9X25, and work is proceeding on that board. The AT91RM9200, AT91SAM9260 and AT91SAM9G20 SoCs are well supported by the base system. Additional work to make the SoC selection more modular is in progress.

SoC Modularization

Currently in the design phases, the SoC modularization work aims to make the addition of a new SoC nothing more than creating a bunch of tables, and, of course writing new drivers. Currently, much code needs to be duplicated to bring up a new SoC. Many of the interfaces in the system lack the fidelity of information to effectively operate in this scheme. A number of changes are needed.

Generic Board Support

Currently, only one board can be supported by any given kernel. All the particular details of the board are compiled into the kernel. The APIs that are used don't allow for multiple boards to be included. There's no way for a board init routine to query metadata from the boot loader about which board it thinks is present.

To combat the single board limitation, the arm port will be enhance to allow a number of boards to be compiled into a kernel. The boards will be listed in a linker set, and the platform specific code will iterate over this list, calling the board's init routine that matches the metadata from the loader.

The role of the board_init function will expand. Currently, on a very minimal set of actions are performed in the board_init function. In the future, the board_init function will communicate which devices are hard wired to the outside world, which GPIOs are used for what features, etc. Currently, there's no way to tell a device driver which pins are used for each of the functional pins that the driver is controlling. Currently, there's a lot of cut and paste code between the different board_init() functions. However, the current GPIO infrastructure is insufficient to make progress on this aspect of the problem.

GPIO Improvements

Currently, the interfaces between the board_init() and other parts of the kernel and the gpio system is based on a tuple of PIO unit base address and mask. This interface is somewhat cumbersome. It would be better to have a list of pin numbers rather than masks to operate on the PIOs. Registering interrupts for GPIO, selecting which peripheral to wire to a given pin, etc also needs to be refactored. Migration to using Atmel provided .h files also will make it easier to move to new SoCs, since we'll not need to generate these ourselves.

USART

Need to document the interface for board_init() to register USARTs.

EMAC

Need to document the interface for board_init() to register ethernet devices, both EMAC and MACB type.

SoC Generalization

Right now we have a lot of code that's cut and paste for each new SoC. However, this code could be table driven. The following items would need a table:

Status of SoC

Chip

Release Date (est)

Atmel Status

FreeBSD status / Notes

AT91RM9200

2004

Retired, use AT91SAM9 parts

Supported

AT91SAM9260

2006

Retired, Replaced by AT91SAM9G20, AT91SAM9XE family

Supported

AT91SAM9261

2006

Mature Product, Replaced by AT91SAM9G10

Maybe

AT91SAM9263

2006

Retired

Unlikely

AT91SAM9G10

2008

Production

Maybe

AT91SAM9G20

2008

Production

Supported

AT91SAM9R64

2009

Production

Maybe

AT91SAM9RL64

2009

Production

Maybe

AT91SAM9G45

2010

Production

Supported

AT91SAM9G46

2010

See AT91SAM9G45

AT91SAM9M10

2010

See AT91SAM9G45

AT91SAM9M11

2010

See AT91SAM9G45

AT91SAM9XE128

2010

Production

Supported (Same as AT91SAM9260)

AT91SAM9XE256

2010

See AT91SAM9XE128

AT91SAM9XE512

2010

See AT91SAM9XE128

AT91SAM9X25

2011

Production

Preliminary Support

AT91SAM9G15

2011

See AT91SAM9X25

AT91SAM9G25

2011

See AT91SAM9X25

AT91SAM9G35

2011

See AT91SAM9X25

AT91SAM9X35

2011

See AT91SAM9X25

AT91SAM9N12

2012

Production

Not Yet

FreeBSDAtmel (last edited 2012-08-06 19:27:01 by WarnerLosh)