Skip Navigation LinksProjects > LPC1343 Reference Design > LPC1343 Code Base Documentation (v0.5.0)

LPC1343 Code Base Documentation (v0.5.0)

An overview of the main functions and structure of the LPC1343 Code Base

The LPC1343 Code Base should be relatively easy to understand on its own, but we've put together a basic summary and some examples of the main methods that you can use to interact with the LPC1343 Reference Board.  While this documentation isn't exhaustive, it should serve as a good starting point.

German Translation: Volker Karrer was kind enough to translate this into German as well. The translated text is available here.

Last updated 23 March 2010.  This version of the documentation is out of date, and does not reflect the latest version of the LPC1343 Code Base.  A number of breaking changes were made in v1.0.0 of the Code Base.  This document  is provided for reference sake only for people using earlier versions of the library.

Table of Contents

Project Structure

The LPC1343 Code Base has a fairly simple project structure, with all peripheral and device-specific code placed in the "core/" folder, any drivers for external HW in the "drivers/" folder, and core application files placed in the root directory (notably projectconfig.h and the system header file lpc134x.h).

Project Files

Project files for CodeLite (a free cross-platform, open-source IDE) and Rowley Associates Crossworks for ARM (commercial) are included in the "build/.." folder. While both of these IDEs use the same underlying peripheral code, they do not compile using the same toolchain. CodeLite runs the Makefile in the root folder and requires a GNU GCC toolchain for ARM to be installed on your computer. Crossworks for ARM uses it's own GCC toolchain and startup code, and does not use the Makefile included in the root folder. Crossworks is ideal for complex projects where HW debugging is required (using a HW debugger like the Segger J-Link), but CodeLite should allow you to get started without a significant investment in HW and SW.

If you do not wish to use an IDE, you can also build directly from the command-line using the included Makefile in the root folder and an appropriate GNU GCC toolchain for ARM.  (If you're feeling particularly adventurous, you can also have a look at our tutorial on building a GCC toolchain from source.)

lpc134x.h

In order to make understanding (and debugging) any projects based on the LPC1343 Code Base as easy as possible, a new system header file was created.  While several header files already exist for the LPC1343, we really wanted to eliminate the use of "magic-numbers" throughout the code, so we decided to cozy up with the user manual and make our own header file. Along with the normal system registers, lpc134x.h contains appropriately labelled definitions for almost all the individual bits that can be set for each register. While there is obviously a fair amount of work involved in putting all this information into the header file, the end result is code that is much easier to understand, particularly if you are inheriting a project initially managed or created by someone else.

What are Magic Numbers?
Entering raw ("magic") numbers into your program may be quicker on the front-end of a project, but which of these two (identical when compiled) lines of code would you rather be faced with debugging six months from now?
UART_U0LCR = 0x83;
UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
              UART_U0LCR_Stop_Bit_Select_1Bits |
              UART_U0LCR_Parity_Disabled |
              UART_U0LCR_Break_Control_Disabled |
              UART_U0LCR_Divisor_Latch_Access_Enabled);

projectconfig.h

The projectconfig.h file contains a variety of definitions and enumerations that are used throughout the project.  By placing this information in one file, it's much easier to maintain up-to-date code when small changes are made, such as adjusting the speed of the system clock, as well as allowing one central location to enable or disable various code blocks or device features.

Core Peripherals (core/...)

Code to initialise and interact with all of the internal peripherals on the LPC1343 is located in the 'core' folder.

External Hardware (drivers/...)

Any code that interacts with external HW is located in the 'drivers' folder.

Core Peripherals

Most of the peripherals available on the LPC1343 or accessible using the code provided in the LPC1343 Code Base, including methods to initialise and interact with them.  For details on customising the behaviour of individual peripherals, consult the latest version of the LPC1343 User Manual.

Core/CPU

The LPC1343 can be configured to run at speeds up to 72MHz.  By default, the core system clock will be set to the maximum speed (72MHz), and the external 12MHz crystal will be used.  (The LPC1343 also contains an internal 12MHz oscillator, but it isn't as accurate as an external crystal and can not be used with USB.)  In order to reduce power consumption all pins are set to GPIO and input, with their internal pull-up resistors left in the default "pull-up" state (meaning all pins are being pulled high after the cpu is first initialised). If you wish to use a lower speed system clock (which will consume less power), or configure the default pin states differently, you will need to modify the code in the cpuInit method. 

void cpuInit (void)

Initialises the system clocks to use the external crystal and run at maximum speed (12MHz x 6 = 72MHz).  This should be the first function called by your application, since the rest of the LPC1343 Code Base will not perform as expected if the CPU is in an 'unknown' state.  All pins are set to GPIO with the internal pull-up resistor enabled (to reduce power consumption by ensuring that no pins are left 'floating').

Arguments
  • None
#include "core/cpu/cpu.h"

int main(void)
{
  cpuInit();

  // Enter permanent loop
  while(1);
}
cpuDeviceID_t cpuGetDeviceID (void)

Get's the CPU part number from the CPU ID register

Arguments
  • None

Returns

cpuDeviceID_LPC1311, cpuDeviceID_LPC1313, cpuDeviceID_LPC1342, cpuDeviceID_LPC1343 or cpuDeviceID_Unknown

#include "core/cpu/cpu.h"

int main(void)
{
  cpuInit();

  cpuDeviceID_t id = cpuGetDeviceID();

  if (id == cpuDeviceID_LPC1343)
  {
    // Part is either LPC1343FBD48 or LPC1343FHN33
  }

  // Enter permanent loop
  while(1);
}

Core/ADC

The LPC1343 includes an 8-channel, 10-bit analog-to-digital converter (ADC), capable of measuring between 0 and 3.6V (not to exceed VDD, which is set to 3.3V in the case of the LPC1343 Reference Board). Each channel can be read individually, or all eight channels can be read at once in 'Burst' mode. Currently, only one channel is read at a time for simplicity sake (this should be sufficient for most situations).

void adcInit (void)

Initialises the A/D converter and configures channels 0..3 for 10-bit, SW-controlled A/D conversion.

Arguments
  • None

See the example for adcRead
uint32_t adcRead (uint8_t channelNum)

This function will manually start an A/D conversion on a single channel (0..7) and return the conversion results (0..1023).

Arguments
  • uint8_t channelNum: The A/D channel [0..7] that will be used during the A/D conversion.

Returns

0 if an overrun error occurred, otherwise a 10-bit value containing the A/D conversion results.

Warning

Only AD channels 0..3 are configured for A/D in adcInit. If you wish to use A/D pins 4..7 they will also need to be added to the adcInit function

#include "core/cpu/cpu.h"
#include "core/adc/adc.h"

void main (void)
{
  cpuInit();
  adcInit();

  uint32_t results = 0;  
  while(1)
  {
    // Get A/D conversion results from A/D channel 0
    results = adcRead(0);
  }
}

Core/GPIO

GPIO (General Purpose Input/Output) is used for digital I/O, and each pin can be configured as either an input (meaning that you can read the pin's externally adjustable state) or as an output (to turn an LED on or off, for example). In addition to simple I/O, every GPIO pin on the LPC1343 can be configured to behave as an external interrupt source, meaning that an interrupt can be raised when a pin's state changes (such as a button being pressed). This is different than some earlier ARM7 chips that had a limited number of EINTs. Each GPIO pin also has an internal resistor that can either be disabled or configured to work in pull-up, pull-down, or 'repeater' mode (see the User Manual for further details on the different modes, specifically chapter 5 "LPC13xx I/O Configuration"). While the addition of internal resistors is, in itself, a welcome addition since it reduces the overall external parts count and adds more flexibility to your system, it also requires a bit more attention on the part of developpers to make sure that the resistor is always set in an appropriate state (see gpioSetPullup for further details).

void gpioInit (void)

Initialises GPIO and enables the GPIO interrupt handler for all GPIO ports.

Arguments
  • None

See the example for gpioSetValue
void gpioSetDir (uint32_t portNum, uint32_t bitPos, gpioDirection_t dir)

Sets the direction (input/output) for a specific port pin.

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]
  • dir: the pin direction (gpioDirection_Input or gpioDirection_Output)

See the example for gpioSetValue
void gpioSetValue (uint32_t portNum, uint32_t bitPos, uint32_t bitVal)

Sets the value for a specific port pin (only relevant when a pin is configured as output).

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]
  • bitVal: indicates whether the pin should be set high (1) or low (0).

#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"

int main (void)
{
  cpuInit();
  gpioInit();

  // Set GPIO1.8 to output
  gpioSetDir(1, 8, gpioDirection_Output);
  // Disable the internal pullup/down resistor on P1.8
  gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
  // Set GPIO1.8 high
  gpioSetValue(1, 8, 1);

  while(1);
}
uint32_t gpioGetValue (uint32_t portNum, uint32_t bitPos)

Gets the value for a specific port pin.

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]

Returns

1 if the pin is currently high, or 0 is the pin is currently low.

Warning

All GPIO pins on the LPC1343 have internal pull-up/pull-down resistors that can be individually configured. By default, the LPC1343 will enable the pull-up resistors on most pins when it comes out of reset. The rationale behind this decision is that placing the pins in a defined state will avoid wasting power when pins are left 'floating', but it can also cause some confusion if you are not explicitly setting the resistors to a different state yourself should this be required. In order to avoid problems, you should always explicitly set the state of the internal resistor using gpioSetPullup.

#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"

int main (void)
{
  cpuInit();
  gpioInit();

  // Set GPIO1.8 to input
  gpioSetDir(1, 8, gpioDirection_Input);
  // Disable the internal pullup/down resistor on P1.8
  gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);

  uint32_t results = 0;
  while(1)
  {
    // Read the current state of GPIO1.8 (1 = high, 0 = low)
    results = gpioGetValue(1, 8);
  }
}
void gpioSetPullup (volatile uint32_t *ioconReg, gpioPullupMode_t mode)

All GPIO pins on the LPC1343 have internal pull-up/pull-down resistors that can be individually configured. This method can be used to explicitly set the internal resistor's 'mode' of operation. For details on the different modes (inactive, pull-up, pull-down, or repeater) see chapter 5 of the LPC1343 User Manual (figure 5 in particular).

Arguments
  • *ioconReg: pointer to the IOCON register for the appropriate pin (ex. 'IOCON_PIO1_8' for GPIO 1.8, 'IOCON_PIO2_2' for GPIO 2.2, etc.). Note: Since this is a pointer, you need to pass the 'address' of the register in to the method, and not it's value. This can be accomplished by placing a '&' just before the name of the IOCON register, for example: 'gpioSetPullup(&IOCON_PIO2_2, gpioPullupMode_Inactive);'.
  • mode: the mode to set the internal resistor to (gpioPullupMode_Inactive, gpioPullupMode_PullDown, gpioPullupMode_PullUp or gpioPullupMode_Repeater).

Warning

By default, the LPC1343 will enable the pull-up resistors on most pins when it comes out of reset. The rationale behind this decision is that placing the pins in a defined state will avoid wasting power when pins are left 'floating', but it can also cause some confusion if you are not explicitly setting the resistors to a different state yourself should this be required. In order to avoid problems, you should always explicitly set the state of the internal resistor.

#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"

int main (void)
{
  cpuInit();
  gpioInit();

  // Set GPIO1.8, 1.9, 1.10 and 1.11 to input
  gpioSetDir(1, 8, gpioDirection_Input);
  gpioSetDir(1, 9, gpioDirection_Input);
  gpioSetDir(1, 10, gpioDirection_Input);
  gpioSetDir(1, 11, gpioDirection_Input);

  // Enable the pull-down resistor on P1.8
  gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_PullDown);
  // Enable the pull-up resistor on P1.9
  gpioSetPullup (&IOCON_PIO1_9, gpioPullupMode_PullUp);
  // Disable the internal resistor resistor on P1.10
  gpioSetPullup (&IOCON_PIO1_10, gpioPullupMode_Inactive);
  // Set P1.11 to 'Repeater' (remembers the last state explicitly set)
  gpioSetPullup (&IOCON_PIO1_11, gpioPullupMode_Repeater);

  while(1);
}
void gpioSetInterrupt (uint32_t portNum, uint32_t bitPos, gpioInterruptSense_t sense, gpioInterruptEdge_t edge, gpioInterruptEvent_t event)

Any GPIO pin on the LPC1343 can be configured as an external interrupt source. The gpioSetInterrupt method allows you to determine which pins act as an interrupt source, and specify the conditions under which an interrupt should be raised (if the pin goes high or low, etc.). Depending on the portNum specified, the interrupt will be handled (by default) by PIOINTx_IRQHandler, where 'x' is the port number in question (PIOINT1_IRQHandler would be entered if an interrupt was raised on GPIO pin 1.8, for example).

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]
  • sense: whether the interrupt should be configured as edge (gpioInterruptSense_Edge) or level (gpioInterruptSense_Level) sensitive.
  • edge: whether an interrupt is triggered on one edge (gpioInterruptEdge_Single) or on both (gpioInterruptEdge_Double).
  • event: whether the rising edge (gpioInterruptEvent_ActiveHigh) or the falling edge (gpioInterruptEvent_ActiveLow) should be used to trigger the interrupt. ActiveHigh means that a HIGH level on the pin will trigger an interrupt, ActiveLow means that a LOW level on the pin will trigger an interrupt.

#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"

int main (void)
{
    cpuInit();
    gpioInit();

    // Set GPIO1.8 to input
    gpioSetDir(1, 8, gpioDirection_Input);
    // Disable the internal pullup/down resistor on P1.8
    gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
    // Setup an interrupt on GPIO1.8
    gpioSetInterrupt(1,                               // Port
                     8,                               // Pin
                     gpioInterruptSense_Edge,         // Edge Sensitive
                     gpioInterruptEdge_Single,        // Single Edge
                     gpioInterruptEvent_ActiveHigh);  // Active High
    // Enable the interrupt
    gpioIntEnable(1, 8);

    while (1);
}
void gpioIntEnable (uint32_t portNum, uint32_t bitPos)

Enables an interrupt on the specified GPIO pin.

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]

See the example for gpioSetInterrupt.
void gpioIntDisable (uint32_t portNum, uint32_t bitPos)

Disables an interrupt on the specified pin.

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]

See the example for gpioSetInterrupt.
void gpioIntClear (uint32_t portNum, uint32_t bitPos)

Clears the interrupt on the specified pin. This method should only be called from withint the interrupt service routine (ISR) once the interrupt has been raise.

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]

// IRQ Handler for GPIO Port 1
void PIOINT1_IRQHandler(void)
{
  uint32_t regVal;

  // Check if pin 1.8 raised the interrupt  
  regVal = gpioIntStatus(1, 8);
  if (regVal)
  {
    // Do Something
    ...
    // Clear the interrupt
    gpioIntClear(1, 8);
  }		
  return;
}
See the example for gpioSetInterrupt to configure an interrupt.
uint32_t gpioIntStatus (uint32_t portNum, uint32_t bitPos)

Gets the interrupt status for a specific port pin.

Arguments
  • portNum: the gpio port number [0..3]
  • bitPos: the bit position for the gpio pin [0..11]

Returns

'1' if an interrupt was raised by the specified pin, otherwise '0'.

See the example for gpioIntClear.

Core/PMU

Configures the Power Management Unit (PMU) to control sleep, deep-sleep and power-down modes. Any GPIO pin can be configured to wake the device up from sleep modes, but only a low-level on pin 1.4 (WAKEUP) can wake the device up from power-down.

void pmuInit(void)

Initialises the power management unit, and configures pin 0.1 to act as a wakeup source from sleep or deep-sleep mode.

Arguments
  • None

Notes

For sleep and deep-sleep modes -- entered via pmuSleep and pmuDeepSleep-- any I/O pin can be used as a wakeup source. For deep power-down mode -- entered via pmuPowerDown -- only a low level on pin 1.4 (WAKEUP) can wake the device up.

By default, only P0.1 is configured as a wakeup source, but the appropriate code to enable any other pin as a wakeup source (from sleep or deep-sleep mode) is provided in pmuSleep and simply needs to be uncommented (the pin configured for GPIO may also need to be set to GPIO, following the example for P0.1).

See the examples for pmuSleep, pmuDeepSleep and pmuPowerDown.
void pmuSleep(void)

This function will put the device into sleep mode. Any gpio pin can be used to wake the device up (however, the pins must first be configured for this in pmuInit).

Arguments
  • None

#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"

int main(void)
{
    cpuInit();

    // Configure wakeup sources before going into sleep/deep-sleep.
    // By default, pin 0.1 is configured as wakeup source (falling edge)
    pmuInit();

    // Enter sleep mode
    pmuSleep();

    while(1)
    {
        // Wait for an interrupt to wake the device up
    }
}
void pmuDeepSleep( uint32_t sleepCtrl, uint32_t wakeupSeconds )

This function will put the device into deep-sleep mode. Any gpio pin can be used to wake the device up (however, the pins must first be configured for this in pmuInit). The sleepCtrl parameter is used to indicate which peripherals should be put in sleep mode (see the SCB_PDSLEEPCFG register for details). Optionally, providing a non-zero value to wakeupSeconds will cause the device to wakeup from deep-sleep after the specified delay using 32-bit timer 0 and pin 0.1 (CT32B0_MAT2).

Arguments

  • sleepCtrl: The bits to set in the SCB_PDSLEEPCFG register. This controls which peripherals will be put in sleep mode.
  • wakeupSeconds: If this is greater than 0, the device will be configure to wakeup from deep-sleep after the specified number of seconds.

#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"

int main(void)
{
    cpuInit();

    uint32_t pmuRegVal;

    // Configure wakeup sources before going into sleep/deep-sleep.
    // By default, pin 0.1 is configured as wakeup source (falling edge)
    pmuInit();

    // Inidicate which peripherals should be disabled in deep-sleep
    pmuRegVal = SCB_PDSLEEPCFG_IRCOUT_PD | 
                SCB_PDSLEEPCFG_IRC_PD | 
                SCB_PDSLEEPCFG_FLASH_PD | 
                SCB_PDSLEEPCFG_USBPLL_PD | 
                SCB_PDSLEEPCFG_SYSPLL_PD | 
                SCB_PDSLEEPCFG_SYSOSC_PD | 
                SCB_PDSLEEPCFG_ADC_PD | 
                SCB_PDSLEEPCFG_BOD_PD;

    // Enter deep sleep mode and wakeup after 10 seconds
    pmuDeepSleep(pmuRegVal, 10);

    while(1)
    {
    }
}
void pmuPowerDown( void )

This function will configure the PMU control register and enter deep power-down mode. Optionally, pre-determined values can be stored in the four general-purpose registers (PMU_GPREG0..3), which can be used to persist any essential system settings while the device is in deep power-down mode, so long as 3.3V is still available.

Arguments
  • None

Warning

The only way to wake a device up from deep power-down mode is to set a low-level on P1.4 (WAKEUP). If 3.3V power is lost, the values stored in the four general-purpose registers will also be lost.

#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"

int main(void)
{
    cpuInit();
    pmuInit();

    // Enter power-down mode
    pmuPowerDown();

    while(1)
    {
        // Device was woken up by WAKEUP pin
    }
}

Core/SSP

Generic code for SSP/SPI communications. By default, the SSP block is initialised in SPI master mode

void sspInit (uint32_t portNum, sspClockPolarity_t polarity, sspClockPhase_t phase)

Initialises the SSP port. By default, SSP is set to SPI frame-format with 8-bit data. Pin 2.11 is routed to serve as serial clock (SCK), and SSEL (0.2) is set to GPIO to allow manual control of when the SPI port is enabled or disabled. Overrun and timeout interrupts are both enabled.

Arguments
  • portNum: The port number. (This should always be 0 on the LPC1343, since there is only 1 SSP port available.  The portNum is provided for code compatability with other devices containing more than one SSP port.)
  • polarity: Indicates whether the clock should be held high (sspClockPolarity_High) or low (sspClockPolarity_Low) when inactive.
  • phase: Indicates whether new bits start on the leading (sspClockPhase_RisingEdge) or falling (sspClockPhase_FallingEdge) edge of clock transitions

Notes

sspSelect() and sspDeselect() macros have been defined in ssp.h to control the SSEL line without having to know the specific pin being used.

See the example for sspSend
void sspSend (uint32_t portNum, uint8_t *buf, uint32_t length)

Sends a block of data to the SSP port

Arguments
  • portNum: The port number. (This should always be 0 on the LPC1343, since there is only 1 SSP port available.  The portNum is provided for code compatability with other devices containing more than one SSP port.)
  • *buf: Pointer to the data buffer
  • length: Block length of the data buffer

#include "core/cpu/cpu.h"
#include "core/ssp/ssp.h"

#define SSP_FIFOSIZE		8

int main(void)
{
    cpuInit();
    sspInit(0, sspClockPolarity_High, sspClockPhase_RisingEdge);

    uint8_t request[SSP_FIFOSIZE];
    uint8_t response[SSP_FIFOSIZE];

    // Send 0x9C to the slave device and wait for a response

    // Fill request buffer
    request[0] = 0x80 | 0x1C;

    // Enable CS line
    ssp0Select();

    // Send the 'request' data (1 byte)
    sspSend(0, (uint8_t *)&request, 1);

    // Wait for the response (1 byte)
    sspReceive(0, (uint8_t *)&response, 1);

    // Disable CS line
    ssp0Deselect();
}
void sspReceive(uint32_t portNum, uint8_t *buf, uint32_t length)

Receives a block of data from the SSP port

Arguments
  • portNum: The port number. (This should always be 0 on the LPC1343, since there is only 1 SSP port available.  The portNum is provided for code compatability with other devices containing more than one SSP port.)
  • *buf: Pointer to the data buffer
  • length: Block length of the data buffer

See the example for sspSend

Core/Systick

Controls the 24-bit 'system tick' timer, which can be used as a generic timer or to control time sharing with an embedded real-time operating system (FreeRTOS, Crossworks CTL, etc.).

void systickInit (uint32_t delayMs)

Initialises the systick timer with the specified delay in millaseconds (typical 10ms). This will cause a systick interrupt to be raised every x millaseconds, and an unsigned 32-bit variable named "msTicks" will be incremented by one every time the interrupt is fired.

Arguments
  • delayMs: Indicates the length of time in millaseconds between each system 'tick'.
See the example for systickDelay.
void systickDelay (uint32_t delayTicks)

Causes a blocking delay for the specific number of systick timer ticks. The length of the delay depends on the value supplied to the systickInit function. The delay can be calculated by multiplying delayMs from systickInit with delayTicks. (For example, if the systick timer is configure for 10mS ticks, a delayTicks value of 15 would cause a 150mS delay.)

Arguments
  • delayTicks: The number of systick ticks to wait.
#include "core/cpu/cpu.h"
#include "core/systick/systick.h"

int main (void)
{
  // Initialise the cpu
  cpuInit();
  // Initialise the systick timer with one tick every 10 millaseconds
  systickInit(10);

  while(1)
  {
    // Wait 15 ticks on the systick timer (meaning 150ms)
    systickDelay(15);
    // Do something ...
  }
}

Core/Timer16

Controls either of the 16-bit timers available on the LPC1343. It's worth noting that while the 16-bit and 32-bit timers are functionally identical, the 16-bit timers are limited to roughly 0.91mS (or 910uS) on a system running at 72MHz since:
1 mS = CFG_CPU_CCLK / 1000
     = 72000000 / 1000
     = 72000 'ticks'

Thus the maximum value of a 16-bit timer, 0xFFFF (65535), is equal to 0.910208 milliseconds. As such, if you are using the timers exclusively for timing delays, you may want to consider using a 32-bit timer since it provide a much larger maximum delay (~59 seconds on a 72MHz system). The 16-bit timers are still very useful for a number of other situations, or if you required very fine-grained control over timing, but are limited to millisecond and microsecond timing. (Running the system at a slower clock speed will also increase the maximum delay possible with a 16-bit timer.)

Both 16-bit and 32-bit timers can be used in co-ordination with external pins so that when a 'match' occurs (after a predetermined delay), a pin can either be set high, low, or toggled. Each timer's match register can also be configured as PWM, allowing you to create single edge controlled PWM outputs.

Blocking versus non-blocking delays: Two different types of delays are supported with this code (though the timers can be used for more than just delays!). The first type of delay, using timer16DelayTicks and timer16DelayUS, is referred to as a blocking delay since it will block the execution of any other code (except an interrupt) until the specified delay has passed. This can be both desirable or undesirable, depending on the task as hand. The second type of delay is based on interrupts, and involves simply checking a pre-defined variable that will increment by one every time a fixed delay elapses. (The 32-bit variable that counts up will automatically 'roll-over' to 0 once 0xFFFFFFFF has been reached.) An example of how to use this non-blocking delay is visible in the example for timer16Init.
void timer16Init(uint8_t timerNum, uint16_t timerInterval)

Initialises a 16-bit timer with the supplied timer interval (the amount of time that passes between each timer 'tick'). Every time that this interval elapses, the timer's interrupt will be fired and the appropriate counter variable will be incremented by one (For example, with CT16B0, 'timer16_0_counter' would be incremented).

Arguments
  • timerNum: The 16-bit timer to initialise [0..1]
  • timerInterval: The number of clock 'ticks' between resets [0..65534]

Warning

Care needs to be taken when configuring the timers since the pins are all multiplexed with other peripherals. This code is provided as a starting point, but it will need to be adjusted according to your own situation and pin/peripheral requirements

#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"

// Instantiated in timer16.c
extern volatile uint32_t timer16_0_counter;

int main(void)
{
    cpuInit();

    // Initialise timer0 with a delay of 0xFFFF, which will cause the
    // timer interrupt to fire every 65535 ticks and increment
    // timer16_0_counter by 1
    timer16Init(0, 0xFFFF);

    // Enable the timer
    timer16Enable(0);

    // At this point timer16_0_counter should start incrementing by 1
    // every 65535 ticks

    while(1)
    {
        // If the timer has been fired 10 times, disabled the timer
        if (timer16_0_counter == 10)
        {
            timer16Disable(0);
        }
    }
}
void timer16DelayTicks(uint8_t timerNum, uint16_t delayInTicks)

Causes a blocking delay for the specified number of clock ticks.

Arguments
  • timerNum: The 16-bit timer to use [0..1]
  • delayInTicks: The number of clock ticks to delay [0..65534]

Notes

The exact duration of this delay depends on the speed of the system clock, but it will invariably be short because of the 16-bit limitation. For example, on a system with a 72MHz clock, a 1mS delay would be equal to 72,000 ticks, which is already above the maximum 16-bit value of 65,535. Thus, the maximum delay measured in mS with a 72MHz clock is ~0.91mS.

#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"

int main(void)
{
    cpuInit();

    // Initialise timer 0 ... delay is provided but not used here
    timer16Init(0, 0xFFFF);

    // Enable the timer
    timer16Enable(0);

    while(1)
    {
        // Cause blocking delay for 36000 ticks (0.5mS @ 72MHz)
        // Note: The delay must be 65534 or less (16-bit value)
        timer16DelayTicks(0, 36000);
    }
}
void timer16DelayUS(uint8_t timerNum, uint16_t delayInUS)

Causes a blocking delay for the specified number of microseconds.

Arguments
  • timerNum: The 16-bit timer to use [0..1]
  • delayInUS: The number of microseconds to wait

Warning

The maximum delay in uS will depend on the clock speed, but running at 72MHz the maximum delay (MR = 0xFFFF) would be 910uS (0xFFFF / 72 = 910), or 0.91 milliseconds.

#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"

int main(void)
{
    cpuInit();

    // Initialise timer 0 ... delay is provided but not used here
    timer16Init(0, 0xFFFF);

    // Enable the timer
    timer16Enable(0);

    while(1)
    {
        // Cause blocking delay for 500 microseconds (0.5mS)
        timer16DelayUS(0, 500);
    }
}
void timer16Enable(uint8_t timerNum)

Enables the specified timer (which will cause any configured interrupts to fire)

Arguments
  • timerNum: The 16-bit timer to enable [0..1]

See the example for timer16Init
void timer16Disable(uint8_t timerNum)

Disables the specified timer (which will stop any configured interrupts from firing)

Arguments
  • timerNum: The 16-bit timer to disable [0..1]

See the example for timer16Init
void timer16Reset(uint8_t timerNum)

Resets the specified timer.

Arguments
  • timerNum: The 16-bit timer to reset [0..1]

Core/Timer32

Controls either of the 32-bit timers available on the LPC1343. It's worth noting that while the 16-bit and 32-bit timers are functionally identical, but the 32-bit timers support a much longer delay. For example, on a system running at 72MHz since:
1 mS = CFG_CPU_CCLK / 1000
     = 72000000 / 1000
     = 72000 'ticks'

Thus the maximum value of a 32-bit timer, 0xFFFFFFFF (4,294,967,295), is equal to 59652 milliseconds (slightly less than 1 minute). As such, if you are using the timers exclusively for timing delays, you may want to consider sticking to 32-bit timers since they provide a much larger maximum delay (versus ~0.91 milliseconds with a 16bit timer @ 72MHz).

Both 16-bit and 32-bit timers can be used in co-ordination with external pins so that when a 'match' occurs (after a predetermined delay), a pin can either be set high, low, or toggled. Each timer's match register can also be configured as PWM, allowing you to create single edge controlled PWM outputs.

void timer32Init(uint8_t timerNum, uint32_t timerInterval)

Initialises a 32-bit timer with the supplied timer interval (the amount of time that passes between each timer 'tick'). Every time that this interval elapses, the timer's interrupt will be fired and the appropriate counter variable will be incremented by one (For example, with CT32B0, 'timer32_0_counter' would be incremented).

Arguments
  • timerNum: The 32-bit timer to initialise [0..1]
  • timerInterval: The number of clock 'ticks' between resets [0..4,294,967,294]

Warning

Care needs to be taken when configuring the timers since the pins are all multiplexed with other peripherals. This code is provided as a starting point, but it will need to be adjusted according to your own situation and pin/peripheral requirements

#include "/core/cpu/cpu.h"
#include "/core/timer32/timer32.h"

// Instantiated in timer32.h
extern volatile uint32_t timer32_0_counter;

int main(void)
{
    cpuInit();

    // Initialise timer0 with a delay of 72000, which will cause the
    // timer interrupt to fire every 1mS @ 72MHz and increment
    // timer32_0_counter by 1
    timer32Init(0, 72000);

    // Enable the timer
    timer32Enable(0);

    // At this point timer32_0_counter should start incrementing by 1
    // every 72000 ticks

    while(1)
    {
        // If the timer has been fired 10 times, disabled the timer
        if (timer32_0_counter == 10)
        {
            timer32Disable(0);
        }
    }
}
void timer32Delay(uint8_t timerNum, uint32_t delay)

Causes a blocking delay for the specified number of 'ticks' on the timer. The duration of each tick is determined by the 'timerInterval' property supplied to timer32Init

Arguments
  • timerNum: The 32-bit timer to use [0..1]
  • delay: The number of timer counter increments to wait

Warning

The maximum delay will depend on the the 'timerInterval' value supplied when initialising the timer (see timer32Init).

#include "/core/cpu/cpu.h"
#include "/core/timer32/timer32.h"

int main(void)
{
    cpuInit();

    // Initialise timer 0 with 1 millisecond 'ticks'
    timer32Init(0, TIMER32_CCLK_1MS);

    // Enable the timer
    timer32Enable(0);

    while(1)
    {
        // Cause a blocking delay for 1.5 seconds (1500 milliseconds)
        timer32Delay(0, TIMER32_DELAY_1MS * 1500);
    }
}
void timer32Enable(uint8_t timerNum)

Enables the specified timer (which will cause any configured interrupts to fire)

Arguments
  • timerNum: The 32-bit timer to enable [0..1]

See the example for timer32Init
void timer32Disable(uint8_t timerNum)

Disables the specified timer (which will stop any configured interrupts from firing)

Arguments
  • timerNum: The 32-bit timer to disable [0..1]

See the example for timer32Init
void timer32Reset(uint8_t timerNum)

Resets the specified timer.

Arguments
  • timerNum: The 32-bit timer to reset [0..1]

Core/UART

Allows simple text messages to be sent and received over a serial port or USB to serial-port bridge like the FTDI232RL. Any incoming text is placed in a FIFO queue to all the data to be safely processed, without having to worry about new data arriving via the interrupt during processing.

uart_pcb_t *uartGetPCB ()

Get a pointer to the UART's protocol control block, which can be used to check the UART status value, determine whether UART has already been initialised or not, determine if any outgoing data is waiting to be transmitted, and get a reference to the RX FIFO. 

Arguments
  • None
// Make sure that UART is initialised
uart_pcb_t *pcb = uartGetPCB();
if (!pcb->initialised)
{
  uartInit(CFG_UART_BAUDRATE);
}
void uartInit (uint32_t baudrate)

Initialises UART at the specified baud rate.

Arguments
  • baudRate: The baud rate to use when configuring the UART (ex. '57600').
#include "core/cpu/cpu.h"
#include "core/uart/uart.h"

#define UARTBUFFERSIZE 5

int main(void)
{
    cpuInit();
    uartInit(57600);

    uint8_t uartBuffer[UARTBUFFERSIZE] = { 'T', 'e', 's', 't', '\n' };

    while(1)
    {  
        // Constantly send contents of uartBuffer
        uartSend((uint8_t *)uartBuffer, UARTBUFFERSIZE);
    }
}
void uartSend (uint8_t *bufferPtr, uint32_t length)

Sends the contents of the buffer over UART.

Arguments
  • *bufferPtr: Pointer to the text buffer
  • length: The size of the text buffer

See the example for uartInit
void uartSendByte (uint8_t byte)

Sends a single byte over UART.

Arguments
  • byte: The byte to send
// Send 0xFF over UART
uartSendByte(0xFF);

// Send 'B' over UART (note single quotes)
uartSendByte('B');
void uartRxBufferInit ()

Initialises the RX FIFO buffer.

Arguments
  • None
No example current available.
uint8_t uartRxBufferRead ()

Read one byte out of the RX buffer. This function will return the byte located at the array index of the read pointer, and then increment the read pointer index. If the read pointer exceeds the maximum buffer size, it will roll over to zero.

Arguments
  • None
See the example for uartRxBufferWrite.
void uartRxBufferWrite(uint8_t data)

Write one byte into the RX buffer. This function will write one byte into the array index specified by the write pointer and increment the write index. If the write index exceeds the max buffer size, then it will roll over to zero.

Note: Normally you will not need to call this method yourself. All incoming data is handled by the UART ISR, and any bytes received via UART are automatically inserted in the RX buffer. You simply need to check for new messages at appropriate intervals by testing the return value of uartRxBufferDataPending() or looking at the value of "pcb->rxfifo.len" on the UART control block (which will be non-zero if data is present in the RX buffer).

Arguments
  • uint8_t data: The byte to add to the RX buffer.
#include "core/cpu/cpu.h"
#include "core/uart/uart.h"

int main(void)
{
    cpuInit();
    uartInit(57600);

    // Add 0xFF to the RX buffer
    uartRxBufferWrite(0xFF);

    // Check if the buffer is empty (it shouldn't be!)
    while (uartRxBufferDataPending())
    {
      // Retrieve the first available character in the buffer
      uint8_t c = uartRxBufferRead();
    }

    ...
}
void uartRxBufferClearFIFO ()

Clears the FIFO read and write pointers and sets the length to zero.

Arguments
  • None
No example currently available.
void uartRxBufferDataPending()

Determines whether there is any data in the FIFO queue. If one or more bytes are present in the FIFO, this method will return 1. If the buffer is empty, it will return 0.

Arguments
  • None
See the example for uartRxBufferWrite.

Core/USBHID-ROM

The LPC1343 includes rom-based support for HID (Human Interface Device) and MSCD (Mass Storage Device) USB classes, making them very easy and efficient to implement. A simple HID implementation is provided to show how to enable basic communication between the LPC1343 and a PC or USB-Host device. In these examples, the device is configured to send and receive 1-byte 'reports', and the LED on the LPC1343 Reference Board will be toggled if bit 0 is set to 1 (for example, 0x01), or disabled if it is set to 0 (ex.: 0x00). The LPC1343 will also report the current state of the LED back to the PC using the same bit.

It's worth mentionning that, while the rom-based HID driver is exceptionally convenient in that it takes very little space or effort to implement, it's a bit more limited than a full SW-based USB/HID stack. The main difference is that you are limited to a single 'report', though the number of bytes in the ingoing and outgoing reports can both be individually adjusted. If you require multiple unique reports, you will need to implement a full SW-based USB stack, some examples of which are provided on NXP's website. (One possible compromise solution is to use reports of 2 or more bytes, using the first byte as a 'command ID', of sorts, to determine how the subsequent bytes should be interpretted.)

Memory Restrictions: The rom-based HID drivers use sections 0x10000050 to 0x10000180 of the on-chip RAM, meaning that you will need to configure the linker in your toolchain to avoid this area. Any attempt to use this memory for your own code will almost certainly result in system failure. The project files provided with the LPC1343 Code Base are configure to exclude these chunks of memory from system use, but if you are implementing your own custom project and making use of rom-based HID you will need to make sure the linker is properly configured to avoid this memory range.
void usbHIDInit (void)

Initialises the device for USB HID support and attempts to connect to the host device. By default, the device is configured to send and receive 1-byte reports.

Arguments
  • None
#include "core/cpu/cpu.h"
#include "core/usbhid-rom/usbhid.h"
#include "core/gpio/gpio.h"

int main(void)
{
    cpuInit();

    // Set GPIO2.10 (LED) as output
    gpioSetDir(2, 10, gpioDirection_Output);
    // Disable LED (set high)
    gpioSetValue (2, 10, 1);

    // Initialise and connect USB
    usbHIDInit();

    // The device should enumerate on the PC, and
    // the LED on 2.10 can be enabled by sending 0x01

    while (1)
    {
    }
}
void usbHIDGetInReport (uint8_t src[], uint32_t length)

Sets the HID in report (the report going from the LPC1343 to the USB host).

Arguments
  • src[]: An array of bytes containing the report data
  • length: The length of src

Warning

The signature for this method (uint8_t src[], uint32_t length) should not be modified, and this method should never be called directly. All interrupts and report exchanges are handled by the rom-based drivers. The only thing that should be modified in these methods is the code inside them that either generates or handles the appropriate byte data.

See the example for usbHIDInit
void usbHIDSetOutReport (uint8_t dst[], uint32_t length)

Sets the HID out report (the report coming in from the USB host to the LPC1343).

Arguments
  • dst[]: An array of bytes containing the report data
  • length: The length of src

Warning

The signature for this method (uint8_t dst[], uint32_t length) should not be modified, and this method should never be called directly. All interrupts and report exchanges are handled by the rom-based drivers. The only thing that should be modified in these methods is the code inside them that either generates or handles the appropriate byte data.

See the example for usbHIDInit

Core/WDT

The LPC1343 includes a watchdog timer that can be used to detect when the system has stopped responding. The 'watchdog' is configured to be fed every 'x' ticks on the system clock, and if it isn't fed it will perform one of several actions selected by the user (such as resetting the system, or raising an interrupt). By default, the supplied code will setup the WDT to be fed at a rate of 250kHz (once every 250,000 ticks), and it will simply raise an interrupt (handled by WDT_IRQHandler) if it is not fed within the specified delay.

void wdtInit (void)

Initialises the watchdog timer and sets up the interrupt (reset is not enabled by default).

Arguments
  • None
#include "core/cpu/cpu.h"
#include "core/wdt/wdt.h"

int main(void)
{
    cpuInit();
    wdtInit();

    // Pat the watchdog to start it
    wdtFeed();

    while(1)
    {
        // Keep the watchdog happy by regularly feeding it
        wdtFeed();

        // Any delay here > 250,000 ticks (~3.5mS @ 72MHz)
        // will cause the watchdog to raise an interrupt, which
        // will be handled by WDT_IRQHandler
    }
}

void wdtFeed (void)

Feeds the watchdog to keep it from timing out.

Arguments
  • None

See the example for wdtInit

  • Facebook
  • DZone It!
  • Digg It!
  • StumbleUpon
  • Technorati
  • Del.icio.us
  • NewsVine
  • Reddit
  • Blinklist
  • Furl it!

Comments