Aeolus Development

Newlib Port and Basic Microcontroller Support

ARMStick 100

ARMStick 101

ARMStick 102

In System Programming (ISP)

Documentation and Application Notes

Downloads

Other Resources

Warranty and Returns

Contacts

Product Feedback and Suggestions

Consulting

Whats New

Privacy Policy

Store

By Robert Adsett

Thursday, April 01, 2004

Note: This library of routine only provides the adaptation of newlib to the LPC210X. See the download page for pointer to the required newlib sources and build instructions.

Microcontroller Support

In addition to straight newlib functionality this port provides support for setting up and controller aspects of the LPC210X. In addition it provides a timer that can be used to wait for a specific amount of time.

Register Support

lpc210x.h provides declarations of the peripheral registers in the 2104/5/6. lpc210x.ld is a linker script that provides the actual definitions.

Enums

Several enums are used to control the microcontroller. These enums are typedef'd to make their use in parameters clearer.


VPB_param -- used to set the ratio between the CPU clock and the VP bus clock. Possible values are:

  • VPB_DIV1 -- VPB clock = CPU clock
  • VPB_DIV2 -- VPB clock = CPU clock / 2
  • VPB_DIV4 -- VPB clock = CPU clock / 4

MAM_CONTROL -- used to control the memory access module. Possible values are:

  • MAM_disabled -- MAM disabled.
  • MAM_part_enable -- MAM partially enabled.
  • MAM_full_enable -- MAM fully enabled.

Functions


ActualSpeed

unsigned long ActualSpeed( void);

Returns the actual operating speed of the microcontroller. It takes into account the operation of the PLL. Relies on SetNativeSpeed being called earlier with the correct value.


GetUs

unsigned long long GetUs( void);

Returns the microseconds since the timer was started.


MinimumAchievableWait

unsigned int MinimumAchievableWait(void);

Returns the minimum number of microseconds that can be expected to be reasonably accurate in a WaitUs call. Values below this will not fail but may wait for a larger or smaller amount of time than requested. Indeed, the actual wait could well be identical for different values of requested wait time used below this.


SetDesiredSpeed

int SetDesiredSpeed( struct _reent *r, unsigned long desired_speed);

Set the cpu to desired frequency. Relies on an earlier call to SetNativeSpeed to inform the timing routines of the correct oscillator speed. Returns 0 if successful. errno will be set on error.

  • struct _reent *r -- re-entrancy structure, used by newlib to support multiple threads of operation.
  • unsigned long desired_speed -- CPU operating frequency in kHz.

SetMAM

int SetMAM( struct _reent *r, unsigned int cycle_time, MAM_CONTROL ctrl);

Set up the MAM. Minimal error checking, not much more than a wrapper around the register. Returns 0 if successful, something else. Returns 0 if successful. Sets errno in case of an error.

  • struct _reent *r -- re-entrancy structure, used by newlib to support multiple threads of operation.
  • unsigned int cycle_time -- number of cycles to access the flash.
  • MAM_CONTROL ctrl -- Mode to place MAM in. One of:
    • MAM_disabled
    • MAM_part_enable
    • MAM_full_enable

SetNativeSpeed

int SetNativeSpeed( struct _reent *r, unsigned long speed);

Set the oscillator frequency of the external oscillator. This is used to inform the routines that deal with cpu frequencies what the starting point is. Any error here will be multiplied later. Note: There is no way to determine or verify this value so we have to trust the caller to get it right. Returns 0 if successful.

  • struct _reent *r -- re-entrancy structure, used by newlib to support multiple threads of operation.
  • unsigned long speed -- external oscillator/crystal frequency in kHz.

StartClock

int StartClock( struct _reent *r);

Starts up the clock used for internal timing. Attempts to match the desired clock speed (CLOCK_SPEED) and initializes timing_scale_factor to a compensating scale. Returns 0 if successful, otherwise error code will be retained in errno. Note: Should be called only after all clocks have been set up. Otherwise time scale will not be correct.

  • struct _reent *r -- re-entrancy structure, used by newlib to support multiple threads of operation.

VPBControl

int VPBControl( struct _reent *r, VPB_param p);

Control the clock divider on the peripheral bus. Returns 0 if successful.

  • struct _reent *r -- re-entrancy structure, used by newlib to support multiple threads of operation.
  • VPB_parm p -- requested VPB to CPU freq rate.

VPBRate

unsigned long VPBRate( void);

Finds and returns the rate of the clock on the peripheral bus (in Hz).


UsToCounts

unsigned int UsToCounts( unsigned int us);

Converts to internal units in counts from uS. Other modules use this counter for a timebase so this needs to be available to them. Returns number of counts corresponding to us. Saturates on overflow so for large time periods it is possible to get a result lower than requested.

  • unsigned int us -- microseconds to convert to counts.

WaitUs

void WaitUs( unsigned int wait_time);

Wait for 'wait_time' us (microseconds) Will break wait into multiple waits if needed to avoid saturation.

  • unsigned int wait_time -- microseconds to convert to counts.

Device driver structure

Structure used to define a device driver.

struct device_table_entry {
   const char *name;  /* Device name.   */
   
        /* Device open method.*/
   int (*open)(struct _reent *r,const char *name, int flags, int mode);
   
        /* Device close method.*/
   int (*close)(struct _reent *r,int file);
   
        /* Device read method.*/
   _ssize_t (*read)(struct _reent *r,int file, void *ptr, size_t len);

        /* Device write method.*/
   _ssize_t (*write)(struct _reent *r,int file, const void *ptr, size_t len);
   
        /* Device ioctl method (controls device operating parameters. */
   int (*ioctl)(struct _reent *r, int file, unsigned long request, void *ptr);
   };
name
The name of the device. Used by open to find the device to open.
open
Implements open for this device. The parameters are the same as those passed to open_r. open_r (and through it open) breaks down the name passed to it and uses the device portion of the name to search for a matching device. When a matching device is found the non-device portion of the name is passed to this function. For many devices this portion will be an empty string. For some devices this will be the name of a sub-device or file. It is the responsibility of the driver to check and parse this name. The format of the name passed to open should be of the form "device_name/device_specific_sub_dev_or_file". The portion up to the / is used to match against name. The / and everything after it is optional and the portion after the / will be passed on to the device driver. Some devices may require it, some may require that there be only the device_name. On success this routine should return a non-negative number that can be used by other calls to refer to the specific file or device opened (drivers that only implement a single device will typically return 0 on success). open combines the return value with the driver index to form an unique file number newlib uses to refer to the open device/file. On failure returns a negative number and sets errno to indicate the error source.
close
The inverse of open. Takes similar parameters to close_r. close_r first breaks out the driver index from the file number passed to it and passes the remainder to this function. This function should perform any cleanup needed. For some devices drivers this will be an empty operation.
read
Reads up to len bytes from an open file/device. Bytes are read into buffer pointed to by ptr. Returns the number of bytes read or a negative number in the case of an error (errno will be set). May return 0 or block if there are no bytes to read.
write
Writes up to len bytes to an open file/device. Bytes to be written are taken from the buffer pointed to by ptr. Returns a negative number and sets errno in the case of an error, otherwise returns the number of bytes actually written.
ioctl
I/O control. See ioctl_r for a full description. Device specific control. Returns 0 if successful. Otherwise the return will be negative and errno will be set. This is the only entry that may be a null pointer. Set this to 0 if the device does not support ioctl calls, then any attempts to call ioctl for that device will result in an error return and errno will be set to ENOSYS.

List of devices. This list must be provided by the application program. Newlib adapatation uses this to determine what devices are available and how to control them. List is terminated by a null pointer entry. Note: Entries 0, 1, 2 are reserved to address stdin, stdout and stderr. These must be able to work from a standard open w/o needing further setup if they are to be transparent, alternatively they must be setup before any I/O is done. They must also not require the use of a sub-device/file to open successfully.

extern const struct device_table_entry *device_table[];

Included Device Drivers

com1
Serial port driver for Uart 0. Set baud rate before using any I/O. Support simple polled I/O. Use ioctl to set serial line characteristics.
sys
System device. Originally held some control functionality. Now essentially a dummy that discards anything sent to it.

Error Codes Specific to this port

ELPC_CANT
Can't perform requested operation.
ELPC_OOR
Argument out of range.
ELPC_INTERNAL
Internal error encountered.

IO Control

Control over the characteristics of device is provided through a facility somewhat similar to that provided by Unix and Linux. Unlike that facility it takes a fixed number of arguments with the last argument being a pointer to an input/output structure that varies based on the call being made. The only action defined at the moment is for setting serial line characteristics.


_ioctl_r

int _ioctl_r( struct _reent *r, int fd, unsigned long request, void *ptr);

Support function. Provides a version with explicit re-entrancy variable. If you would normally use open_r directly then this is the appropriate call, otherwise the companion call ioctl is probably better suited. Device specific control. Returns 0 if successful, otherwise errno will be set to indicate the source of the error.

  • struct _reent *r -- re-entrancy structure, used by newlib to support multiple threads of operation.
  • int fd -- number referring to the open file. Generally obtained from a corresponding call to open.
  • unsigned long request -- Number to indicate the request being made of the driver.
  • void *ptr -- pointer to data that is either used by or set by the driver. Varies by request.


ioctl

int ioctl( int fd, unsigned long request, void *ptr);

Support function. Device specific control. A shell to convert requests into a re-entrant form. Returns 0 if successful, otherwise errno will be set to indicate the source of the error.

  • int fd -- number referring to the open file. Generally obtained from a corresponding call to open.
  • unsigned long request -- Number to indicate the request being made of the driver.
  • void *ptr -- pointer to data that is either used by or set by the driver. Varies by request.

Request definitions. These define the requested actions.

UART_SETUP
Set up baud rate parity etc. Pass pointer to a serial_param structure that contains the information on how to set up the serial port.

structure to pass via ptr with ioctl request

struct serial_param {
    unsigned long baud;
    unsigned int length;
    unsigned int parity;
    unsigned int stop;
    };

baud is the required baud rate in Hz. The driver will set the baud rate based on this value and before returning will set baud to the actual baud rate that the driver is set to.

Possible stop bit settings, assign to stop field of serial_param.

UART_STOP_BITS_2
Provide 2 stop bits
UART_STOP_BITS_1
Provide 1 stop bit

Possible parity values, assign to parity field of serial_param.

UART_PARITY_NONE
Set to parity None
UART_PARITY_ODD
Set to parity Odd
UART_PARITY_EVEN
Set to parity Even
UART_PARITY_STICK1
Set to parity stuck on
UART_PARITY_STICK0
Set to parity stuck off

Possible word length values, assign to length field of serial_param.

UART_WORD_LEN_5
5 bit serial byte.
UART_WORD_LEN_6
6 bit serial byte.
UART_WORD_LEN_7
7 bit serial byte.
UART_WORD_LEN_8
8 bit serial byte.

Linking to the Library

If you use the -llibrary option to request the use of a library in linking remeber theat GNU expands that to liblibrary.a. So -lnewlib-lpc becomes a search for libnewlib-lpc.a.

ToDo

  • Decouple timing support from newlib support so that timing can be used independently of newlib.
  • Add a few more device drivers.
  • Expand documentation.

Home