adding an example using the watchdog timer
This commit is contained in:
46
blinker06/Makefile
Normal file
46
blinker06/Makefile
Normal 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
24
blinker06/README
Normal 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
32
blinker06/blinker06.c
Normal 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
12
blinker06/memmap
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram : ORIGIN = 0x8000, LENGTH = 0x1000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text*) } > ram
|
||||
.bss : { *(.bss*) } > ram
|
||||
}
|
||||
|
||||
143
blinker06/periph.c
Normal file
143
blinker06/periph.c
Normal 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
13
blinker06/periph.h
Normal 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
23
blinker06/vectors.s
Normal 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
61
blinker06/wdog.c
Normal 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
8
blinker06/wdog.h
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
void wdog_start ( unsigned int );
|
||||
void wdog_stop ( void );
|
||||
unsigned int wdog_get_remaining ( void );
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user