Example of a Program Written in C and running on a ARM7


The following program (main.c) tests the USB serial interface and the LED of the Olimex DEV-00268 board with the Philips LPC2294 chip.

// Author Richard St-Denis, Universite de Sherbrooke, 2013.
#include "uart.h"

// Addresses of SCB (System Control Block) registers
#define SCB_MEMMAP *((volatile unsigned int*)0xE01FC040)
// interrupt vectors are not re-mapped and reside in flash
#define MEMMAP_USER_FLASH_MODE (1 << 0)
#define SCB_PLLCON *((volatile unsigned int*)0xE01FC080)
#define PLLE 0         // enable PLL (Phase Locked Loop) 
#define PLLC 1         // connect PLL (Phase Locked Loop)
#define SCB_PLLCFG *((volatile unsigned int*)0xE01FC084)
#define PLL_M 4        // multiplier
#define MSEL (PLL_M-1) // multiplier - 1
#define PSEL0 5
#define PSEL1 6
#define SCB_PLLSTAT *((volatile unsigned int*)0xE01FC088)
#define PLOCK 10       // PLOCK bit
#define SCB_PLLFEED *((volatile unsigned int*)0xE01FC08C)
#define PLL_FEED1 0xAA // feed sequence
#define PLL_FEED2 0x55
#define SCB_VPBDIV *((volatile unsigned int*)0xE01FC100)
// VPB should run at full speed
#define VPBDIV_VAL 1

// Addresses of MAM (Memory Accelerator Module) registers
#define MAM_MAMCR *((volatile unsigned int*)0xE01FC000)
#define MAM_MODE 2     // MAM fully enabled
#define MAM_MAMTIM *((volatile unsigned int*)0xE01FC004)
#define MAM_FETCH 3    // 3 cclks are proposed as fetch timing

void systemInit(void)
{
 // Enable and connect the PLL (Phase Locked Loop)
 // 1. Set multiplier and divider
 SCB_PLLCFG = MSEL | (1 << PSEL1) | (0 << PSEL0);
 // 2. Enable PLL
 SCB_PLLCON = (1 << PLLE);
 // 3. Feed sequence
 SCB_PLLFEED = PLL_FEED1;
 SCB_PLLFEED = PLL_FEED2;
 // 4. Wait for PLL lock (PLOCK bit is set if locked)
 while (!(SCB_PLLSTAT & (1 << PLOCK)));
 // 5. Connect (and enable) PLL
 SCB_PLLCON = (1 << PLLE) | (1 << PLLC);
 // 6. Feed sequence
 SCB_PLLFEED = PLL_FEED1;
 SCB_PLLFEED = PLL_FEED2;
	
 // Setup and enable the MAM (Memory Accelerator Module)
 // 1. Start change by turning of the MAM (redundant)
 MAM_MAMCR = 0;	
 // 2. Set MAM-Fetch cycle to 3 cclks as recommended for > 40MHz
 MAM_MAMTIM = MAM_FETCH;
 // 3. Enable MAM 
 MAM_MAMCR = MAM_MODE;

 // --- set VPB speed ---
 SCB_VPBDIV = VPBDIV_VAL;
	
 SCB_MEMMAP = MEMMAP_USER_FLASH_MODE; // according to the Makefile
}
// Addresses of PCB (Pin Connect Block) registers
#define PCB_PINSEL1 *((volatile unsigned int*)0xE002C004)
// Addresses of GPIO (General Purpose I/O) registers
#define GPIO_IOSET *((volatile unsigned int*)0xE0028004)
#define GPIO_IODIR *((volatile unsigned int*)0xE0028008)
#define GPIO_IOCLR *((volatile unsigned int*)0xE002800C)
// GPIO pin associated to the LED
#define LEDPIN 30

void gpioInit(void)
{
 GPIO_IODIR |= (1 << LEDPIN);	// define LED-Pin as output
 PCB_PINSEL1 = 0x0;
 GPIO_IOSET  = (1 << LEDPIN);	// set Bit = LED off (active low)
}

void ledToggle(void)
{
 static unsigned char state=0;

 state = !state;
 if (state)
     GPIO_IOCLR = (1 << LEDPIN);  // set Bit = LED on
 else 
     GPIO_IOSET = (1 << LEDPIN);  // set Bit = LED off
}

// Line Control Register bit definitions
#define ULCR_CHAR_8 (3 << 0)      // 8-bit character length
#define ULCR_STOP_1 (0 << 2)      // 1 stop bit
#define ULCR_PAR_NO (0 << 3)      // no parity

// Definition of a typical UART 'mode' setting
#define UART_8N1 (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_NO + ULCR_STOP_1)

// FIFO Control Register bit definitions
#define UFCR_FIFO_ENABLE (1 << 0)  // FIFO enable
#define UFCR_FIFO_TRIG8  (2 << 6)  // Rx trigger, 8 characters in FIFO

// Definition of a typical UART 'fmode' setting
#define UART_FIFO_8 (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG8)

#define BAUD 9600
#define FOSC 14745000
// Baud-Rate is calculated based on pclk (VPB-clock)
// the devisor must be 16 times the desired baudrate
#define UART_BAUD(baud) (uint16_t)(((FOSC*PLL_M/VPBDIV_VAL) / ((baud) * 16.0)) + 0.5)

int main(void)
{
 int ch;

 systemInit();
 gpioInit();
	
 uart0Init(UART_BAUD(BAUD), UART_8N1, UART_FIFO_8);

 uart0Puts("\r\nTesting the USB serial interface of the Olimex DEV-00268 board\r\n");
 uart0Puts("and testing the LED...\r\n");
	
 while(1) {
   if ((ch = uart0Getch()) >= 0) {
       uart0Putch(ch);
       uart0Puts("\r\n");
       ledToggle();
   }
 }	
 return 0;
}

This is the contents of uart.h file.

/******************************************************************************
 * Based on software from:
 * Copyright 2004, R O SoftWare
 * No guarantees, warrantees, or promises, implied or otherwise.
 * May be used for hobby or commercial purposes provided copyright
 * notice remains intact.
 * 
 * Reduced to see what has to be done for minimum UART-support
 * by Richard St-Denis, Universite de Sherbrooke, 2013.
 *****************************************************************************/
#ifndef INC_UART_H
#define INC_UART_H

#include "inttypes.h"

void uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode);
int uart0Getch(void);
int uart0Putch(int ch);
const char *uart0Puts(const char *string);

#endif


This is the contents of uart.c file.

/******************************************************************************
 * This module provides interface routines to the LPC ARM UARTs.
 * Copyright 2004, R O SoftWare
 * No guarantees, warrantees, or promises, implied or otherwise.
 * May be used for hobby or commercial purposes provided copyright
 * notice remains intact.
 *
 * Reduced to see what has to be done for minimum UART-support
 * by Richard St-Denis, Universite de Sherbrooke, 2013.
 *****************************************************************************/

#include "uart.h"

// Addresses of UART0 registers
#define UART0_RBR *((volatile unsigned int*)0xE000C000)
#define UART0_THR *((volatile unsigned int*)0xE000C000)
#define UART0_IER *((volatile unsigned int*)0xE000C004)
#define UART0_IIR *((volatile unsigned int*)0xE000C008)
#define UART0_FCR *((volatile unsigned int*)0xE000C008)
#define UART0_LCR *((volatile unsigned int*)0xE000C00C)
#define ULCR_DLAB_ENABLE (1 << 7)  // Enable Divisor Latch Access
#define UART0_LSR *((volatile unsigned int*)0xE000C014)
#define ULSR_RDR  (1 << 0)         // Receive Data Ready
#define ULSR_THRE (1 << 5)         // Transmit Holding Register Empty
#define UART0_DLL *((volatile unsigned int*)0xE000C000)
#define UART0_DLM *((volatile unsigned int*)0xE000C004)

// Addresses of PCB (Pin Connect Block) registers
#define PCB_PINSEL0 *((volatile unsigned int*)0xE002C000)

#define PINSEL_BITPIN0 0           // TX-Pin for Pin 0.0
#define PINSEL_BITPIN1 2           // RX-Pin for Pin 0.1
// PINSEL0 has to be set to "UART-Function" = Function "01"
#define PINSEL_FIRST_ALT_FUNC 1
// Values of bits 0-3 in PINSEL to activate UART0
#define UART0_PINSEL ((PINSEL_FIRST_ALT_FUNC << PINSEL_BITPIN0)|(PINSEL_FIRST_ALT_FUNC << PINSEL_BITPIN1))
#define UART0_PINMASK (0x0000000F) // PINSEL0 Mask for UART0

void uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode)
{
 // Setup Pin Function Select Register (Pin Connect Block) 
 // Make sure old values of Bits 0-4 are masked out and
 // Set them according to UART0-Pin-Selection
 PCB_PINSEL0 = (PCB_PINSEL0 & ~UART0_PINMASK) | UART0_PINSEL;

 UART0_IER = 0x00;   // clear Interrupt Enable Register
 UART0_IIR = 0x00;   // clear Interrupt Identification Register
 UART0_LSR = 0x00;   // clear Line Status Register

 // Set the baud rate - DLAB must be set to access DLL/DLM
 UART0_LCR = (ULCR_DLAB_ENABLE);    // set divisor latches (DLAB)
 UART0_DLL = (uint8_t)baud;         // set for baud low byte
 UART0_DLM = (uint8_t)(baud >> 8);  // set for baud high byte

 // Setup Line Control Register (Parity, Stop bit, Word length)
 UART0_LCR = (mode & ~(ULCR_DLAB_ENABLE));   // and clear DLAB 
 // Setup FIFO Control Register (FIFO-Enabled + Rx Trigger) 
 UART0_FCR = fmode;
}

int uart0Getch(void)
{                            // get a character
 if (UART0_LSR & ULSR_RDR)   // check if a character is available
     return UART0_RBR;       // return the character
 return -1;
}

int uart0Putch(int ch)
{                            // put a character
 while (!(UART0_LSR & ULSR_THRE))
   continue;                 // wait for an empty buffer
 UART0_THR = (uint8_t)ch;    // put the character to the Transmit Holding Register
 return (uint8_t)ch;         // return char
}

const char *uart0Puts(const char *string)
{                            // put a string
 char ch;

 while ((ch = *string)) {
   if (uart0Putch(ch)<0) break;
       string++;
 }
 return string;
}

Installation of the USB-Serial driver under Windows Server 2003

  1. Plug the Olimex DEV-00268 board into your computer using the USB cable
  2. Windows Server 2003 should automatically search the driver online and install it on your computer
  3. Determine the port of the USB-Serial device
    • Control PanelSystem submenu → Hardware tab → Device Manager button → Ports (COM & LPT) entry
    • The port should be com3 or com4

Modification of Makefile

  1. It is assumed that a project already exists and it includes the files main.c, uart.h, uart.c and Makefile
  2. Modify the Makefile such that line 149 indicates the appropriate port (COMx) and line 150 indicates the desired baud rate (9600)

Compilation and uploading the code on the board in the Programmers Notepad 2 development environment

  1. Compile the program main.c
    • Menu barTools menu → Make All submenu
    • Be sure that the message is displayed
  2. Upload the program to the Olimex DEV-00268 board
    • Set the dip switch 1 to ICSP (the other dip switches must be set to ON)
    • Push the reset button
    • Menu barTools menu → Make Program submenu
    • Be sure that the message is displayed

Execution of the program under the ARM using the virtual terminal Tera Term

  1. Start Tera Term and in the Tera Term New Connection dialog box
    • Serial button → Port subdialog → COMx
    • Menu barSetup menu → Serial port... submenu → Data 8 bits, Parity none, Stop 1 bit
  2. Lauch the execution of the program
    • Set the dip switch 1 to RUN (the other dip switches must be set to ON)
    • Push the reset button