* Move UART code into its own file
* Set up vectored interrupt controller * Set up timer interrupt
This commit is contained in:
2
Makefile
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
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
Normal file
84
interrupt.c
Normal file
@@ -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
Normal file
46
interrupt.h
Normal file
@@ -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
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
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
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
Normal file
79
uart.c
Normal file
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user