Forth Lesson 22
Using Forth Under Linux
You can run Forth under Linux and use it to inspect I/O devices.
On XO-1.75 and XO-4
On OLPC OS builds, Forth is in /runin/sdkit-arm and can be started from Terminal:
$ su # cd /runin/sdkit-arm # RUNIN_PATH=/runin ./sdkit.sh ok █
Or download http://dev.laptop.org/~wmb/sdkit-arm.tgz . Unpack it into your home directory:
$ tar xfz sdkit-arm.tgz
Then:
$ cd sdkit-arm $ su # ./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-mfprs | ( -- ) | 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.
Recipes
Storage LED
Useful for checking that sdkit-arm is functioning.
ok d# 10 gpio-set \ turn on the LED ok d# 10 gpio-clr \ turn off the LED ok d# 10 0 do d# 10 gpio-set d# 100 ms d# 10 gpio-clr d# 400 ms loop \ blink the LED ten times
Thermal Sensor
Obtains the temperature from the CPU, until <trac>10954</trac> is fixed.
d4013200 unaligned-mmap constant thermal-base : cpu-temperature ( -- celcius ) 0 ( acc ) d# 100 0 do ( acc ) \ Accumulate 100 samples thermal-base @ ( acc reg ) h# 3ff and ( acc val ) + ( acc' ) loop ( acc ) d# 52940 - d# 196 / ( convert to celcius ) ; cpu-temperature .d
Chip ID
Reading the Chip ID register on XO-4, to demonstrate access to the CIU.
d4282c00 unaligned-mmap constant ciu ciu @ . b02128
The 2128 indicates this is a Marvell PXA2128 SoC.
Thus endeth the lesson.