Forth Lesson 22

From OLPC
Revision as of 17:16, 23 May 2011 by Wmb@firmworks.com (talk | contribs) (Added documentation of unaligned-mmap)
Jump to: navigation, search
Mitch Bradley's Forth and
Open Firmware Lessons:

Using Forth Under Linux

You can run Forth under Linux and use it to inspect I/O devices.

On XO-1.75

Get http://dev.laptop.org/~wmb/sdkit-arm.tgz . Unpack it into your home directory on an XO-1.75 .

 $ tar xfz sdkit-arm.tgz

Then:

 $ cd sdkit-arm
 $ sudo -s
 # ./sdkit.sh
 ok

sdkit comes up in hex mode, so you can enter and display numbers in hex without additional qualifiers. To enter a decimal number, precede it with "d# ", e.g. "d# 123"

GPIO Access

Command Stack Description Example
gpio-pin@ ( gpio# -- flag ) Flag is true if GPIO pin is high d# 108 gpio-pin@ .
gpio-out? ( gpio# -- flag ) Flag is true if GPIO is an output d# 108 gpio-out? .
gpio-set ( gpio# -- ) Drives GPIO high d# 108 gpio-set
gpio-clr ( gpio# -- ) Drives GPIO low d# 108 gpio-clr
gpio-rise@ ( gpio# -- flag ) Flag is true if rising edge detected d# 108 gpio-rise@ .
gpio-fall@ ( gpio# -- flag ) Flag is true if falling edge detected d# 108 gpio-fall@ .
gpio-edge@ ( gpio# -- flag ) Flag is true if edge detected d# 108 gpio-edge@ .
gpio-clr-edge ( gpio# -- ) Clears GPIO edge detector d# 108 gpio-clr-edge
gpio-dir-out ( gpio# -- ) Sets GPIO direction to output d# 108 gpio-dir-out
gpio-dir-in ( gpio# -- ) Sets GPIO direction to input d# 108 gpio-dir-out
gpio-set-rer ( gpio# -- ) Enables rising edge detection d# 108 gpio-set-rer
gpio-clr-rer ( gpio# -- ) Disables rising edge detection d# 108 gpio-set-rer
gpio-set-fer ( gpio# -- ) Enables falling edge detection d# 108 gpio-set-fer
gpio-clr-fer ( gpio# -- ) Disables falling edge detection d# 108 gpio-set-fer

Multi-Function Pin Register Access

The Multi-Function Pin Registers (MFPRs) control the assignment of chip pins to internal functions, and also control characteristics of those pins, such as drive strength, pull up/down resistors, etc. Since each multi-function pins can be used as a GPIO, we use the GPIO number to designate which pin we are interested in.

Command Stack Description Example
af@ ( gpio# -- function ) Returns the MFPR setting for gpio# d# 108 af@ .
af! ( function gpio# -- ) Sets the MFPR for gpio# h# a0c0 d# 108 af!
dump-mprs ( -- ) Displays a table of all MFPR settings dump-mfprs
gpio>mfpr ( gpio# -- address ) Returns the address of the MFPR register for gpio# d# 108 gpio>mfpr .

Camera Test

The camera test turns on the camera chip and lets you access internal camera chip registers via its I2C bus interface.

Command Stack Description Example
test-camera-i2c ( -- ) Turns on the camera and dumps its internal registers test-camera-i2c
start-camera ( -- ) Sets up the camera clocks and pads, powers on and resets the camera sensor chip start-camera
ov@ ( reg# -- value ) Reads an internal camera register via I2C 5 ov@ .
ov! ( value reg# -- ) Writes an internal camera register via I2C 4 12 ov!
ov-dump ( -- ) Displays a bunch of camera registers ov-dump

Accelerometer

Command Stack Description Example
select /accelerometer ( -- ) Activate accelerometer device driver select /accelerometer
acceleration@ ( -- x y z ) Read acceleration values acceleration@ .d .d .d

acceleration@ .d .d .d cr many

unselect ( -- ) Deactivate the current device driver unselect

Two-Wire Serial Interface (I2C/SMBUS) Hardware

Command Stack Description Example
set-twsi-target ( slave channel -- ) Select a TWSI channel and slave address for subsequent access h# 3a 6 set-twsi-target
twsi-b@ ( reg -- byte ) Read a byte h# 20 twsi-b@ .
twsi-b! ( byte reg -- byte ) Write a byte h# 47 h# 20 twsi-b!
twsi-write ( byte_n-1 .. byte0 n -- ) Write n bytes from the stack 33 22 11 00 4 twsi-write
twsi-get ( reg#_n-1 .. reg#0 #reg-bytes #data-bytes -- data_n-1 .. data0 ) Send #reg-bytes register address bytes from the stack, then read #data-bytes onto the stack. h# 23 h# 01 2 4 twsi-get . . . .


Accessing Arbitrary Devices

In addition to the "canned" access words for specific devices, you can manually access any device you wish, using the "mmap" command to assign a virtual address to the I/O device's physical address.

Command Stack Description Example
mmap ( phys-addr size -- virt-addr ) Assigns a page-aligned virtual address to a physical device address range d4050000 1000 mmap constant clock-unit-base
unaligned-mmap ( phys-addr -- virt-addr ) Assigns a possibly-unaligned virtual address to a physical device address d4033800 unaligned-mmap constant twsi5-base

For mmap, the physical address and size must both be multiples of 0x1000 (the CPU page size), i.e. their low three hex digits must be 0.

For unaligned-mmap, the physical address need not be page-aligned. Unaligned-mmap calls mmap with a page-aligned address (mapping a single page) and then adds the offset into the virtual address.

You can add offsets to the virtual address to access registers within the range {virtual-address .. virtual-address+size-1}. For example:

 ok d4050000 1000 mmap  constant clock-unit
 ok clock-unit 24 + l@ .

You could use unaligned-mmap to get an address that points to an individual register within a register block, but it's usually better to map the base address of the register block and then apply small offsets to the virtual address to access individual registers.