Friday, August 13, 2010

NXP MBED aint so bad after all

I have been anti lpc lately. Was discouraging among other things the http://mbed.org development board. The two things that probably set me off and put the thing in almost-permanent storage is that the web based compiler tools and likely on top of that a whole sandbox/rtos. Dont remember didnt try it. Worse than that is the blue leds, near instant migraine headache when those things turn on, even, esp, out of the corner of my eye.

Saw it sitting there all sad in the pile of rejects and decided to give it one more shot, the web side says linux maybe it didnt before. Well it aint so bad after all (well the leds are killing me still, but you absolutely do not need to use their sandbox or compiler).

The copy the bin file to a flash drive thing is interesting and cool, much easier than the armmite pro which is one of the few lpc boards I do like. The extra chips must manage the flash drive thing because I was worried the main LPC1768 did it but got to thinking that if a program written in the sandbox crashed the flash drive would not mount and you would be bricked, so they had to have managed it separately. And did.

I looked at their Hello World binary and confirmed there was no encryption magic or other such thing to force you to use their sandbox, and decided to go for it. If you go to mbed.org and get the schematic (it may take you a while surfing but it is there). You will find that P1.18, 20, 21, and 23 are connected to the four leds along the bottom edge. The fast I/O ports are not what I was expecting, they are 8 bit registers so you have to not assume a 32 bit register manages the whole port as I did. Once I got past that it was easy to make a night rider like led blinker program:


/*blinker1.s*/.cpu cortex-m3
.thumb

.word 0x10008000 /* stack top address */
.word _start /* 1 Reset */
.word hang /* 2 NMI */
.word hang /* 3 HardFault */
.word hang /* 4 MemManage */
.word hang /* 5 BusFault */
.word hang /* 6 UsageFault */
.word hang /* 7 RESERVED */
.word hang /* 8 RESERVED */
.word hang /* 9 RESERVED*/
.word hang /* 10 RESERVED */
.word hang /* 11 SVCall */
.word hang /* 12 Debug Monitor */
.word hang /* 13 RESERVED */
.word hang /* 14 PendSV */
.word hang /* 15 SysTick */
.word hang /* 16 External Interrupt(0) */
.word hang /* 17 External Interrupt(1) */
.word hang /* 18 External Interrupt(2) */
.word hang /* 19 ... */

hang: b .

.thumb_func
dowait:
ldr r7,=0x10000
dowaitloop:
sub r7,#1
bne dowaitloop
bx lr

.thumb_func
.globl _start
_start:
ldr r0,=0x2009C022
ldrb r1,[r0]
mov r2,#0xB4
orr r1,r2
strb r1,[r0]

ldr r0,=0x2009C03A
ldr r1,=0x2009C03E
ldr r2,=0x80
ldr r3,=0x20
ldr r4,=0x10
ldr r5,=0x04

mainloop:
strb r2,[r0]
strb r3,[r1]
strb r4,[r1]
strb r5,[r1]
bl dowait
strb r2,[r1]
strb r3,[r0]
strb r4,[r1]
strb r5,[r1]
bl dowait
strb r2,[r1]
strb r3,[r1]
strb r4,[r0]
strb r5,[r1]
bl dowait
strb r2,[r1]
strb r3,[r1]
strb r4,[r1]
strb r5,[r0]
bl dowait
strb r2,[r1]
strb r3,[r1]
strb r4,[r0]
strb r5,[r1]
bl dowait
strb r2,[r1]
strb r3,[r0]
strb r4,[r1]
strb r5,[r1]
bl dowait
b mainloop

.end



/* memmap */
MEMORY
{
rom(RX) : ORIGIN = 0x00000000, LENGTH = 0x40000
ram(WAIL) : ORIGIN = 0x10000000, LENGTH = 64K
}

SECTIONS
{
.text : { *(.text*) } > rom
}




You may want to look at my stellaris blinker at lmistuff.blogspot.com to understand more about the cortex-m3 and thumb/thumb2 only mode. For starters the exception table is different than other ARM cores. Other arm cores the table contains executable arm instructions which are usually a relative branch or a load pc with something. The cortex-m3 does not execute ARM instructions, at all, it is thumb/thumb2 only. So the exception table starts with the value to pre-load the stack pointer with, the second entry is the address in memory for reset, and so on. So other than the stack pointer thing it is similar to an interrupt vector table on other non-ARM/traditional processors. From the datasheet and/or users manual for the LPC1768 wee see that there is sram up to 0x10007FFF so that is why the stack pointer entry is 0x10008000.

My makefile looks like this:


#ARMGNU=arm-thumb-elf
ARMGNU=arm-none-linux-gnueabi

all : blinker1.bin


blinker1.bin : blinker1.s memmap
$(ARMGNU)-as blinker1.s -o blinker1.o
$(ARMGNU)-ld -o blinker1.elf blinker1.o -T memmap
$(ARMGNU)-objdump -D blinker1.elf > blinker1.list
$(ARMGNU)-objcopy blinker1.elf blinker1.bin -O binary

clean:
rm *.bin
rm *.o
rm *.elf
rm *.list


I am using the codesourcery lite toolchain at the moment. As with most of my programs you dont need a C or gcc library so the linux tool is not doing any linuxy stuff it is just a compiler I had laying around. Actually in this case it is an all assembler program so it is only binutils that is required and if you look at my other posts it is fairly simple to build binutils as a cross compiler(/assembler).

Plug the mbed in, it will mount as a flash drive, copy blinker1.bin to the root of that drive, perhaps remove other .bin files that are there (not sure how that works yet, is it alphabetical?), and press the button in the middle of the board. And your leds will blink in a pattern.