The OnBoard Suite User's Guide
v1.3
Copyright 2002-2004, Wade Guthrie. Permission is granted to copy and redistribute this document so long as it is unmodified (including the section that describes where to get this document for free) and the copyright remains intact. This should really be copyrighted by the OnBoard C group (both Yahoo! and SourceForge) since much of this has been gleaned from that discussion group but I don't know if that would be legally binding. The purpose of the copyright, anyway, is just to make sure that no one charges for the information, such as it is, that we're giving away for free.
Location. The latest version of this document can be obtained (for free) from http://onboardc.sourceforge.net/UsersManual.html. If you have any questions, comments, corrections or suggestions, please don't hesitate to send them to wade@adventure101.com.
Thanks. A special thanks goes to the incredible legion of talented individuals who have contributed to this document. The list (in alphabetical order) can be found at the end of this document. If I've left anyone out, please contact me at the above address.
1. Introduction
Table Of Contents
2. Installation
2.1 The OnBoard C Distribution
2.2 Other Stuff You Might Need
2.3 Install The OnBoard Suite
2.4 A Word or Two About Upgrading (including
rebuilding the headers)
3. User's Tutorial
3.1 If You're Not Already A Palm Programmer (in C). . .
3.2 If You're An Old Hand At Writing Palm Code. . .
4. About The Language
4.1 How is OnBoard C different from ANSI standard C?
4.2 stdio vs. Palm api
4.3 Limits
5. Beyond the Basics
5.1 Support For Other Editors
5.2 Some Dirty Internal Details
5.3 Adding New APIs
5.4 Building A Hack
5.5 Multi-Segmented Code
5.6 Using OnBoard C's Auto-Versioning
6. Reference Guide
6.1 Menus Buttons And Check Boxes
7. Answers To A Few Questions
7.1 Can I write code for some Palm platforms and have it work on others?
7.2 Is it possible to compile with a larger stack with OnBoardC?
7.3 How do you generate a header file from RsrcEdit?
7.4 How do you share my OnBoard C projects with CodeWarrior or the PRC-Tools?
8. Common Problems
8.1 Out Of Node Space
8.2 Unknown Identifier <Palm API>
This document is a user's guide for the OnBoard Suite (which is comprised of the OnBoard C compiler, the OnBoard assembler, and the SrcEdit programmer's editor). OnBoard C is a wonderful C compiler written by Roger Lawrence of Individeo. It runs on, as well as builds code for, the Palm handheld platform (with the help of the OnBoard assembler). You can always get the latest version of the tools from the following address:
1. Introduction
http://sourceforge.net/projects/onboardc/The OnBoard C compiler creates a Palm executable or (at the programmer's option) a Hackmaster hack. You can beam your new program or hotsync it to another Palm if you like. It requires nothing but a Palm (w/ the Palm OS in ROM so your code can take advantage of the library that's there). It does not need a separate run-time library.
1.1 Quickstart
In order to get that quick start we talked about, do the following:
1.2 Licensing
A quick note about this license. This license does NOT constrain code that you write and compile with any portion of the OnBoard Suite. You can write a program with SrcEdit, compile it with OnBoard C/OnBoard Asm, and sell the executable all day long. You do not have to give away the source to your code just because you used OnBoard C. In fact, the SourceForge OnBoard Suite people (i.e., the people who hold the copyright over this stuff) have agreed not to apply the GPL to the skeleton application that is generated by the OnBoard Suite -- you can start commercial applications with the skeleton.
1.3 Why Use The OnBoard Suite?
1.4 A Little History
OnBoard C started on it's path to becoming free open source software in March 2002, when Roger released the source to an editor he had built and used personally, but never released. Originally called LED--now renamed SrcEdit to avoid confusion with an existing product--this editor included many features specifically for use with OnBoard C and has been actively developed by the OnBoard C community.
In May, contact was reestablished with Roger, and he was shown the work that had been done on SrcEdit and asked if he might do one last build of OnBoard C for us that would fix a couple of nagging issues we were having. Attached to his email reply was the source code to the compiler and assembler.
That effort resulted in the source to the OnBoard Suite being placed under the GNU Public License (GPL) and put on the SourceForge site as an open source project. Note: a resource compiler (like RsrcEdit) is required to use the OnBoard Suite -- there are currently no GPLed resource editors that work with the OnBoard Suite.
1.5 Requirements
When OnBoard C begins the initial compile it builds a 'pre-compiled' version of the header file OnBoardHeader.h - this occupies about 80k, but of course more memory is consumed during a compilation, in both the static and dynamic heaps. After installation, your Palm will still need about 200kb free in order to build the header file, though once it is built the compiler can get by with a lot less (about 40k + size of source file).
1.6 Where To Go For Help
You can always report bugs and request features on the SourceForge site. When you report a bug, please do the following:
2.1 The OnBoard C Distribution
2.2 Other Stuff You Might Need
RsrcEdit
Documentation
Helpful Source Code
Other Support Software
2.3 Install The OnBoard Suite
Install the OnBoard Suite
Install the Other Stuff You Need (see above)
Bring It Up
2.4 A Word or Two About Upgrading
OnBoardCompatibility.h
Rebuilding OnBoardHeader.h
3. User's Tutorial
3.1 If You're Not Already A Palm Programmer (in C). . .
Shameless Plug Alert: If you're just starting out with the Palm API, you might want to check out the Palm Programming Cookbook. It goes through learning about event driven programming, discusses a skeleton Palm program, provides step-by-step procedures for building and handling many of the GUI items (buttons and menus, for example), and (best of all) does it from the point-of-view of an OnBoard suite programmer.
Below, you'll find a guess at the level of difficulty you may encounter using OnBoardC based on various levels of programmer experience.
3.2 If You're An Old Hand At Writing Palm Code. . .
So What's an OnBoard C Project?
Creating a Project
Creating and Editing Source Files
/* foo.c */Then, in the main form of OnBoard C, tap the 'Add' button. Select the file type (DOC Source for SrcEdit files), tap the file name, tap the 'Add' button, and (when you've added all the files you wanted to), tap 'Done'.
Note: you don't have to add header (.h) files to your project. They'll get
included through the #include directive in your source (.c) files.
You can either build and run in the same step...
Building and Running Your Code
From the OnBoard C main form:
Working with Your OnBoard C Program
Once you're done editing your file, you'll want to get back to OnBoard C. SrcEdit has an icon to do this and pEdit also has a button for this purpose. With any other editor, you can go through your application browser or use one of the many hacks (e.g., McPhling) that bounces you back and forth between applications.
At this point, tap 'build' again.
If there are compile errors, a dialog box will appear explaining the error. If you tap the 'goto' button on the dialog box, OnBoard C will launch your editor with the offending file at the offending line.
Debugging
First, there's a debugger called OBDebug and you can get it (and some documentation describing how to use it here. NOTE: This software is only a Beta release -- it was never completed and has been known to crash your Palm. You can include symbols in your OnBoard C program by checking the 'Debug' box on the OnBoard C's main form.
Next, you can get disassembly of any Palm program using RsrcEdit. Just open RsrcEdit, select your application and tap 'open', select a 'code' resource and tap 'open', tap the 'Disasm' box and you've got disassembly. Remember that this is a Dragonball processor -- you can get documentation for it here. Finally, you can always use dialog boxes & printing to the screen.
OnBoard C is pretty much vanilla C with a few caveats (most of which have been described elsewhere in this document). You're writing GUI code, so you're writing event-driven code with a mainloop. OnBoard C uses the Palm APIs rather than the stdio.h. And, of course, OnBoard C isn't precisely ANSI.
4. About The Language
4.1 How is OnBoard C different from ANSI standard C?
{ int foo; { int foo; //... } // ... }
4.2 stdio vs. Palm api
Note that you can get support for the Palm APIs that aren't in this header but there's a bit more work involved. The method for using those APIs is explained further, below.
4.3 Limits
There is an overall memory limit of 64K for any one file. There is now a limit of 32 files that can be included. At one time there was a limit to the number of source files that could be part of a project but that has been removed.
There is a limit of 512 ints of inline code. When you run into this, you'll see the following error "Too many inline values, line xx".
There's a de facto limit brought on by the fact that you can't branch over 32K. When the linker part of the OnBoard assembler generates the error message "XXX beyond 32K displacement" you'll have to start rearranging your code (in order to minimize branch distance) to get it to link. As your code gets bigger, it'll become increasingly difficult to get it to fit.
OnBoard C expects OnBoardHeader.h to be in main memory rather than on a memory stick or something like that. It does work fine in Flash ROM, though.
5. Beyond the Basics
5.1 Support For Other Editors
5.2 Some Dirty Internal Details
OnBoardC always automatically includes the contents of the supplied header file, OnBoardHeader.h, before any compilation. When launched, OnBoardC looks for a database 'CompilerData.OnBC' which contains a compressed version of the header. If it is found, all of the declarations in that database are added to the symbol table - as if OnBoardHeader.h had been included, only faster and using less memory. If it is not found, the compiler searches for OnBoardHeader.h, compiles it and builds the compressed header.
5.3 Adding New (or Unsupported) APIs
ReturnValue APIcall(Variables) SYS_TRAP(sysTrapAPIcall);For example, to add access to the ROM routine 'StrCaselessCompare', you'd add the following to either your source or the OnBoardHeader.h file you're using:
Int16 StrCaselessCompare(const Char *s1, const Char *s2) SYS_TRAP (sysTrapStrCaselessCompare);The only extra trick there is that you will have to add a #define sysTrapPalmOSCall to the number specified in the Palm documentation.
If you want to make it available in all of your programs, you can add the calls to OnBoardHeader.h. (Be sure to follow the directions to blow off the precompiled version the first time after you add it, so your additions get found.)
5.4 Building A Hack
5.5 Multi-Segmented Code
A segment is an island of code that doesn't have any branches greater than 32K inside of it. Function pointers are used as bridges between segments. Multiple segments, connected by these bridges, allow an application to grow to an arbitrarily large size. There's also a mechanism for accessing global variables between segments.
In order to build a multi-segment application in OnBoard C, do the following.
Create a file for globals (e.g. "globals.c") and include this file in each of the projects. This file includes the declaration of ALL global variables and a pointer to each function that will be called from one segment to another. You also have to define a corresponding "globals.h" file where the global variables are declared as "extern" and a MemHandle for each secondary code segment. All the "*.c" files in the project must include this header file.
Note: do NOT define any static variables (either global or local) in your application. Because static variables are allocated in memory alongside globals, statics in one file will throw-off the position of globals in that project resulting in Palm system crashes.
Note also that you may also define functions in the main 'code 1' segment which may be called by other segments by the same process.
The projects in a multi-segment can be compiled in any order.
Example
This file is included by any "c" file that uses or defines a cross-segment function or global variable. |
/* seg_globals.h */ // to be included in sources // corresponding to "globals.c" defs extern int x; extern int (*incr_x)(int); extern int (*decr_x)(int); extern MemHandle Code2Handle,Code3Handle; |
This file is part of every project. |
/* seg_globals.c */ // this file is included in all projects // global variables shared by all units int x; // functions defined in various segments int (*incr_x)(int); int (*decr_x)(int); // handle to code 2 and code 3 resources MemHandle Code2Handle,Code3Handle; |
This file, along with seg_globals.c, is part of project 2. |
/* seg2_code2.c */ #pragma segment 2 #include "seg_globals.h" // prototype definition int incr_x_local(int); // dynamic link function called in main. This function MUST // be the first function defined in the first file of the project void Code2Init() { incr_x = incr_x_local; } // definition of function called from another segment int incr_x_local(int a) { x+=a; return x; } |
This file, along with seg_globals.c, is part of project 3. |
/* seg3_code3.c */ #pragma segment 3 #include "seg_globals.h" // prototype definition int decr_x_local(int); // dynamic link function called in main. This function MUST // be the first function defined in the first file of the project void Code3Init() { decr_x = decr_x_local; } // definition of 'code 3' functions int decr_x_local(int a) { return incr_x(-a); } |
Following is the complete seg_main.c. Much of the code isn't necessary for illustration of multi-segment programming but it has the advantage of being complete -- cut and paste and you have a running, multi-segment, OnBoard C program. All code in this function that is required for multi-segment programming is commented with the string 'MULTI-SEG' and is highlighted in red.
This file is part of project 1. |
/* seg_main.c */ #include "seg_globals.h" #define MainForm 1000 #define UpButton 1001 #define DnButton 1002 // MULTI-SEG: need this API but it's not in OnBoardHeader.h #define sysSysCurAppDatabase 0xa0ac Err SysCurAppDatabase (UInt16 *card, LocalID *id) SYS_TRAP(sysSysCurAppDatabase); void showX(void); static Boolean appHandleEvent (EventPtr event); static void mainFormInit (FormPtr form); static Boolean mainFormEventHandler (EventPtr event); /* * MULTI-SEG: This function sets up the dynamic links to the function * pointers used to communicate across segments. It does that by * calling the first function in every other segment (remember that * we carefully made each secondary segment's first function the * dynamic link function). */ static void startApp() { UInt16 cardno; LocalID id; DmOpenRef db; void (*DynLink)(void); // get handle to code 2 and 3 resources in our application's // database SysCurAppDatabase(&cardno,&id); db=DmOpenDatabase (cardno,id,dmModeReadOnly); Code2Handle=DmGetResource ('code',2); Code3Handle=DmGetResource ('code',3); DmCloseDatabase(db); // get ptr to 'code 2' dynamic lnk function and call it DynLink=MemHandleLock (Code2Handle); DynLink(); // same for 'code 3' DynLink=MemHandleLock (Code3Handle); DynLink(); // set the global, x x=16; return; } // MULTI-SEG: gotta unlock the code handles static void stopApp() { MemHandleUnlock(Code2Handle); MemHandleUnlock(Code3Handle); return; } /* * Completely normal PilotMain */ UInt32 PilotMain (UInt16 cmd, void *cmdPBP, UInt16 launchFlags) { EventType event; UInt16 error; if (cmd == sysAppLaunchCmdNormalLaunch) { startApp(); FrmGotoForm(MainForm); do { EvtGetEvent (&event, evtWaitForever); if (!SysHandleEvent (&event)) if (!MenuHandleEvent (0, &event, &error)) if (!appHandleEvent (&event)) FrmDispatchEvent (&event); } while (event.eType != appStopEvent); stopApp(); FrmCloseAllForms(); } return 0; } /* * Completely normal appHandleEvent */ static Boolean appHandleEvent (EventPtr event) { FormPtr frm; UInt16 formId; Boolean handled = false; if (event->eType == frmLoadEvent) { // Load the resource for the form formId = event->data.frmLoad.formID; frm = FrmInitForm(formId); FrmSetActiveForm(frm); // install a form-specific event hdlr if (formId == MainForm) FrmSetEventHandler (frm, mainFormEventHandler); handled = true; } return handled; } /* * Only slightly abnormal mainFormEventHandler. This function * */ static Boolean mainFormEventHandler (EventPtr event) { Boolean handled = false; FormPtr frmP = FrmGetActiveForm(); switch (event->eType) { /* * the first event received by a form's event handler is the * frmOpenEvent. */ case frmOpenEvent: FrmDrawForm(frmP); mainFormInit(frmP); showX(); handled = true; break; case ctlSelectEvent: switch (event->data.ctlSelect.controlID) { case UpButton: // MULT-SEG: call function in another segment x= (*incr_x)(4); showX(); handled = true; break; case DnButton: // MULT-SEG: call function in another segment x= (*decr_x)(2); showX(); handled = true; break; } // switch which button break; } // switch event type return handled; } static void mainFormInit (FormPtr frmP) { } // Other Useful Bits void showX(void) { Char bar[40]; StrPrintF (bar, "num %03d", x); WinDrawChars(bar, StrLen(bar), 60, 30); } |
5.6 Using OnBoard C's Auto-Versioning
First, you need to enable the feature. On OnBoard C's main form, there's a checkbox marked 'Auto Version'. Check the checkbox.
Now, you need a version for OnBoard C to update. This is in the form of a tVer resource. Starting in OnBoard C, do the following:
MemHandle hVer = DmGetResource ('tver', 1000); // that's the number // you remembered char *pVer = MemHandleLock (hVer); // Now, you have a string that points to your version -- // use the string as you would like to MemHandleUnlock (hVer); DmReleaseResource (hVer);
6. Reference Guide
6.1 Menus Buttons And Check Boxes
OnBoard C -- Main Form
The 'Add' button adds files into the project.
The 'Remove' button allows for removing the selected file from the project.
The 'Edit' button launches the appropriate editor for the selected file.
The 'Type' field specifies the 4 character database type signature of the output. This is usually set to 'appl' for an application, or 'HACK' for a HackMaster hack.
The 'Creator' field specifies the 4 character database creator signature of the output, set at the user's whim to uniquely identify the output database. All lower case creator signatures are reserved for the Palm system files.
The 'PRC name' field specifies the name of the output database. This is not necessarily the same as the application name shown in the launcher (which is whatever string is stored in resource 'tAIN' #1000)
The 'Execute' checkbox, when checked, signals OnBoardC to launch the application after it's been successfully built.
The "Always Rebuild' checkbox, when checked, causes OnBoardC to delete it's intermediate files after compilation. As a result, OnBoardC will always recompile every source file whether it's been modified since the last build or not - this saves space on the Palm and handles cases where an editor might not have updated the modification date for the source file.
The 'Auto version' checkbox causes OnBoard C to bump-up a version count every time a project is compiled. For details on how to use this feature, check out the section on using OnBoard C's auto-versioning.
The 'Debug' checkbox...
OnBoard C -- 'Add To Project' Form
From the 'Options' menu :
'Delete Header' - deletes the pre-compiled header that OnBoardC uses for speedy access to the Palm ROM API, this is only used when making changes to the header file (see 'Some dirty internal details' below).
'Choose Editor' - provides a dialog box to specify which editor to launch for the Memo or Doc source files when either the 'edit' button is pressed or 'Goto' selected from the compile-error alert.
From the 'Project' menu :
'Delete Object Code' - deletes any intermediate files for the current project. This frees up the space they occupy and forces each source file to be re-built when 'Build' is pressed rather than depending on the source file modification timestamp.
'New Project' - launches a dialog that prompts for the new project name. It also provides a checkbox 'Generate Skeleton' which populates the new project with the necessary files to build an empty application. For example creating a new project named 'Cardiff' will produce the project file 'Cardiff.proj', a source file 'Cardiff.c' and resource file 'Cardiff.Rsrc'. When built, the application 'Cardiff' has an empty main form with a single 'About Cardiff' menu item and dialog.
'Open Project' - opens a dialog to select from the other OnBoardC projects.
'Rename Project' - opens a dialog to change the name of the current project.
'Delete Project' - opens a dialog to delete existing OnBoardC projects.
7. Answers To A Few Questions
7.1 Can I write code for some Palm platforms and have it work on others?
Note: your code will only work on Palm platforms -- not PocketPC, or Blackberry, or other handheld devices. Also note that an application built for one major processor type (i.e., Dragonball/68K or ARM) won't work on a Palm platform running the other major processor type.
7.2 Is it possible to compile with a larger stack with OnBoardC?
7.3 How do you generate a header file from RsrcEdit?
7.4 How do you share my OnBoard C projects with CodeWarrior or the PRC-Tools?
There still may be some portability issues. No two compilers are 100% compatible so there may be some differences that you have to address. The most probable problem is a mismatch in data types. Another compatibility problem is that OnBoard C doesn't have the error checking that host- based compilers do. Instead of investing effort documenting the known differences, the OnBoard Suite development team will put their effort into making the two compilers more compatible.
Sherpa is designed to make the OnBoard Suite compatible with the PRC tools. If you're using CodeWarrior, there's a good tutorial at http://www.xpinneret.com/OBC_and_CW.html.
Note: OnBoard C has very little code optimization and no register allocation. The same code that may have worked with GCC or CodeWarrior very well could be generated too large by OnBoard C.
8.1 Out Of Node Space
8. Common Problems
8.1 Out Of Node Space
if (a || (b && c)) foo(); // instead of this if (a) foo(); else if (b&&c) foo(); // try this
8.2 Unknown Identifier <Palm API>
I'm going to try to get everyone. If you contributed or know someone who did that's not in here, please let me know.
9. Thanks!
Keithen and Roger at individeo DOT net "Alice Campbell" <acampbell AT scsengineers DOT com> "davidsvisor" <david AT xpinneret DOT com> "Dinesh Ramalingam (IE10)" <Dinesh DOT Ramalingam AT honeywell DOT com> "drawitpalm" <andrew AT drawit DOT co DOT nz> "gomezbenz" <gomezbenz AT yahoo DOT com> "gubihu" <gubi AT icss DOT hu> "Haemish Graham" <haemish AT astraware DOT com> "hkonstas2001" <hkonstas AT total DOT net> "jdhedden" <jdhedden AT yahoo DOT com> "John P. Pywtorak" <jpywtora AT calpoly DOT edu> "John Wilund" <orlando AT runbox DOT com> "Laurent THALER" <lthaler AT free DOT fr> "Mike LaFleur" <lafleur911 AT yahoo DOT com> "Philippe Guillot" <ph DOT guillot AT wanadoo DOT fr> "William F. Hostman" <aramis AT gci DOT net> "yogsototh76" <yogsototh76 AT yahoo DOT fr>