Browse Source

* Move UART code into its own file

* Set up vectored interrupt controller
* Set up timer interrupt
master
Gavan Fantom 14 years ago
parent
commit
e1b1b60a53
  1. 2
      Makefile
  2. 3
      crt0.s
  3. 84
      interrupt.c
  4. 46
      interrupt.h
  5. 86
      main.c
  6. 44
      timer.c
  7. 1
      timer.h
  8. 79
      uart.c
  9. 11
      uart.h

2
Makefile

@ -3,7 +3,7 @@
NAME=quad NAME=quad
SSRCS=crt0.s 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 COPTIM?=-O1
CFLAGS=-march=armv4t -msoft-float $(COPTIM) -Wall -Werror -Wextra CFLAGS=-march=armv4t -msoft-float $(COPTIM) -Wall -Werror -Wextra

3
crt0.s

@ -69,7 +69,7 @@ vectors:
b prefetch_abort_handler b prefetch_abort_handler
b data_abort_handler b data_abort_handler
nop /* reserved */ nop /* reserved */
b irq_handler ldr pc, [pc, #-0xff0] /* branch through VICVectAddr register */
b fiq_handler b fiq_handler
@ -177,7 +177,6 @@ undefined_handler:
swi_handler: swi_handler:
prefetch_abort_handler: prefetch_abort_handler:
data_abort_handler: data_abort_handler:
irq_handler:
fiq_handler: fiq_handler:
__back: __back:

84
interrupt.c

@ -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);
}

46
interrupt.h

@ -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 */

86
main.c

@ -2,93 +2,17 @@
#include "wmp.h" #include "wmp.h"
#include "i2c.h" #include "i2c.h"
#include "timer.h" #include "timer.h"
#include "uart.h"
#define UARTBASE 0xE000C000 #include "interrupt.h"
#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)) #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) void init_pins(void)
{ {
PINSEL0 = 0x00000055; /* P0.0 and P0.1 assigned to UART */ PINSEL0 = 0x00000055; /* P0.0 and P0.1 assigned to UART */
/* P0.2 and P0.3 assigned to I2C */ /* 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) void reply(char *str)
{ {
putstr(str); putstr(str);
@ -228,6 +152,7 @@ void average_sample(void)
int main(void) { int main(void) {
int i; int i;
init_interrupt();
init_uart(); init_uart();
init_i2c(); init_i2c();
init_pins(); init_pins();
@ -330,6 +255,11 @@ int main(void) {
puthex(timer_read()); puthex(timer_read());
reply("."); reply(".");
break; break;
case 'P':
putstr("Initialising timer... ");
timer_set_period(10000*TIMER_MS);
reply("done");
break;
default: default:
reply("Unrecognised command."); reply("Unrecognised command.");
break; break;

44
timer.c

@ -1,4 +1,6 @@
#include "timer.h" #include "timer.h"
#include "interrupt.h"
#include "uart.h"
#define TIMER0BASE 0xE0004000 #define TIMER0BASE 0xE0004000
#define TIMER1BASE 0xE0008000 #define TIMER1BASE 0xE0008000
@ -28,14 +30,29 @@
#define TCR_ENABLE (1<<0) #define TCR_ENABLE (1<<0)
#define TCR_RESET (1<<1) #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) void init_timer(void)
{ {
TREG(TCR) = TCR_ENABLE | TCR_RESET; TREG(TCR) = TCR_ENABLE | TCR_RESET;
TREG(CTCR) = 0; /* Use PCLK */ TREG(CTCR) = 0; /* Use PCLK */
TREG(TC) = 0; TWREG(TC) = 0;
TREG(PR) = TIMER_PRESCALE ; TWREG(PR) = TIMER_PRESCALE ;
TREG(PC) = 0; TWREG(PC) = 0;
TREG(TCR) = TCR_ENABLE; TREG(TCR) = TCR_ENABLE;
} }
@ -51,3 +68,24 @@ void timer_delay_clocks(unsigned int clocks)
while (((signed int) (time-TWREG(TC))) > 0); 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();
}

1
timer.h

@ -11,6 +11,7 @@
void init_timer(void); void init_timer(void);
unsigned int timer_read(void); unsigned int timer_read(void);
void timer_delay_clocks(unsigned int clocks); 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_us(x) timer_delay_clocks((x)*TIMER_US)
#define timer_delay_ms(x) timer_delay_clocks((x)*TIMER_MS) #define timer_delay_ms(x) timer_delay_clocks((x)*TIMER_MS)

79
uart.c

@ -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);
}

11
uart.h

@ -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 */
Loading…
Cancel
Save