The unified diff between revisions [8760ae92..] and [961b04dd..] is displayed below. It can also be downloaded as a raw diff.
# # old_revision [8760ae9232295422550b79f09e55122390704b3c] # new_revision [961b04ddb07ba2b5dd6bccfa66a03e442e40d8f0] # # add_file "interrupt.c" # content [cd7c20769cf360122ade5179a795a26b7f28f260] # # add_file "interrupt.h" # content [faeb61e4d25cc1baced72430fd4ff30c169ea721] # # add_file "uart.c" # content [b336e227dc442fef728c0a695671328c7a265dd1] # # add_file "uart.h" # content [2d08795e26e7e976bded494c773936c5f91d1b69] # # patch "Makefile" # from [de7747e757f0f60e45c426582c5736214e14d050] # to [b5d08d5d0ac834ea39ee009f56ef0e3780848f88] # # patch "crt0.s" # from [adfe53d34fb8bcfcb9ecc9f2824f484661f0ec94] # to [5b6b789fc104e92e95e61047448c05cbcfb0e3db] # # patch "main.c" # from [ef5435dd23ece2876b0d557328e6c83a7ee04ab6] # to [f3f04a92cb8f9ba8fdecd0b2fd95773011c1e076] # # patch "timer.c" # from [cd7a8d69e6c6dcdc33683f9f6dfcc98c62d77b4d] # to [bbb624ceb301647f8ffb240074c02ed3c3200135] # # patch "timer.h" # from [95b887ab46f9dbd390b5a152bc1dc36793949c19] # to [c2e75d36a6314f29f490f12d9d98f4bb50b843fc] # ============================================================ --- Makefile de7747e757f0f60e45c426582c5736214e14d050 +++ Makefile b5d08d5d0ac834ea39ee009f56ef0e3780848f88 @@ -3,7 +3,7 @@ SSRCS=crt0.s NAME=quad SSRCS=crt0.s -CSRCS=main.c i2c.c wmp.c timer.c +CSRCS=main.c i2c.c wmp.c timer.c interrupt.c uart.c COPTIM?=-O1 CFLAGS=-march=armv4t -msoft-float $(COPTIM) -Wall -Werror -Wextra ============================================================ --- crt0.s adfe53d34fb8bcfcb9ecc9f2824f484661f0ec94 +++ crt0.s 5b6b789fc104e92e95e61047448c05cbcfb0e3db @@ -69,7 +69,7 @@ vectors: b prefetch_abort_handler b data_abort_handler nop /* reserved */ - b irq_handler + ldr pc, [pc, #-0xff0] /* branch through VICVectAddr register */ b fiq_handler @@ -177,7 +177,6 @@ data_abort_handler: swi_handler: prefetch_abort_handler: data_abort_handler: -irq_handler: fiq_handler: __back: ============================================================ --- /dev/null +++ interrupt.c cd7c20769cf360122ade5179a795a26b7f28f260 @@ -0,0 +1,84 @@ +#include "interrupt.h" + +#define VICBASE 0xFFFFF000 + +#define IRQStatus 0x00 +#define FIQStatus 0x04 +#define RawIntr 0x08 +#define IntSelect 0x0c +#define IntEnable 0x10 +#define IntEnClr 0x14 +#define SoftInt 0x18 +#define SoftIntClear 0x1c +#define Protection 0x20 +#define VectAddr 0x30 +#define DefVectAddr 0x34 +#define VectAddr0 0x100 +#define VectAddr1 0x104 +#define VectAddr2 0x108 +#define VectAddr3 0x10c +#define VectAddr4 0x110 +#define VectAddr5 0x114 +#define VectAddr6 0x118 +#define VectAddr7 0x11c +#define VectAddr8 0x120 +#define VectAddr9 0x124 +#define VectAddr10 0x128 +#define VectAddr11 0x12c +#define VectAddr12 0x130 +#define VectAddr13 0x134 +#define VectAddr14 0x138 +#define VectAddr15 0x13c +#define VectCntl0 0x200 +#define VectCntl1 0x204 +#define VectCntl2 0x208 +#define VectCntl3 0x20c +#define VectCntl4 0x210 +#define VectCntl5 0x214 +#define VectCntl6 0x218 +#define VectCntl7 0x21c +#define VectCntl8 0x220 +#define VectCntl9 0x224 +#define VectCntl10 0x228 +#define VectCntl11 0x22c +#define VectCntl12 0x230 +#define VectCntl13 0x234 +#define VectCntl14 0x238 +#define VectCntl15 0x23c + +#define VWREG(x) (((volatile unsigned int *)VICBASE)[(x)/sizeof(unsigned int)]) +#define VADDRREG(x) VWREG(VectAddr0 + (x) * 4) +#define VCNTLREG(x) VWREG(VectCntl0 + (x) * 4) + +#define IRQslot_en (1<<5) + + +void __attribute__((interrupt("IRQ"))) interrupt_default_handler(void); + + +void init_interrupt(void) +{ + VWREG(IntSelect) = 0; + VWREG(IntEnable) = 0; + VWREG(DefVectAddr) = (unsigned int) &interrupt_default_handler; +} + +void __attribute__((interrupt("IRQ"))) interrupt_default_handler(void) +{ + /* Do nothing. Assume that if there is a genuine interrupt + * request that it will be asserted again soon. + */ + interrupt_clear(); +} + + +/* Call as interrupt_register(SOURCE, fn) */ + +void interrupt_register_code(unsigned int source, unsigned int priority, + void(*handler)(void)) +{ + VADDRREG(priority) = (unsigned int) handler; + VCNTLREG(priority) = source | IRQslot_en; + VWREG(IntEnable) |= (1<<source); +} + ============================================================ --- /dev/null +++ interrupt.h faeb61e4d25cc1baced72430fd4ff30c169ea721 @@ -0,0 +1,46 @@ +#ifndef __INTERRUPT_H +#define __INTERRUPT_H + +#define VICVectAddr (*(volatile unsigned int *)0xFFFFF030) + +#define I_WDT 0 + +#define I_ARMCore0 2 +#define I_ARMCore1 3 +#define I_TIMER0 4 +#define I_TIMER1 5 +#define I_UART0 6 +#define I_UART1 7 + +#define I_I2C0 9 +#define I_SPI0 10 +#define I_SPI1 11 +#define I_SSP 11 +#define I_PLL 12 +#define I_RTC 13 +#define I_EINT0 14 +#define I_EINT1 15 +#define I_EINT2 16 + +#define I_AD0 18 +#define I_I2C1 19 + +#define I_TIMER2 26 +#define I_TIMER3 27 + +/* Assign interrupt priorities here to avoid clashes */ + +#define I_PRIORITY_I2C0 0 +#define I_PRIORITY_UART0 1 +#define I_PRIORITY_TIMER0 2 + +#define interrupt_clear() do { VICVectAddr = 0xff; } while (0) + +void init_interrupt(void); +void interrupt_register_code(unsigned int source, unsigned int priority, + void(*handler)(void)); + +#define interrupt_register(x, fn) \ + interrupt_register_code(I_##x, I_PRIORITY_##x, fn) + +#endif /* __INTERRUPT_H */ ============================================================ --- main.c ef5435dd23ece2876b0d557328e6c83a7ee04ab6 +++ main.c f3f04a92cb8f9ba8fdecd0b2fd95773011c1e076 @@ -2,93 +2,17 @@ #include "wmp.h" #include "i2c.h" #include "timer.h" +#include "uart.h" +#include "interrupt.h" -#define UARTBASE 0xE000C000 - -#define RBR 0x00 -#define THR 0x00 -#define DLL 0x00 -#define DLM 0x04 -#define IER 0x04 -#define IIR 0x08 -#define FCR 0x08 - -#define LCR 0x0c -#define LSR 0x14 -#define SCR 0x1c -#define ACR 0x20 -#define FDR 0x28 -#define TER 0x30 - -#define UREG(x) (((volatile unsigned char *)UARTBASE)[x]) - -#define U0THRE ((UREG(LSR) & (1<<5))) /* UART0 transmitter holding register is empty */ -#define U0DR ((UREG(LSR) & (1<<0))) /* UART0 data ready */ - #define PINSEL0 (*((volatile unsigned char *) 0xE002C000)) -void init_uart(void) -{ - UREG(FDR) = 0x10; /* DivAddVal = 0, MulVal = 1 */ - - UREG(LCR) = 0x80; - UREG(DLM) = 0x00; - UREG(DLL) = 0x08; /* 14745600 / (16*115200) */ - UREG(LCR) = 0x13; - UREG(FCR) = 0x07; -} - void init_pins(void) { PINSEL0 = 0x00000055; /* P0.0 and P0.1 assigned to UART */ /* P0.2 and P0.3 assigned to I2C */ } -void putch(char c) { - while (!U0THRE); - UREG(THR) = c; -} - -void putstr(char *s) { - while (*s) putch(*s++); -} - -void putint(unsigned int n) { - char s[11]; - int i; - - i = 10; - s[i] = '\0'; - - do { - s[--i] = n % 10 + '0'; - } while ((n /= 10) > 0); - - putstr(s+i); -} - -void puthex(unsigned int n) { - char s[9]; - int i; - - i = 8; - s[i] = '\0'; - - do { - int x = n % 16; - if (x > 9) - x += 'A' - '0' - 10; - s[--i] = x + '0'; - } while ((n /= 16) > 0); - - putstr(s+i); -} - -char getch(void) { - while (!U0DR); - return UREG(RBR); -} - void reply(char *str) { putstr(str); @@ -228,6 +152,7 @@ int main(void) { int main(void) { int i; + init_interrupt(); init_uart(); init_i2c(); init_pins(); @@ -330,6 +255,11 @@ int main(void) { puthex(timer_read()); reply("."); break; + case 'P': + putstr("Initialising timer... "); + timer_set_period(10000*TIMER_MS); + reply("done"); + break; default: reply("Unrecognised command."); break; ============================================================ --- timer.c cd7a8d69e6c6dcdc33683f9f6dfcc98c62d77b4d +++ timer.c bbb624ceb301647f8ffb240074c02ed3c3200135 @@ -1,4 +1,6 @@ #include "timer.h" +#include "interrupt.h" +#include "uart.h" #define TIMER0BASE 0xE0004000 #define TIMER1BASE 0xE0008000 @@ -28,14 +30,29 @@ #define TCR_ENABLE (1<<0) #define TCR_RESET (1<<1) +#define MR0I (1<<0) +#define MR0R (1<<1) +#define MR0S (1<<2) +#define MR1I (1<<3) +#define MR1R (1<<4) +#define MR1S (1<<5) +#define MR2I (1<<6) +#define MR2R (1<<7) +#define MR2S (1<<8) +#define MR3I (1<<9) +#define MR3R (1<<10) +#define MR3S (1<<11) + +void __attribute__((interrupt("IRQ"))) timer_interrupt_handler(void); + void init_timer(void) { TREG(TCR) = TCR_ENABLE | TCR_RESET; TREG(CTCR) = 0; /* Use PCLK */ - TREG(TC) = 0; - TREG(PR) = TIMER_PRESCALE ; - TREG(PC) = 0; + TWREG(TC) = 0; + TWREG(PR) = TIMER_PRESCALE ; + TWREG(PC) = 0; TREG(TCR) = TCR_ENABLE; } @@ -51,3 +68,24 @@ void timer_delay_clocks(unsigned int clo while (((signed int) (time-TWREG(TC))) > 0); } +void timer_set_period(unsigned int period) +{ + TWREG(MR0) = period; + TWREG(MCR) = MR0I | MR0R; + interrupt_register(TIMER0, timer_interrupt_handler); +} + +void __attribute__((interrupt("IRQ"))) timer_interrupt_handler(void) +{ + unsigned int ir; + ir = TREG(IR); + TREG(IR) = ir; + + if (ir & (1<<0)) { + /* Match channel 0 */ + putstr(" *timer0* "); + } + + interrupt_clear(); +} + ============================================================ --- timer.h 95b887ab46f9dbd390b5a152bc1dc36793949c19 +++ timer.h c2e75d36a6314f29f490f12d9d98f4bb50b843fc @@ -11,6 +11,7 @@ void timer_delay_clocks(unsigned int clo void init_timer(void); unsigned int timer_read(void); void timer_delay_clocks(unsigned int clocks); +void timer_set_period(unsigned int period); #define timer_delay_us(x) timer_delay_clocks((x)*TIMER_US) #define timer_delay_ms(x) timer_delay_clocks((x)*TIMER_MS) ============================================================ --- /dev/null +++ uart.c b336e227dc442fef728c0a695671328c7a265dd1 @@ -0,0 +1,79 @@ +#include "uart.h" + +#define UARTBASE 0xE000C000 + +#define RBR 0x00 +#define THR 0x00 +#define DLL 0x00 +#define DLM 0x04 +#define IER 0x04 +#define IIR 0x08 +#define FCR 0x08 + +#define LCR 0x0c +#define LSR 0x14 +#define SCR 0x1c +#define ACR 0x20 +#define FDR 0x28 +#define TER 0x30 + +#define UREG(x) (((volatile unsigned char *)UARTBASE)[x]) + +#define U0THRE ((UREG(LSR) & (1<<5))) /* UART0 transmitter holding register is empty */ +#define U0DR ((UREG(LSR) & (1<<0))) /* UART0 data ready */ + +void init_uart(void) +{ + UREG(FDR) = 0x10; /* DivAddVal = 0, MulVal = 1 */ + + UREG(LCR) = 0x80; + UREG(DLM) = 0x00; + UREG(DLL) = 0x08; /* 14745600 / (16*115200) */ + UREG(LCR) = 0x13; + UREG(FCR) = 0x07; +} + +void putch(char c) { + while (!U0THRE); + UREG(THR) = c; +} + +void putstr(char *s) { + while (*s) putch(*s++); +} + +void putint(unsigned int n) { + char s[11]; + int i; + + i = 10; + s[i] = '\0'; + + do { + s[--i] = n % 10 + '0'; + } while ((n /= 10) > 0); + + putstr(s+i); +} + +void puthex(unsigned int n) { + char s[9]; + int i; + + i = 8; + s[i] = '\0'; + + do { + int x = n % 16; + if (x > 9) + x += 'A' - '0' - 10; + s[--i] = x + '0'; + } while ((n /= 16) > 0); + + putstr(s+i); +} + +char getch(void) { + while (!U0DR); + return UREG(RBR); +} ============================================================ --- /dev/null +++ uart.h 2d08795e26e7e976bded494c773936c5f91d1b69 @@ -0,0 +1,11 @@ +#ifndef __UART_H +#define __UART_H + +void init_uart(void); +void putch(char c); +void putstr(char *s); +void putint(unsigned int n); +void puthex(unsigned int n); +char getch(void); + +#endif /* __UART_H */