adding blinker04, this uses the ARM timer

This commit is contained in:
David Welch
2012-05-28 18:23:24 -04:00
parent 4792bb0a31
commit 36fd5ec1f2
5 changed files with 153 additions and 0 deletions

31
blinker04/Makefile Normal file
View File

@@ -0,0 +1,31 @@
ARMGNU ?= arm-none-eabi
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding
all : blinker04.hex blinker04.bin
clean :
rm -f *.o
rm -f *.bin
rm -f *.hex
rm -f *.elf
rm -f *.list
rm -f *.img
novectors.o : novectors.s
$(ARMGNU)-as novectors.s -o novectors.o
blinker04.o : blinker04.c
$(ARMGNU)-gcc $(COPS) -c blinker04.c -o blinker04.o
blinker04.elf : memmap novectors.o blinker04.o
$(ARMGNU)-ld novectors.o blinker04.o -T memmap -o blinker04.elf
$(ARMGNU)-objdump -D blinker04.elf > blinker04.list
blinker04.bin : blinker04.elf
$(ARMGNU)-objcopy blinker04.elf -O binary blinker04.bin
blinker04.hex : blinker04.elf
$(ARMGNU)-objcopy blinker04.elf -O ihex blinker04.hex

32
blinker04/README Normal file
View File

@@ -0,0 +1,32 @@
See the top level README for information on where to find the
schematic and programmers reference manual for the ARM processor
on the raspberry pi. Also find information on how to load and run
these programs.
This example uses the ARM timer, not the free running ARM timer which
counts up (see blinker03) but the other timer that counts down.
A few more typos in the datasheet. It is an SP804 not AP804 (page 196).
Page 197, bit 1 32 bit counter not 23 bit counter. Page 198 neither
the raw nor masked IRQ registers are at address 0x40C.
So if you want to poll an arbitrary time with a free running timer you
take a reference count, and then take a sample, wait for the difference
between the sample and reference count. You have to know if it is an
up or down counter. You can turn this timer into a free running timer
by setting the load registers to all ones. What you can also do with
this kind of timer that you cannot with a free runing timer is set the
load registers to some number of ticks (minus 1) and it will roll over
the counter at that rate. Often these kinds of timers have an interrupt
as does this one. And you can poll the interrupt bit without havingt to
actually configure an interrupt. This example sets the prescaler to
divide by 250. The clock as running here is 250Mhz, so this takes it
down to 1Mhz, 1000000 clocks per second. Now if we set the load registers
to 4 million counts (minus 1) then every 4 million counts at 1 million
per second is 4 seconds. Every 4 seconds the timer interrupt will fire.
Which you can read in the raw irq (not masked) register. Once it is
set you have to write anything to the clear interrupt register. If you
were to set up an interrupt service routine, you would clear that
interrupt in the interrupt handler.

55
blinker04/blinker04.c Normal file
View File

@@ -0,0 +1,55 @@
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
extern void PUT32 ( unsigned int, unsigned int );
extern unsigned int GET32 ( unsigned int );
extern void dummy ( unsigned int );
#define ARM_TIMER_LOD 0x2000B400
#define ARM_TIMER_VAL 0x2000B404
#define ARM_TIMER_CTL 0x2000B408
#define ARM_TIMER_CLI 0x2000B40C
#define ARM_TIMER_RIS 0x2000B410
#define ARM_TIMER_MIS 0x2000B414
#define ARM_TIMER_RLD 0x2000B418
#define ARM_TIMER_DIV 0x2000B41C
#define ARM_TIMER_CNT 0x2000B420
#define SYSTIMERCLO 0x20003004
#define GPFSEL1 0x20200004
#define GPSET0 0x2020001C
#define GPCLR0 0x20200028
#define TIMEOUT 4000000
//-------------------------------------------------------------------------
int notmain ( void )
{
unsigned int ra;
ra=GET32(GPFSEL1);
ra&=~(7<<18);
ra|=1<<18;
PUT32(GPFSEL1,ra);
PUT32(ARM_TIMER_CTL,0x003E0000);
PUT32(ARM_TIMER_LOD,4000000-1);
PUT32(ARM_TIMER_RLD,4000000-1);
PUT32(ARM_TIMER_DIV,0x000000F9);
PUT32(ARM_TIMER_CLI,0);
PUT32(ARM_TIMER_CTL,0x003E0082);
while(1)
{
PUT32(GPSET0,1<<16);
while(1) if(GET32(ARM_TIMER_RIS)) break;
PUT32(ARM_TIMER_CLI,0);
PUT32(GPCLR0,1<<16);
while(1) if(GET32(ARM_TIMER_RIS)) break;
PUT32(ARM_TIMER_CLI,0);
}
return(0);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

12
blinker04/memmap Normal file
View File

@@ -0,0 +1,12 @@
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.bss*) } > ram
}

23
blinker04/novectors.s Normal file
View File

@@ -0,0 +1,23 @@
.globl _start
_start:
b reset
reset:
mov sp,#0x1000
bl notmain
hang: b hang
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.globl dummy
dummy:
bx lr