The unified diff between revisions [cc8258a6..] and [1dfe3b7e..] is displayed below. It can also be downloaded as a raw diff.
# # old_revision [cc8258a6c3643514892e84cf24fed008bc6f9660] # new_revision [1dfe3b7eee76f3c8aea3b33932857682ee17701c] # # add_file "event.c" # content [36ab52fd83585734fc7b199852099d76470bf398] # # add_file "event.h" # content [b92070564927535f836fe3cfc7b9460703f7afa0] # # add_file "swi.h" # content [1198af2b0bcc19ab77033a4a390f0a2f32bc9305] # # patch "Makefile" # from [b5d08d5d0ac834ea39ee009f56ef0e3780848f88] # to [bd708913eaf7c1bac787cd82ff2b7e23c57ddc59] # # patch "crt0.s" # from [5b6b789fc104e92e95e61047448c05cbcfb0e3db] # to [0dec978fe999503c2346f42cb3588323205db715] # # patch "interrupt.h" # from [faeb61e4d25cc1baced72430fd4ff30c169ea721] # to [3735115d09df71f1da6b5ed670f9df7c4aafb82c] # # patch "main.c" # from [0a896cdc054a7e9fc0211de74469c22eef83a867] # to [cc6bdc935c17a517544beb8e177fc1093fff5249] # # patch "timer.c" # from [bbb624ceb301647f8ffb240074c02ed3c3200135] # to [9ef2a6c50a8a227103c6c98477c1ce62327a0977] # # patch "types.h" # from [410b58a239e1dd3e76ed5c6c9f7cfa28d09ef6c7] # to [00b92d607bdb71185e8326714de30eb16d3329ff] # ============================================================ --- Makefile b5d08d5d0ac834ea39ee009f56ef0e3780848f88 +++ Makefile bd708913eaf7c1bac787cd82ff2b7e23c57ddc59 @@ -3,7 +3,7 @@ SSRCS=crt0.s NAME=quad SSRCS=crt0.s -CSRCS=main.c i2c.c wmp.c timer.c interrupt.c uart.c +CSRCS=main.c i2c.c wmp.c timer.c interrupt.c uart.c event.c COPTIM?=-O1 CFLAGS=-march=armv4t -msoft-float $(COPTIM) -Wall -Werror -Wextra ============================================================ --- crt0.s 5b6b789fc104e92e95e61047448c05cbcfb0e3db +++ crt0.s 0dec978fe999503c2346f42cb3588323205db715 @@ -10,12 +10,24 @@ .equ APB_DIVIDER, 4 /* 1, 2 or 4 */ .equ UND_STACK_SIZE, 0x0004 - .equ SVC_STACK_SIZE, 0x0004 + .equ SVC_STACK_SIZE, 0x0010 .equ ABT_STACK_SIZE, 0x0004 .equ FIQ_STACK_SIZE, 0x0004 .equ IRQ_STACK_SIZE, 0x0080 .equ USR_STACK_SIZE, 0x0400 + +.global _stack_size + + .equ _stack_size, 0 + .equ _stack_size, _stack_size + UND_STACK_SIZE + .equ _stack_size, _stack_size + SVC_STACK_SIZE + .equ _stack_size, _stack_size + ABT_STACK_SIZE + .equ _stack_size, _stack_size + FIQ_STACK_SIZE + .equ _stack_size, _stack_size + IRQ_STACK_SIZE + .equ _stack_size, _stack_size + USR_STACK_SIZE + + # Processor definitions .equ Mode_USR, 0x10 @@ -174,7 +186,6 @@ undefined_handler: # Undefined handlers can just spin for now undefined_handler: -swi_handler: prefetch_abort_handler: data_abort_handler: fiq_handler: @@ -182,5 +193,37 @@ __back: __back: b __back + + .equ SWI_MAX, 1 + +swi_handler: + stmfd sp!, {ip, lr} + ldr ip, [lr, #-4] + bic ip, #0xff000000 + + cmp ip, #SWI_MAX + ldmhifd sp!, {ip, pc}^ + + add ip, pc, ip, lsl #2 + ldr pc, [ip] + +swi_branch_table: + .word disable_interrupts + .word enable_interrupts + + +disable_interrupts: + mrs ip, SPSR + orr ip, ip, #I_Bit + msr SPSR_c,ip + ldmfd sp!, {ip, pc}^ + +enable_interrupts: + mrs ip, SPSR + bic ip, ip, #I_Bit + msr SPSR_c,ip + ldmfd sp!, {ip, pc}^ + + .endfunc .end ============================================================ --- /dev/null +++ event.c 36ab52fd83585734fc7b199852099d76470bf398 @@ -0,0 +1,74 @@ +#include "event.h" +#include "interrupt.h" +#include "types.h" + +event_handler *event_handler_table[EVENT_MAX+1]; + +#define EVENT_WORDS ((EVENT_MAX+1+31)/32) + +unsigned int event_pending[EVENT_WORDS]; + +#define EVENT_WORDLEN 32 +#define EVENT_WORD(x) (x/EVENT_WORDLEN) +#define EVENT_BIT(x) (x%EVENT_WORDLEN) +#define EVENT_MASK(x) (1<<EVENT_BIT(x)) + +void event_set(unsigned int event) +{ + if (event > EVENT_MAX) + return; + + interrupt_block(); + event_pending[EVENT_WORD(event)] |= EVENT_MASK(event); + interrupt_unblock(); +} + +static int bitset(unsigned int x) +{ + x = 0xffffffff - (x-1); + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x << 8); + x = x + (x << 16); + return 32 - (x >> 24); +} + +bool event_get(unsigned int *event) +{ + int i; + unsigned int p; + + for (i = 0; i < EVENT_WORDS; i++) { + if ((p = event_pending[i]) != 0) { + p = p & (-p); + *event = bitset(p) + EVENT_WORDLEN*i; + return TRUE; + } + } + return FALSE; +} + +void event_clear(unsigned int event) +{ + interrupt_block(); + event_pending[EVENT_WORD(event)] &= ~EVENT_MASK(event); + interrupt_unblock(); +} + +void event_dispatch(void) +{ + unsigned int event; + + if (event_get(&event)) { + event_clear(event); + (event_handler_table[event])(); + } +} + +void event_register(unsigned int event, event_handler *handler) +{ + if (event > EVENT_MAX) + return; + event_handler_table[event] = handler; +} ============================================================ --- /dev/null +++ event.h b92070564927535f836fe3cfc7b9460703f7afa0 @@ -0,0 +1,19 @@ +#ifndef __EVENT_H +#define __EVENT_H + +#include "types.h" + +#define EVENT_TIMER 0 +#define EVENT_I2C_COMPLETE 1 + +#define EVENT_MAX 1 + +typedef void event_handler(void); + +void event_set(unsigned int event); +bool event_get(unsigned int *event); +void event_clear(unsigned int event); +void event_dispatch(void); +void event_register(unsigned int event, event_handler *handler); + +#endif /* __EVENT_H */ ============================================================ --- interrupt.h faeb61e4d25cc1baced72430fd4ff30c169ea721 +++ interrupt.h 3735115d09df71f1da6b5ed670f9df7c4aafb82c @@ -1,6 +1,8 @@ #ifndef __INTERRUPT_H #define __INTERRUPT_H +#include "swi.h" + #define VICVectAddr (*(volatile unsigned int *)0xFFFFF030) #define I_WDT 0 @@ -43,4 +45,7 @@ void interrupt_register_code(unsigned in #define interrupt_register(x, fn) \ interrupt_register_code(I_##x, I_PRIORITY_##x, fn) +#define interrupt_block() swi_call(SWI_INTERRUPT_BLOCK) +#define interrupt_unblock() swi_call(SWI_INTERRUPT_UNBLOCK) + #endif /* __INTERRUPT_H */ ============================================================ --- main.c 0a896cdc054a7e9fc0211de74469c22eef83a867 +++ main.c cc6bdc935c17a517544beb8e177fc1093fff5249 @@ -4,6 +4,7 @@ #include "timer.h" #include "uart.h" #include "interrupt.h" +#include "event.h" #define PINSEL0 (*((volatile unsigned char *) 0xE002C000)) #define FP0XDIR (*((volatile unsigned int *) 0x3FFFC000)) @@ -255,6 +256,10 @@ int main(void) { timer_set_period(10000*TIMER_MS); reply("done"); break; + case 'E': + event_dispatch(); + reply("done"); + break; default: reply("Unrecognised command."); break; ============================================================ --- /dev/null +++ swi.h 1198af2b0bcc19ab77033a4a390f0a2f32bc9305 @@ -0,0 +1,10 @@ +#ifndef __SWI_H +#define __SWI_H + +#define SWI_INTERRUPT_BLOCK 0 +#define SWI_INTERRUPT_UNBLOCK 1 + +#define swi_call(x) swi_call_(x) +#define swi_call_(x) __asm(" swi " #x "\n") + +#endif /* __SWI_H */ ============================================================ --- timer.c bbb624ceb301647f8ffb240074c02ed3c3200135 +++ timer.c 9ef2a6c50a8a227103c6c98477c1ce62327a0977 @@ -1,6 +1,7 @@ #include "timer.h" #include "interrupt.h" #include "uart.h" +#include "event.h" #define TIMER0BASE 0xE0004000 #define TIMER1BASE 0xE0008000 @@ -45,6 +46,8 @@ void __attribute__((interrupt("IRQ"))) t void __attribute__((interrupt("IRQ"))) timer_interrupt_handler(void); +void timer_event_handler(void); + void init_timer(void) { TREG(TCR) = TCR_ENABLE | TCR_RESET; @@ -55,6 +58,7 @@ void init_timer(void) TWREG(PC) = 0; TREG(TCR) = TCR_ENABLE; + event_register(EVENT_TIMER, timer_event_handler); } unsigned int timer_read(void) @@ -86,6 +90,12 @@ void __attribute__((interrupt("IRQ"))) t putstr(" *timer0* "); } + event_set(EVENT_TIMER); + interrupt_clear(); } +void timer_event_handler(void) +{ + putstr(" *t0event* "); +} ============================================================ --- types.h 410b58a239e1dd3e76ed5c6c9f7cfa28d09ef6c7 +++ types.h 00b92d607bdb71185e8326714de30eb16d3329ff @@ -7,4 +7,6 @@ typedef int bool; #define NULL 0 +typedef int size_t; + #endif /* __TYPES_H */