adding an example using the watchdog timer

This commit is contained in:
David Welch
2012-06-16 01:29:20 -04:00
parent ec4a2220f8
commit 7569f21dcf
9 changed files with 362 additions and 0 deletions

46
blinker06/Makefile Normal file
View File

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

24
blinker06/README Normal file
View File

@@ -0,0 +1,24 @@
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.
So when surfing through the linux source for the raspberry pi I found
some watchdog timer registers that dont appear to be in the datasheet.
So I played with the registers a bit and it appears that from reset
and/or using the settings as configured in this code, the watchdog
timer is a divide by 4000 of the system timer, so 250,000,000/4000 =
62500 Hz.
Based on assumptions from the linux code the biggest timer is 0xFFFFF
which is 16.8 seconds. If you do not reprogram the timer and let it
run out, then it resets the chip, down to re-reading the sd card and
bringing the ARM up using kernel.img.
This example simply uses the watchdog timer to time the led state
changes. Because it reprograms the watchdog timer with a new time
the timer does not timeout and reset the chip. Comment out or remove
the break in the loop and it will timeout and reset the chip.

32
blinker06/blinker06.c Normal file
View File

@@ -0,0 +1,32 @@
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
#include "periph.h"
#include "wdog.h"
//------------------------------------------------------------------------
int notmain ( void )
{
unsigned int ra;
unsigned int rb;
init_led();
while(1)
{
wdog_start(0xFFFFF);
while(1)
{
ra=wdog_get_remaining();
//if(ra<0x67697) //10 seconds
if(ra<0xC2F6F) //4 seconds
{
toggle_led();
break;
}
}
}
return(0);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

12
blinker06/memmap Normal file
View File

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

143
blinker06/periph.c Normal file
View File

@@ -0,0 +1,143 @@
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
extern void PUT32 ( unsigned int, unsigned int );
extern unsigned int GET32 ( unsigned int );
extern void dummy ( unsigned int );
#define GPFSEL1 0x20200004
#define GPSET0 0x2020001C
#define GPCLR0 0x20200028
#define GPPUD 0x20200094
#define GPPUDCLK0 0x20200098
#define AUX_ENABLES 0x20215004
#define AUX_MU_IO_REG 0x20215040
#define AUX_MU_IER_REG 0x20215044
#define AUX_MU_IIR_REG 0x20215048
#define AUX_MU_LCR_REG 0x2021504C
#define AUX_MU_MCR_REG 0x20215050
#define AUX_MU_LSR_REG 0x20215054
#define AUX_MU_MSR_REG 0x20215058
#define AUX_MU_SCRATCH 0x2021505C
#define AUX_MU_CNTL_REG 0x20215060
#define AUX_MU_STAT_REG 0x20215064
#define AUX_MU_BAUD_REG 0x20215068
#define ARM_TIMER_LOD 0x2000B400
#define ARM_TIMER_VAL 0x2000B404
#define ARM_TIMER_CTL 0x2000B408
#define ARM_TIMER_DIV 0x2000B41C
#define ARM_TIMER_CNT 0x2000B420
//GPIO14 TXD0 and TXD1
//GPIO15 RXD0 and RXD1
//alt function 5 for uart1
//alt function 0 for uart0
//((250,000,000/115200)/8)-1 = 270
//------------------------------------------------------------------------
void uart_putc ( unsigned int c )
{
while(1)
{
if(GET32(AUX_MU_LSR_REG)&0x20) break;
}
PUT32(AUX_MU_IO_REG,c);
}
//------------------------------------------------------------------------
void hexstrings ( unsigned int d )
{
//unsigned int ra;
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_putc(rc);
if(rb==0) break;
}
uart_putc(0x20);
}
//------------------------------------------------------------------------
void hexstring ( unsigned int d )
{
hexstrings(d);
uart_putc(0x0D);
uart_putc(0x0A);
}
//------------------------------------------------------------------------
int uart_init ( void )
{
unsigned int ra;
PUT32(AUX_ENABLES,1);
PUT32(AUX_MU_IER_REG,0);
PUT32(AUX_MU_CNTL_REG,0);
PUT32(AUX_MU_LCR_REG,3);
PUT32(AUX_MU_MCR_REG,0);
PUT32(AUX_MU_IER_REG,0);
PUT32(AUX_MU_IIR_REG,0xC6);
PUT32(AUX_MU_BAUD_REG,270);
ra=GET32(GPFSEL1);
ra&=~(7<<12); //gpio14
ra|=2<<12; //alt5
ra&=~(7<<15); //gpio15
ra|=2<<15; //alt5
PUT32(GPFSEL1,ra);
PUT32(GPPUD,0);
for(ra=0;ra<150;ra++) dummy(ra);
PUT32(GPPUDCLK0,(1<<14)|(1<<15));
for(ra=0;ra<150;ra++) dummy(ra);
PUT32(GPPUDCLK0,0);
PUT32(AUX_MU_CNTL_REG,3);
return(0);
}
//-------------------------------------------------------------------------
void init_timer ( void )
{
PUT32(ARM_TIMER_CTL,0x00000000);
PUT32(ARM_TIMER_CTL,0x00000200);
}
//-------------------------------------------------------------------------
unsigned int timer_tick ( void )
{
return(GET32(ARM_TIMER_CNT));
}
//-------------------------------------------------------------------------
unsigned int ledstate;
//-------------------------------------------------------------------------
void toggle_led ( void )
{
ledstate++;
if(ledstate&1)
{
PUT32(GPSET0,1<<16);
}
else
{
PUT32(GPCLR0,1<<16);
}
}
//-------------------------------------------------------------------------
void init_led ( void )
{
unsigned int ra;
ra=GET32(GPFSEL1);
ra&=~(7<<18);
ra|=1<<18;
PUT32(GPFSEL1,ra);
ledstate=0;
toggle_led;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

13
blinker06/periph.h Normal file
View File

@@ -0,0 +1,13 @@
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void uart_putc ( unsigned int );
void hexstrings ( unsigned int );
void hexstring ( unsigned int );
int uart_init ( void );
void init_timer ( void );
unsigned int timer_tick ( void );
void toggle_led ( void );
void init_led ( void );
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

23
blinker06/vectors.s Normal file
View File

@@ -0,0 +1,23 @@
.globl _start
_start:
b reset
reset:
mov sp,#0x8000
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

61
blinker06/wdog.c Normal file
View File

@@ -0,0 +1,61 @@
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// this is derived from:
/*
* Broadcom BCM2708 watchdog driver.
*
* (c) Copyright 2010 Broadcom Europe Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* BCM2708 watchdog driver. Loosely based on wdt driver.
*/
//------------------------------------------------------------------------
extern void PUT32 ( unsigned int, unsigned int );
extern unsigned int GET32 ( unsigned int );
//------------------------------------------------------------------------
#define BCM2708_PERI_BASE 0x20000000
#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */
#define PM_RSTC (PM_BASE+0x1c)
#define PM_WDOG (PM_BASE+0x24)
#define PM_WDOG_RESET 0000000000
#define PM_PASSWORD 0x5a000000
#define PM_WDOG_TIME_SET 0x000fffff
#define PM_RSTC_WRCFG_CLR 0xffffffcf
#define PM_RSTC_WRCFG_SET 0x00000030
#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
#define PM_RSTC_RESET 0x00000102
//------------------------------------------------------------------------
void wdog_start ( unsigned int timeout )
{
unsigned int pm_rstc,pm_wdog;
/* Setup watchdog for reset */
pm_rstc = GET32(PM_RSTC);
pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0)
pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
PUT32(PM_WDOG,pm_wdog);
PUT32(PM_RSTC,pm_rstc);
}
//------------------------------------------------------------------------
void wdog_stop ( void )
{
PUT32(PM_RSTC,PM_PASSWORD | PM_RSTC_RESET);
}
//------------------------------------------------------------------------
unsigned int wdog_get_remaining ( void )
{
return(GET32(PM_WDOG)& PM_WDOG_TIME_SET);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

8
blinker06/wdog.h Normal file
View File

@@ -0,0 +1,8 @@
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void wdog_start ( unsigned int );
void wdog_stop ( void );
unsigned int wdog_get_remaining ( void );
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------