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.

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:

  • SD Flash card 512MB
  • Ethernet cable
  • Serial cable
  • USB serial adapter
  • FreeBSD sources

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

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

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

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.

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

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!

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.

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.

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.

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:

  • Children Lists (along with the resources needed, and quirks)
  • Pin assignments for each of the devices
  • Interrupt priorities
  • Clock configurations
  • reset function
  • delay function

Work is underway to move all of these things, and future support of SoCs to being 100% FDT driven from Atmel's FDT files.

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
AT91SAM9CN11 2013 Production Not Yet
AT91SAM9CN12 2013 Production Not yet
ATSAMA5D21 2015 Production Not Yet
ATSAMA5D22 2015 see ATSAMA5D21
ATSAMA5D23 2015 see ATSAMA5D21
ATSAMA5D24 2015 see ATSAMA5D21
ATSAMA5D26 2015 see ATSAMA5D21
ATSAMA5D27 2015 see ATSAMA5D21
ATSAMA5D28 2015 see ATSAMA5D21
ATSAMA5D31 2013 Production Not yet
ATSAMA5D33 2013 See ATSAMA5D31
ATSAMA5D34 2013 See ATSAMA5D31
ATSAMA5D35 2013 See ATSAMA5D31
ATSAMA5D36 2013 See ATSAMA5D31
ATSAMA5D41 2014 Production Not Yet
ATSAMA5D42 2014 see ATSAMA5D21
ATSAMA5D43 2014 see ATSAMA5D21
ATSAMA5D44 2014 see ATSAMA5D21
  • freebsdatmel.txt
  • Last modified: 2026/10/12 10:55
  • (external edit)