Thursday, March 10, 2011

stm32vld

Updated project at

https://github.com/dwelch67/stm32vld/wiki/stm32vld

Learned a few things that are not necessarily in the code. When erasing a page the FLASH_AR register is the address of the page not the page number. For example to erase page four put 0x1000 in this register. Second the flash programming doc mentions writing a single halfword to flash then waiting for the busy bit. So far I have been able to write a whole flash page before waiting on the busy bit. Well not a whole page as the sample program is not that big but the whole program.

If you mess up the flash, for example doing something like an ARM based address (lsbit of zero) for the reset vector. The usb/stlink interface will let you get at the registers in the chip, you can blink the leds for example, but I was not able to load programs and run them. Basically was not able to change the program counter (r15) to a thumb based address, allowing it to return execution to sram, the bad boot from flash put it in a bad state. By removing the BOOT0 jumper/strap on the back of the board, the processor will boot using the factory bootloader. Then either using the stlink interface or using a uart based programmer to talk to the bootloader you can then repair the flash with something usable. The board is not bricked. Then if you desire add a solder blob back on there to boot from flash again. It would have been nice if they had a two pin jumper instead of a no-ohm resistor (or solder bridge).

Once I find out how to perform 16 bit writes using the stlink interface then programming the flash can happen directly and not require this two step of loading a program and having the program write the flash.

Wednesday, March 9, 2011

STM32 Value line discovery


ST now has an eval board everyone can afford. No doubt like the msp430 launchpad ST must be delivering these at a loss. Personally I would rather have a bare bones eval board than a rubber ducky or mousepad with a logo, when it comes to the marketing folks giving away handouts. Perhaps that is whose budget is paying for this.

Anyway, thanks to http://capitanio.org/mlink/index.html there is some work underway to support the usb interface into the stlink side allowing access from linux to the evaulation chip. As with mcapitanio I have a lot more work to do on this (programming the flash or experimenting with other boot modes or loading methods) but for now I went with a trivial solution. Load ram (address 0x20000000) with a simple blink the leds program, while the stm32 was halted changed register 15 to point at the program in ram, then allowed the stm32 to run again and sure enough it blinks the leds. change the program to blink faster or slower, re-run the program and you can see the new program is loaded and running.

Sunday, February 6, 2011

leaflabs maple

Recently received a leaflabs maple r5. Contains an STM32F103RB.

I am using the dfu-util from the openmoko folks.


svn co https://svn.openmoko.org/trunk/src/host/dfu-util/
cd dfu-util
./autogen.sh
./configure
make
make install


When you have a program to load, both after plugging in to the usb connector and after pressing the reset button there is some activity on the blue led (hate blue leds, going to replace it) you run this command when that is going on (otherwise, the usb can disconnect, unless you have code on there keeping it alive).

dfu-util -a1 -d 1EAF:0003 -D filename.bin -R

Simple count based loop blink the led example program:

startup.s:



.word 0x20005000
.word notmain
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang

hang: b .

.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr

.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr

.thumb_func
.globl dummy_fun
dummy_fun:
bx lr

notmain.c



void PUT32 ( unsigned int, unsigned int);
unsigned int GET32 ( unsigned int );

void notmain ( void )
{
unsigned int ra;
unsigned int rb;

ra=GET32(0x40021018);
ra&=(~4);
PUT32(0x40021018,ra);

ra=GET32(0x4002100C);
ra&=~4;
rb=ra|4;
PUT32(0x4002100C,rb);
PUT32(0x4002100C,ra);

ra=GET32(0x40021018);
ra|=4;
PUT32(0x40021018,ra);

ra=GET32(0x40010800);
ra&=(~0x00F00000);
ra|= 0x00100000;
PUT32(0x40010800,ra);

while(1)
{
for(ra=0;ra<1000000;ra++) dummy_fun(ra);
PUT32(0x40010810,0x00000020);
for(ra=0;ra<10000;ra++) dummy_fun(ra);
PUT32(0x40010810,0x00200000);
}
}


Makefile:


# dfu-util -a1 -d 1EAF:0003 -D filename.bin -R

ARMGNU ?= arm-none-eabi
#ARMGNU ?= arm-none-linux-gnueabi

COPSjustthumb = -O2 -mthumb -nostdlib -nostartfiles -ffreestanding
COPS = -O2 -march=armv7-m -mcpu=cortex-m3 -mtune=cortex-m3 -mthumb -nostdlib -nostartfiles -ffreestanding

maple.bin : maple.elf
$(ARMGNU)-objcopy -O binary maple.elf maple.bin

maple.elf: startup.s memmap notmain.c
$(ARMGNU)-gcc -O2 -march=armv7-m -mcpu=cortex-m3 -mtune=cortex-m3 -mthumb -nostdlib -nostartfiles -ffreestanding startup.s notmain.c -T memmap -o maple.elf
$(ARMGNU)-objdump -D maple.elf > maple.list

clean:
rm -f *.elf
rm -f *.bin
rm -f *.list


memmap (linker script):

MEMORY {
flash (rwx) : ORIGIN = 0x08005000, LENGTH = 256k
}

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


The length is probably wrong on that linker script. Just a cut and paste. No libraries or includes are used so the code sourcery lite toolchains or a roll your own will work just fine.

The program enables clocks to the gpio, resets the gpio interface just for good measure, sets PA5 as a push-pull output. dummy_fun() is there simply to prevent the optimizer from trying to optimize out the delay count loop.