1174

The Oberon high-level, modular programming language with its origins in Pascal and Modula-2 can be used to program the Sceptre.

Oberon is a type-safe, high-level, modular programming language with its origins in Pascal and Modula-2. It has features that allow you to design complex data structures and use them in platform-independent applications. This is all very well for desktop applications but when programming embedded systems like Elektor's Sceptre you often need to “get your hands dirty”. This means manipulating data at the byte/bit level, accessing memory-mapped registers with absolute addresses and being able to do it all with a minimal impact on performance. The latest version of the Oberon language, Oberon-07 offers the best of both of these worlds.

This is article is part of a large project published in 2010 & 2011 covering several articles:
Astrobe is an integrated development system running on Windows which incorporates an Oberon-07 compiler and linker with a powerful multi-window editor and a set of library modules. You can use it to develop applications for the NXP LPC2xxx ARM7 family, which includes the LPC2148 microcontroller used in the Sceptre prototyping system. This article describes the structure of an Oberon-07 application and some of the low-level features of Oberon-07 used when programming the Sceptre hardware directly. It shows how you can use the Astrobe development system to build a simple application.
 
The source code file of an Oberon module has the following structure:
MODULE Name;
 
<import list>
<constant declarations>
<type declarations>
<variable declarations>
<procedure declarations>
<initialisation section>
 
END Name.
 All <items> are optional but must appear in that sequence. The name of the source code file is the same as the module name with the extension ‘.mod’

Astrobe applications consist of a main module and other modules that you may have written yourself, and library/startup modules supplied with the system. The main module is the starting point of the application. It is just like any other module except for having to import the startup library module called Main: 
IMPORT Main, LPC, SYSTEM;
When writing a module intended to access public types, variables and procedures that are contained in another module must be included in the name of the module on an <import list>, e.g.
IMPORT Maths, Out, I2C;
Then you can use statements like:
Out.String("hello");
I2C.Read(CompassAddr, command, degrees);
The order of the modules in the import list is unimportant. Although you may be indirectly accessing other modules as well, you only need to include the names of modules that you explicitly reference.

To export an item from an Oberon module so that it can be accessed by another module just add an asterisk * to the item's name:
VAR count*: INTEGER;
Any other items declared in the module are hidden and protected from accidental modification by client modules that import it.

When you are viewing the source code of a module in Astrobe, a list of the imported modules is displayed in the "Imports" window. Double-click on the name of an imported library module and a definition of its interface (a list of exported items) opens in a new editor window showing which types, variables and procedures are accessible. 

LPC module: memory mapped register definitions

The LPC module contains definitions of the memory-mapped peripheral registers which are common to the LPC2xxx family: e.g. the Vectored Interrupt Controller (VIC), UART0, Timer0, Timer1 etc. The names used generally correspond to those used in the registers' descriptions in NXP's LPC2148 User Manual [4]. Refer to this manual whenever you are doing low-level programming.

As an example, the General Purpose IO (GPIO) access registers used to set or clear pins are defined as:
IOPIN* = 0E0028000H;
IOSET* = 0E0028004H;
IODIR* = 0E0028008H;
IOCLR* = 0E002800CH;
The LPC2148 used in the Sceptre has a number of additional features like UART1, Analog/Digital Converter (ADC), I2C interface, etc. Access these by importing the module named LPC2148. If you prefer, you can give this module an alias when you import it:
IMPORT LPC := LPC2148, ....
 

SYSTEM module: accessing low-level features

The SYSTEM module contains low-level functions GET, PUT, ADR, SIZE, PC, SP etc. used to access the LPC2148 hardware directly, e.g.
SYSTEM.GET (LPC.IODIR, direction);
SYSTEM.PUT (LPC.PLLFEED, 0AAH);
SYSTEM.PUT (LPC.T1MR0, 100000);
SYSTEM.PUT (LPC.IOSET, {13});
SYSTEM.PUT (FIQHandlerAddress, SYSTEM.ADR (TimerHandler));
SYSTEM functions are implemented as inline code. Most generate just one or two ARM instructions and do not have any overhead normally associated with procedures. 

The SET data type: testing, setting and clearing bits

Much of the low-level programming of the Sceptre's LPC2148 involves testing, setting and clearing specific bits of the memory-mapped registers. This is where Oberon's built-in SET data type is very useful. For example, if you have LEDs connected to pins P0.13, P0.14 and P0.15 you can light them the traditional way using hexadecimal notation:
SYSTEM.PUT (LPC.IOSET, 0E000H)
Alternatively, if you prefer, using a SET constant you can say:
SYSTEM.PUT (LPC.IOSET, { 13..15 })
The ARM7 instructions generated are identical for both cases.

To help you when working from examples using hexadecimal constants, the Astrobe menu item "Tools > Convert Hex to SET" converts them to the equivalent Oberon-07 SET constant ready to be pasted into your code. 
 
Hex value Equivalent SET constant
0 { }
1 { 0 }
0A0AH { 1, 3, 9, 11 }
0FF0A0AH { 1, 3, 9, 11, 16..23 }
0FFFFFFFFH { 0..31 }
Hex and SET Equivalents.
 

Creating a Main Module

After you have installed Astrobe, a good way to start is to build and run a simple "Hello World" application to test communication between the Sceptre and your PC. Create a subfolder in your ‘Documents\Astrobe’ folder next to the ‘Lib" and "Examples’ folder and name it ‘Projects’. Start Astrobe and select ‘File > New’ to create a new module called Untitled.mod. Select "File > Save As" to save the file in your ‘Projects’ folder with the name ‘Hello.mod’.

Copy the text from Figure 1 in the editor window. ‘Out’ is a library module which allows you to send and receive text using a terminal emulator running at 38 400 baud on a PC connected to the USB port of the Sceptre. Out.String sends the characters in the string and Out.Ln sends a CR/LF sequence.

The last part of the program is the initialisation section. This is automatically executed when you start an Oberon-07 application on the Sceptre. Initialisation sections are most often used to assign default values to module variables at startup time. These are all automatically executed before your main program is initialised.

Once you have finished typing in the program select “File > Save” to update the saved file Hello.mod.

Compile the Module

Select ‘Tools > Compile’ to compile the main module. When you compile a module the compiler reads the .mod file and the symbol files <importname.smb> for each import name on the IMPORT list.

If you copied the text from Figure 1 verbatim, the compiler will detect an error. Errors are listed in a new pane below the source window. Double-click on the error line which contains the line and column number and the cursor is positioned at that location in the source file, ready for you to correct the error.

Messages starting with an exclamation mark are just warnings e.g. “! length rounded up.”

When there are no remaining errors the compiler creates an object file called <modulename.arm>. If the interface has changed since it was last compiled its symbol file <modulename.smb> is also updated.

Linking your Application

Once your module has compiled successfully, select ‘Project > Link’ from the menu. If this is the first time you have attempted to link this module a dialog box will appear. For the Sceptre you should enter:
Target: LPC2148
Crystal Freq (Hz): 12000000
 That is the only information that is required. The <modulename>.arm file is automatically linked with all of the *.arm files it imports, and all of the *.arm files that they import... and so on. The linker creates a HEX file in the same folder as the main module. Use the FlashMagic tool to upload this file to the Sceptre as described in the main article.
 
Now that you have got your first Oberon-7 Sceptre application running, look at the source code of the demo applications and library modules supplied with Astrobe. Use these as examples of how to use the information in the LPC2148 user manual to help you write your own applications. Some more examples are available in the download section.
 
Name Description
Convert Conversion of integers to / from strings
FPU Support of mathematical operations on floating point numbers
I2C I2C0 / I2C1 Master Transmitter / Receiver mode using polling
IAP In-Application (IAP) Programming for flash ROM reading and writing
LPC Common definitions for all LPC2100 / LPC2200-family processors
LPC2103 LPC2101 / 2102 / 2103 processor definitions
LPC2106 LPC2104 / 2105 / 2106 processor definitions
LPC2129 LPC2109 / 2119 / 2129 processor definitions
LPC2138 LPC2131 / 2132 / 2134 / 2136 / 2138 processor definitions
LPC2148 LPC2142 / 2144 / 2146 / 2148 processor definitions
LPC2214 LPC2212 / 2214 processor definitions
LPC2378 LPC2364 / 2366 / 2368 / 2378 processor definitions
Main Initialisation code required by an LPC2000-family application
Math Basic mathematical and trigonometrical functions
MAU Memory Allocation Unit
Out Formatted ASCII text output
Put String-handling helper functions used by Convert and Reals
Random Pseudo-random number generator
Reals Real number support and conversion to / from strings
ResData Access constant user data attached to the program by the linker
Serial Basic polled UART serial IO
Strings General string-handling functions
SYSTEM Implementation-specific low level functions
Timer Microsecond and millisecond time measurement and delays
Traps Runtime error trapping

Astrobe comes with many ready-to-use libraries. Refer to the document ‘Oberon for LPC2000 Microcontrollers’ accessible from the Help menu for details on how to use them.