Using USB WiFi with K70 under uCLinux Print

 

This application note explains how to use a USB WiFi module with K70 under uClinux. The demo described in this note configures the K70 as a WiFi access point (AP), allowing other wireless devices, such as a notebook or smarthpone, to connect to the K70 using WiFi without any additional equipment. This capability makes it very easy to access a standalone K70-based device over TCP/IP, for instance, for checking the device status or offloading collected data for further processing.


Hardware Platform

The hardware platform is Emcraft Systems' K70 system-on-module (SOM) plugged into the SOM-BSB-EXT baseboard. The Cortex-M4 core is configured to run at 150 MHz. The on-chip caches are enabled by software for LPDDR.

The demo documented in this application note assumes that the Mini-B to USB 2.0 A Female cable is plugged into the USB interface connector on the SOM-BSB-EXT baseboard and that a USB Wireless adapter is plugged into the USB 2.0 A Female connector of the above cable. Supported USB Wireless adapters are based on the Ralink RT5370 chipset (for example, D-Link DWA-140 (H/W rev B3) or Comfast WU815N).

Note also that to power the K70 Starter Kit for this demo, you should plug the mini-USB Y-cable into the P1 mini-USB connector on the SOM-BSB-EXT board and then connect both links of the Y-cable into free USB ports on your PC. This is needed since this demo requires more than 500 mA for reliable operation.

 


Installing the Demo

The procedure described here explains how to install the bootable Linux image (usbwifi.uImage) to the target.

Here is how you can build and install the bootable Linux image from the project sources (usbwifi.tgz), having installed them on top of the Emcraft Systems K70 uClinux distribution.

Note: The Linux image and the sample project have been built and validated in context of the Emcraft Systems Release 1.10.1. If you are using a different release, some porting changes may be needed.


Starting the WiFi Access Point

On power-up reset, U-Boot loads the Linux image from the NAND Flash to the LPDDR and passes control to the kernel entry point:

U-Boot 2010.03-linux-cortexm-1.9.0 (Dec 06 2012 - 17:14:55)

CPU : Freescale Kinetis series (Cortex-M4)
Freqs: SYSTICK=150MHz,CCLK=150MHz,PCLK=75MHz,MACCLK=50MHz
Board: K70-SOM Rev 1.A, www.emcraft.com
DRAM: 64 MB
NAND: 128 MiB
In: serial
Out: serial
Err: serial
Net: FECO
Hit any key to stop autoboot: 0

Loading from NAND, offset 0x100000
Image Name: Linux-2.6.33-arm1
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3499008 Bytes = 3.3 MB
Load Address: 08008000
Entry Point: 08008001
## Booting kernel from Legacy Image at 08007fc0 ...
Image Name: Linux-2.6.33-arm1
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3499008 Bytes = 3.3 MB
Load Address: 08008000
Entry Point: 08008001
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK

Starting kernel ...

The kernel proceeds to boot-up, initializing the configured I/O interfaces and sub-systems:

Linux version 2.6.33-arm1 (psl @ocean.emcraft.com) (gcc version 4.4.1 (Sourcery G++ Lite 2010q1-189) ) #139 Mon Feb 4 18:17:31 +0400 2013
CPU: ARMv7-M Processor [410fc241] revision 1 (ARMv7M)
CPU: WRITE-BACK data cache, WRITE-THROUGH instruction cache
Machine: Freescale Kinetis
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: kinetis_platform=k70-som console=ttyS2,115200 panic=10
ip=172.17.6.46:172.17.0.1:::k70-som:eth0:off ethaddr=C0:B1:3C:77:88:AB
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 61492k/61492k available, 4044k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0x00000000 - 0x00001000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0x00000000 - 0xffffffff (4095 MB)
lowmem : 0x70000000 - 0x74000000 ( 64 MB)
modules : 0x70000000 - 0x01000000 (2320 MB)
.init : 0x08008000 - 0x081ec000 (1936 kB)
.text : 0x081ec000 - 0x08345000 (1380 kB)
.data : 0x08346000 - 0x0835e400 ( 97 kB)
Hierarchical RCU implementation.
NR_IRQS:106
Calibrating delay loop... 140.49 BogoMIPS (lpj=702464)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
bio: create slab at 0
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource cm3-systick
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: Freescale Kinetis UART driver
kinetis-uart.2: ttyS2 at MMIO 0x4006c000 (irq = 49) is a Kinetis UART Port console [ttyS2] enabled
FEC Ethernet Driver
fec: PHY @ 0x0, ID 0x00221556 -- KSZ8081RNL
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver

The USB controller is initialized:

mxc-ehci mxc-ehci.0: initializing i.MX USB Controller
mxc-ehci mxc-ehci.0: Freescale On-Chip EHCI Host Controller
mxc-ehci mxc-ehci.0: new USB bus registered, assigned bus number 1
mxc-ehci mxc-ehci.0: irq 96, io mem 0x40034000
mxc-ehci mxc-ehci.0: USB 2.0 started, EHCI 1.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
TCP cubic registered
NET: Registered protocol family 17
lib80211: common routines for IEEE802.11 drivers

The USB WiFi module is initialized by the USB controller:

usb 1-1: new high speed USB device using mxc-ehci and address 2
eth0: config: auto-negotiation on, 100FDX, 100HDX, 10FDX, 10HDX.
IP-Config: Guessing netmask 255.255.0.0
IP-Config: Complete:
device=eth0, addr=172.17.6.46, mask=255.255.0.0, gw=255.255.255.255,
host=k70-som, domain=, nis-domain=(none),
bootserver=172.17.0.1, rootserver=172.17.0.1, rootpath=
Freeing init memory: 1936K
init started: BusyBox v1.17.0 (2012-12-27 15:48:25 +0400)

The startup script /etc/rc loads the required kernel modules for the WiFi support:

loading modules...
compat
Compat-wireless backport release: compat-wireless-v3.4-rc3-1
Backport based on linux-stable.git v3.4-rc3
cfg80211
cfg80211: Calling CRDA to update world regulatory domain
mac80211
rt2x00lib
rt2x00usb
rt2800lib
rt2800usb
usb 1-1: reset high speed USB device using mxc-ehci and address 2
usbcore: registered new interface driver rt2800usb
~ #

The script below implements the needed actions to start the WiFi access point:

~ # cat start_ap
#!/bin/sh

echo "Starting AP"
ifconfig wlan0 192.168.1.1 up
ifconfig wlan0
hostapd /etc/hostapd-minimal.conf &
echo "Starting DHCP server"
udhcpd -f /etc/udhcpd.conf &
~ #

The script enables the wlan0 WiFi interface, then starts the user-space daemon implementing access point functionality. The daemon configuration file, /etc/hostapd-minimal.conf, has a minimal configuration to implement a no-encryption access point named k70:

~ # cat /etc/hostapd-minimal.conf
#change wlan0 to your wireless device
interface=wlan0
driver=nl80211
ssid=k70
hw_mode=g
max_num_sta=255
channel=2
~ #

The last line in the above script starts the DHCP daemon, providing network auto-configuration for connected clients. The DHCP daemon is configured to assign an address from the 192.168.1.2 - 192.168.1.255 range to the WiFi client.

Let's start the access point by running the script:

# ./start_ap
Starting AP
rt2800usb 1-1:1.0: firmware: using built-in firmware rt2870.bin
wlan0 Link encap:Ethernet HWaddr 00:0F:12:44:0C:5D
inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 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:0 (0.0 B) TX bytes:0 (0.0 B)

Starting DHCP server
udhcpd (v1.17.0) started
Configuration file: /etc/hostapd-minimal.conf
Using interface wlan0 with hwaddr 00:0f:12:44:0c:5d and ssid 'k70'
~ #

At this point, the access point is ready to accept requests for connection. Using a WiFi-connected notebook or smartphone, scan for available wireless networks and connect to the k70 network:


While connecting, you should see the progress on the K70 console:

wlan0: STA e4:ce:8f:3f:bd:b4 IEEE 802.11: authenticated
wlan0: STA e4:ce:8f:3f:bd:b4 IEEE 802.11: associated (aid 1)
wlan0: AP-STA-CONNECTED e4:ce:8f:3f:bd:b4
Sending OFFER of 192.168.1.2
Sending OFFER of 192.168.1.2
Sending ACK to 192.168.1.2

At this point, the K70 is connected to the notebook (or smartphone) over TCP/IP. Let's start the HTTP daemon with a demo webpage on the K70:

~ # httpd -h /httpd/html
~ #

On the notebook, open http://192.168.1.1 in the browser and observe the page generated by K70:

How Fast is TCP/IP on K70 using USB WiFi?

As a very rough estimate for the TCP performance of K70 using USB WiFi, here is the output of an FTP get command transferring a file from a host in a local network to K70:

~ # time wget ftp://192.168.1.2/pub/test.dat
Connecting to 192.168.1.2 (192.168.1.2:21)
test.dat 100% |*******************************| 9380k --:--:-- ETA
real   0m    12.14s
user   0m    1.11s
sys    0m    5.69s
~ #

Processing the above results, we get the following TCP performance figure:
9380KB/12.14 = 772.652 KB/sec.

As an estimate of the UDP performance, here is the output of a copy command transferring the same file from an NFS-host to the K70:

~ # mount -o nolock 192.168.1.2:/home/psl /mnt
~ # time cp /mnt/test.dat /
real   0m   8.71s
user   0m   0.06s
sys    0m   1.15s

The UDP performance is 9380KB/8.71=1076.92 KB/sec.

The WiFi connection rate (as reported in the connection status) was 54 Mb/sec in the above test.