added timer/counter interrupt support
authorhackbard <hackbard@sage.physik.uni-augsburg.de>
Fri, 21 Sep 2007 09:41:30 +0000 (11:41 +0200)
committerhackbard <hackbard@sage.physik.uni-augsburg.de>
Fri, 21 Sep 2007 09:41:30 +0000 (11:41 +0200)
betty/interrupts.c
betty/interrupts.h

index e344f05..0e0baa3 100644 (file)
@@ -15,6 +15,8 @@ static t_interrupt interrupt;
  * functions
  */
 
+// generaal interrupt handling
+
 void interrupt_init(void) {
 
        interrupt.default_soft_callback=0;
@@ -33,6 +35,11 @@ void interrupt_set_soft_callback(void (*callback)(void)) {
        interrupt.default_soft_callback=callback;
 }
 
+void interrupt_set_fiq_callback(void (*callback)(void)) {
+
+       interrupt.fiq_callback=callback;
+}
+
 void interrupt_soft_clear(u8 src_number) {
 
        VICSoftIntClr=(1<<src_number);
@@ -62,7 +69,7 @@ void interrupt_soft_enable(u8 src_number) {
        VICSoftInt=(1<<src_number);
 }
 
-int interrupt_enable(u8 src_number,u8 mode,u8 priority,u32 callback_addr) {
+int interrupt_enable(u8 src_number,u8 mode,u8 prio,u32 callback_addr) {
 
        u32 *addr;
        u32 *cntl;
@@ -80,10 +87,10 @@ int interrupt_enable(u8 src_number,u8 mode,u8 priority,u32 callback_addr) {
                        VICIntSelect|=(1<<src_number);
                        break;
                case INTERRUPT_MODE_VIRQ:
-                       if(addr[priority]&0x3f)
+                       if(addr[prio]&0x3f)
                                return INTERRUPT_PRIORITY_USED;
-                       *((volatile u32 *)(addr+priority))=callback_addr;
-                       *((volatile u32 *)(cntl+priority))=(src_number&0x1f)+0x20;
+                       *((volatile u32 *)(addr+prio))=callback_addr;
+                       *((volatile u32 *)(cntl+prio))=(src_number&0x1f)+0x20;
                case INTERRUPT_MODE_IRQ:
                default:
                        break;
@@ -115,6 +122,14 @@ int interrupt_change_callback(u8 src_number,u32 callback) {
        return INTERRUPT_SRC_NOT_USED;
 }
 
+void interrupt_ack(void) {
+
+       VICVectAddr=0;
+}
+
+// specific interrupt handling
+
+// external interrupts
 void interrupt_ext_ir_config(u8 eint,u8 wakeup,u8 mode,u8 polarity) {
 
        if(eint>3)
@@ -135,9 +150,69 @@ void interrupt_ext_ir_set(u8 eint) {
        EXTINT=(1<<eint);
 }
 
-void interrupt_ack(void) {
+// timer counter interrupts
+void interrupt_tc_config(u8 tcnum,u8 mode,u8 cap,u32 psc) {
 
-       VICVectAddr=0;
+       if(tcnum>1)
+               return;
+
+       if(tcnum==0) {
+               T0TCR=0x03;
+               T0CTCR=mode|(cap<<2);
+               T0PR=psc;
+       }
+       else {
+               T1TCR=0x03;
+               T1CTCR=mode|(cap<<2);
+               T1PR=psc;
+       }
+}
+
+void interrupt_tc_match_config(u8 tcnum,u8 mnum,u32 val,u8 mode) {
+
+       u32 *mraddr;
+
+       if(tcnum>1)
+               return;
+
+       if(mnum>3)
+               return;
+
+       if(tcnum==0) {
+               T0MCR=mode<<(3*mnum);
+               mrddr=&T0MR0
+       }
+       else {
+               T1MCR=mode<<(3*mnum);
+               mrddr=&T1MR0
+       }
+
+       mraddr[mnum]=val;
+}
+
+void interrupt_tc_capt_config(u8 tcnum,u8 cnum,u8 mode) {
+
+       if(tcnum>1)
+               return;
+
+       if(cnum>3)
+               return;
+
+       if(tcnum==0)
+               T0CCR=mode<<(3*cnum);
+       else
+               T1CCR=mode<<(3*cnum);
+}
+
+void interrupt_tc_ir_set(u8 tcnum,u8 tcmc) {
+
+       if(tcnum>1)
+               return;
+
+       if(tcnum==0)
+               T0IR=tcmc;
+       else
+               T1IR=tcmc;
 }
 
 /*
@@ -169,5 +244,8 @@ void interrupt_handler_data_abort(void) {
 
 // fiq
 void interrupt_handler_fiq(void) {
+
+       if(interrupt.fiq_callback)
+               interrupt.fiq_callback();
 }
 
index cfb7591..21d7413 100644 (file)
 #define INTERRUPT_EXT2                 2
 #define INTERRUPT_EXT3                 3
 
+#define INTERRUPT_TC_MODE_T            0x00
+#define INTERRUPT_TC_MODE_CR           0x01
+#define INTERRUPT_TC_MODE_CF           0x02
+#define INTERRUPT_TC_MODE_CB           0x03
+
+#define INTERRUPT_TC_MATCH_IR          0x01
+#define INTERRUPT_TC_MATCH_RESET       0x02
+#define INTERRUPT_TC_MATCH_STOP                0x04
+
+#define INTERRUPT_TC_CAPT_R            0x01
+#define INTERRUPT_TC_CAPT_F            0x02
+#define INTERRUPT_TC_CAPT_I            0x04
+
+#define INTERRUPT_CAP0                 0x00
+#define INTERRUPT_CAP1                 0x01
+#define INTERRUPT_CAP2                 0x02
+#define INTERRUPT_CAP3                 0x03
+
+#define INTERRUPT_M0                   0x01
+#define INTERRUPT_M1                   0x02
+#define INTERRUPT_M2                   0x04
+#define INTERRUPT_M3                   0x08
+#define INTERRUPT_C0                   0x10
+#define INTERRUPT_C1                   0x20
+#define INTERRUPT_C2                   0x40
+#define INTERRUPT_C3                   0x80
+
 #define INTERRUPT_SET                  0x00
 #define INTERRUPT_USED                 0x01
 #define INTERRUPT_PRIORITY_USED                0x02
@@ -60,6 +87,7 @@
 
 typedef struct s_interrupt {
        void (*default_soft_callback)(void);
+       void (*fiq_callback)(void);
 } t_interrupt;
 
 /* function prototypes */
@@ -67,15 +95,22 @@ typedef struct s_interrupt {
 void interrupt_init(void);
 void interrupt_set_default_callback(u32 callback_addr);
 void interrupt_set_soft_callback(void (*callback)(void));
+void interrupt_set_fiq_callback(void (*callback)(void));
 void interrupt_soft_clear(u8 src_number);
 void interrupt_clear(u8 src_number);
 void interrupt_soft_enable(u8 src_number);
-int interrupt_enable(u8 src_number,u8 mode,u8 priority,u32 callback_addr);
+int interrupt_enable(u8 src_number,u8 mode,u8 prio,u32 callback_addr);
 int interrupt_change_callback(u8 src_number,u32 callback_addr);
+
 void interrupt_ext_ir_config(u8 eint,u8 wakeup,u8 mode,u8 polarity);
 void interrupt_ext_ir_set(u8 eint);
 void interrupt_ack(void);
 
+void interrupt_tc_config(u8 tcnum,u8 mode,u8 cap,u32 psc);
+void interrupt_tc_match_config(u8 tcnum,u8 mnum,u32 val,u8 mode);
+void interrupt_tc_capt_config(u8 tcnum,u8 cnum,u8 mode);
+void interrupt_tc_ir_set(u8 tcnum,u8 tcmc);
+
 void interrupt_handler_reset(void);
 void interrupt_handler_undef_instruction(void);
 void interrupt_handler_soft_ir(void);