LPC Newb - Barebones Startup Code Help

I’m a complete ARM newb/AVR convert, and my LPC2387 is killing me!

I’m just trying to write the simplest possible program (w/ all my own code) as a starting point, but haven’t been able to get that to work yet.

I’m using the WinARM GNU GCC toolchain, and Flash Magic for loading my program over serial to the bootloader.

I basically just have the startup code in assembly, and a single-pin toggling main function in C (but the LED ain’t flashing…).

Can anybody guess where I’m going wrong here? TIA!! :slight_smile:

LPC2387.S

.text
.arm
.extern main
.global _start
_start:
//=====================================================
	B INIT  // Reset
	B LOOP  // Undefined Instruction
	B LOOP  // Prefetch Abort
	B LOOP  // Data Abort
	NOP     // Bootloader Checksum
	B LOOP  // Interrupt Request
	B LOOP  // Fast Interrupt Request
//====================================================
INIT:
	LDR R3,=BASEADDR

	// Disconnect PLL
	LDR R0, =0
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

	// Set Clock Source to Main Oscillator
	LDR R0, =1
	STR R0, [R3, #CLKSRCSEL]

	// Wait for Main Oscillator to Settle
OSC_LOOP:
	LDR R0, =0x1A0
	ANDS R0, R0, #0x40
	BEQ OSC_LOOP

	// Switch from Internal Clock to Main Oscillator
	LDR R0, =0x1
	STR R0, [R3, #CLKSRCSEL]

	// Setup PLL Scalars
	LDR R0, =0x001000BF   //((16<<16) | 191) == 0x001000BF >> (12*2*192)/16 = 288 >> /4 = 72MHz
	STR R0, [R3, #PLLCFG]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

	// Enable PLL
	LDR R0, =1
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

	// Set CPU Clock Divider (to 4)
	LDR R0, =0x3
	STR R0, [R3, #CCLKCFG]

	// wait for PLL to stabilize
	LDR R0, =0x4000000
PLL_LOOP:
	LDR R1, [R3, #PLLSTAT]
	ANDS R1, R0
	BEQ PLL_LOOP

	// Connect PLL to CPU
	LDR R0, =0x3
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

	// Stack Pointer */
	LDR SP, =0x40010000
	
	// Main
	BL main

LOOP:
	B LOOP

main.c

#include "LPC23xx.h"

int main(void)
{
	int i; //attempting to toggle P0.16 here
	IODIR0   = 0x00010000;
	PINSEL1 |= 0x00000003;
	while(1)
	{
		IOCLR1 = 0x00010000;
		for(i=0; i<6000000; i++) ;
		IOSET1 = 0x00010000;
		for(i=0; i<6000000; i++) ;
	};
}

Okay, so I’ve got it narrowed down, but still not quite working.

My LED toggling code works fine anywhere in the code up to when I switch the Clock Source to the Main (external) Oscillator, then the whole thing seems to halt…

I’m pretty sure I’m following the PLL Setup Sequence from the User Manual…

  1. Disconnect PLL

  2. Disable PLL

  3. Change CPU Clock Divider for non-PLL operation

  4. Change Clock Source to Main/External

  5. Write Multiplier & Divider to PLLCFG

  6. Enable PLL

  7. Change CPU Clock Divider for PLL operation

  8. Wait for PLL Lock

  9. Connect PLL

but, nothing seems to work as soon as I do #4 (write to CCLKSEL register).

Here’s my updated clock setup code:

LDR R3,=BASEADDR

	// Disconnect PLL
	LDR R0, =1
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]
	
	// Disable PLL
	LDR R0, =0
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]
	
	// Set CPU Clock Divider (to 1)
	LDR R0, =0x0
	STR R0, [R3, #CCLKCFG]
	
	//Furthest from start that GPIO Pin Output will work..

	// Set Clock Source to Main Oscillator
	LDR R0, =0x1
	STR R0, [R3, #CLKSRCSEL]

	// Setup PLL Scalars
	LDR R0, =0x001000BF   //((16<<16) | 191) == 0x001000BF >> (12*2*192)/16 = 288 /4 = 72MHz
	STR R0, [R3, #PLLCFG]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

	// Enable PLL
	LDR R0, =1
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

	// Set CPU Clock Divider (to 4)
	LDR R0, =0x3
	STR R0, [R3, #CCLKCFG]

	// wait for PLL to stabilize
PLL_LOOP:
	LDR R0, =0x2000000
	LDR R1, [R3, #PLLSTAT]
	ANDS R1, R0
	BEQ PLL_LOOP

	// Connect PLL to CPU
	LDR R0, =0x3
	STR R0, [R3, #PLLCON]
	LDR R0, =0xAA
	LDR R1, =0x55
	STR R0, [R3, #PLLFEED]
	STR R1, [R3, #PLLFEED]

Finally got it working!! :slight_smile:

I had completely overlooked the OSCEN (main oscillator enable) bit in the SCS register.

You could use IAR’s free compiler, limited to 32KB of code. It has a variety of assembly/C startup programs.