DCON Testing

From OLPC
Revision as of 17:14, 5 February 2007 by Xavi (talk | contribs) (wikification)
Jump to navigation Jump to search

This page describes how to use Open Firmware to work with the DCON. For more basic Open Firmware usage, see the OFW FAQ.

For intensive debugging, I recommend using a serial console, so you can cut and paste, log results to a file, etc. The easiest way to get a serial console is just to leave the keyboard unplugged. If you forget, you can type "com1 io" to force it over to serial. The settings are 115200,8,n,1 no flow control.

Normal Startup to Forth

To get to FORTH, just hit a key during the 6-second countdown that occurs just before autobooting. If you have a keyboard attached, hit the key thereon; otherwise do it on the serial console. The countdown period begins roughly 12 seconds after reset; the count is displayed on the console.

Note that with this method, by the time that you get to the FORTH prompt, the devices, including DCON, the screen, and the USB subsystem, have already been probed and initialized. So if you need to alter the normal probe/init sequence, you'll need to use the early debug method below.

Early Access to Forth

To get to Forth as early as possible so you can debug device startup problems, you must use a serial console, and you must be quick. Reset the target board and hover over the 'i' key on the serial console. About 7 seconds after reset, you'll see the message:

 Forthmacs
 Type 'i' to interrupt stand-init sequence

At this point you have 2 seconds to type that 'i' in order to get control. You can type a lot of 'i's if you want.

DCON-specific Tips

The DCON device driver is in the device node /dcon . The DCON driver lets you perform SMBUS accesses to the DCON registers. During normal startup, it is responsible for probing the DCON and doing some initial register setup. Note that the display driver is separate from the DCON driver. To change the patterns displayed on the screen, you would need to use the display driver.

DCON Access after Normal Startup

If you have used the "Normal startup" method above, to get into the DCON driver and interact with it, type

 ok select /dcon

In this scenario, the DCON will have already been initialized during the normal startup sequence. But modulo that prior initialization, you can still play with the DCON and change settings. The commands for that are listed in the DCON Commands section.

Early DCON Access

If you use the "Early Access to Forth" method, you can get control of the DCON initialization sequence from the outset. Assuming that you are at the early access Forth prompt:

 ok  dev /dcon
 ok  debug ?version
 Stepper keys: <space> Down Up Continue Forth Go Help ? See $tring Quit
 ok  resume

The "dev /dcon" command gets you into the namespace of the DCON driver, without actually running any code therein. "debug ?version" attaches the debugger to the "?version" method, which is the first method that actually touches the DCON hardware. It doesn't run the debugger just yet; think of it as setting a breakpoint on the "?version" routine. The "Stepper keys ..." line is a message briefly listing the main debugger keystroke commands. "resume" restarts the OFW startup sequence to initialize any hardware that must be initialized prior to the DCON. You should see several lines of init messages, then:

 Install console
 : ?version                ( 1e10a1c )
 0                      []

You are now in the Forth debugger. The [] in the above display shows where the cursor is. The ": ?version ..." line shows that the the debugger has just been entered at the beginning of the "?version" method, and that the stack currently has a single number on it - 0x1e10a1c . The next line, the one that the cursor is on, shows that the next Forth word to be executed is the number "0".


Driving the Forth Debugger

The Forth single-step debugger responds to single-key commands. The main ones are:

  • <space> - execute the word to the left of the cursor and stop at the next word, i.e. single-step
  • d - go Down and debug inside the command to the left of the cursor (only works if that command is a colon definition; you can't go down into, for example, a constant)
  • u - go Up, finishing the execution of the word the debugger is attached to, and debug the caller
  • s - See (i.e. decompile) the word you are debugging, so you can look at the context of where you are
  • f - Forth - temporarily suspend the debugger, saving all the context, and go to an ok prompt so you can execute Forth commands
  • g - Go - turn off the debugger and resume normal execution

Memorize Up, Down, Forth, See.

. The next section describes the structure of the DCON init sequence and the DCON-related Forth commands. Armed with that info, you can either continue using the debugger to single-step through the routine, or type 'f' to bail out to the ok prompt and type individual commands.

Forth commands for DCON

Forth stack diagram notation: ( a b -- c ) means that the Forth word expects two arguments "a" and "b" on the stack when it starts execution - "b" on the top of the stack, "a" underneath that. It pops them off the stack, uses them, and pushes a single result "c". Similarly, ( -- ) means no net stack effect - the word doesn't look at anything that is already on the stack, and doesn't leave anything new there.

Low level DCON access primitives

smb-on ( -- ) enables the SMBUS hardware in preparation for DCON register access. It is done automatically when you start the DCON driver, so you probably won't need to run it explicitly.

smb-off ( -- ) disables the SMBUS hardware. You probably won't need to do this explicitly.

dcon@ ( reg# -- w ) pops a register number from the stack, reads that DCON register (via SMBUS), and pushes the 16-bit contents of that register back onto the stack. Example usage:

ok 0  dcon@  .             \ Reads DCON register 0.  The "." pops the result from the stack and displays it.

dcon! ( w reg# -- w ) pops a register number from the stack, then pops a 16-bit value, and stores that value into that DCON register (via SMBUS). Example usage:

 ok e040  3a  dcon!             \ Writes 0xe040 to DCON register 0x3a.  Note that, in OFW, the default number base is hex.

gpio@ ( reg# -- n ) reads the 32-bit value from the GPIO register reg# (reg# is an offset from the GPIO block base address; OFW takes care of adding in the base address so you don't have to worry about what it is).

gpio! ( n reg# -- ) writes a 32-bit value to the GPIO register reg#.

gpio-data@ ( -- n ) reads the GPIO Read Back Low register (0x30), i.e. the one that reads the values of GPIO pins 0-15. "gpio-data@" is equivalent to "30 gpio@". Note that the GPIO setup is complicated, and in order to read a pin value, you have to enable reading it. Fortunately, most of that is taken care of by some canned setup sequences; see dcon-init in a later section.

Prepackaged DCON register access words

mode! ( mode -- ) sets the DCON mode register (register 1). Example:

 ok 69 mode!    \ Monochrome mode
 ok 89 mode!    \ Color mode

hres! ( hres -- ) sets the DCON horizontal resolution register (register 2). Examples:

 ok 458 hres!      \ Sets the horizontal resolution to 0x458
 ok d# 1200 hres!  \ Note that you can precede a number with "d# " to make it decimal
 ok h# 458 hres!    \ You can also be explicit about the hex interpretation

htotal! ( htotal -- ) sets the DCON horizontal total register (register 3). Example: d# 1256 htotal!

hsync! ( sync -- ) sets the DCON horizontal sync register (register 4). Example: h# 1808 hsync!

vres! ( vres -- ) sets the DCON vertical resolution register (register 5). Example: d# 900 vres!

vtotal! ( htotal -- ) sets the DCON vertical total register (register 6). Example: d# 912 vtotal!

vsync! ( sync -- ) sets the DCON vertical sync register (register 7). Example: h# 403 vsync!

timeout! ( to -- ) sets the DCON timeout register (register 8). Example: ffff timeout!

scanint! ( si -- ) sets the DCON scanint register (register9). Example: 0 scanint!

bright! ( level -- ) sets the brightness level (register 0xa). Example: 0 bright! f bright!

dcon-load ( -- ) sets the 0x800 GPIO bit (the DCONLOAD bit, GPIO bit 11)

dcon-unload ( -- ) clears the 0x800 GPIO bit (the DCONLOAD bit, GPIO bit 11)

dcon-blnk ( -- flag ) returns a flag that is nonzero if the 0x1000 GPIO bit is set (DCONBLNK, GPIO bit 12)

dcon-stat ( -- n ) Returns the DCON status in the 2 LSBs. This reads GPIO bits 5 and 6, and shifts them down to bits 0 and 1 of the return value on the stack.

Canned init sequences

dcon-init ( -- ) sets up a bunch of GPIO control registers so the right bits are inputs and outputs, then executes dcon-load (described above).

dcon-enable ( -- ) turn on the DCON using the "standard" enable sequence, involving accesses to DCON register 0xb, 1, and the SDRAM registers. You can see the exact sequence by typing "see dcon-enable" ("see" is Open Firmware's general-purpose decompiler).

dcon-probe? ( -- flag ) is the overall DCON startup/init method. It returns true if a DCON is present, otherwise false. It is a little complicated because it does things like doing most of the work only once (if you call it a second time it will just return the flag that says whether or not the DCON is there). But the basic sequence is: try to read the DCON ID from register 0. If that works, call dcon-init and dcon-enable .