Working timer interrupts on TIC55x (Grandstream BT-200)
authorRick van Rein <vanrein@hwdev.(none)>
Wed, 6 Apr 2011 12:07:50 +0000 (12:07 +0000)
committerRick van Rein <vanrein@hwdev.(none)>
Wed, 6 Apr 2011 12:07:50 +0000 (12:07 +0000)
Note that SLEEP_HIBERNATE still gets stuck, SLEEP_SNOOZE
does not however.  The irqpolling variety is inconsistent
in its timing, but that is not a real problem.

bin/kconfig/.kxgettext.o.d [deleted file]
src/driver/tic55x/grandstream-bt20x.c
src/driver/tic55x/int.c
src/driver/tic55x/timer.c
src/driver/util/linuxtuntest.h [deleted file]
src/function/develtest/timer2led.c

diff --git a/bin/kconfig/.kxgettext.o.d b/bin/kconfig/.kxgettext.o.d
deleted file mode 100644 (file)
index 14865f4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-kxgettext.o: bin/kconfig/kxgettext.c /usr/include/stdlib.h \
-  /usr/include/features.h /usr/include/sys/cdefs.h \
-  /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
-  /usr/include/gnu/stubs-64.h \
-  /usr/lib/gcc/x86_64-linux-gnu/4.3.2/include/stddef.h \
-  /usr/include/sys/types.h /usr/include/bits/types.h \
-  /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
-  /usr/include/bits/endian.h /usr/include/sys/select.h \
-  /usr/include/bits/select.h /usr/include/bits/sigset.h \
-  /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
-  /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
-  /usr/include/string.h /usr/include/bits/string.h \
-  /usr/include/bits/string2.h bin/kconfig/lkc.h bin/kconfig/expr.h \
-  /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
-  /usr/include/wchar.h \
-  /usr/lib/gcc/x86_64-linux-gnu/4.3.2/include/stdarg.h \
-  /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
-  /usr/include/bits/stdio.h \
-  /usr/lib/gcc/x86_64-linux-gnu/4.3.2/include/stdbool.h \
-  /usr/include/libintl.h /usr/include/locale.h /usr/include/bits/locale.h \
-  bin/kconfig/lkc_proto.h
index c68bddc..5baa7b8 100644 (file)
@@ -48,14 +48,15 @@ void main (void) {
        tic55x_setup_interrupts ();
        //TODO// IER0 = 0xdefc;
        //TODO// IER1 = 0x00ff;
-       IER0 = (1 << REGBIT_IER0_TINT0);
        PCR0 = (1 << REGBIT_PCR_XIOEN) | (1 << REGBIT_PCR_RIOEN);
+#if 0
        while (true) {
                uint32_t ctr;
                bottom_led_set (LED_IDX_MESSAGE, led);
                for (ctr=6500000; ctr>0; ctr--) { ; }
                led ^= LED_STABLE_ON ^ LED_STABLE_OFF;
        }
+#endif
        top_main ();
 }
 
index f837327..8398df9 100644 (file)
  * immediately if the flag has been set meanwhile, as the top may
  * have missed incoming work.
  */
-bool tic55x_top_has_been_interrupted;
+volatile bool tic55x_top_has_been_interrupted;
 
 
-#if 0
 void bottom_sleep_prepare (void) {
        tic55x_top_has_been_interrupted = false;
 }
@@ -42,16 +41,13 @@ void bottom_sleep_commit (sleep_depth_t depth) {
        }
        bottom_critical_region_end ();
 }
-#endif
 
 interrupt void tic55x_no_isr (void) {
-#if 0
        /* No action */ ;
-#endif
 }
 
 
-// TODO -- probably do this in the trampoline code?
+// Setup interrupts -- probably move this to the trampoline code?
 void tic55x_setup_interrupts (void) {
        // extern uint32_t interrupt_table;
        // IVPD = (uint16_t) (((uint32_t) interrupt_table) >> 8);
index fc9a349..e545a12 100644 (file)
@@ -68,51 +68,43 @@ timing_t bottom_time (void) {
  */
 timing_t bottom_timer_set (timing_t tim) {
        timing_t intval, previous;
+       uint16_t cnt1, cnt2;
        /* First of all, reset timer0 so it can be configured */
-       GPTGCTL1_0 &= ~ ( REGVAL_GCTL_TIM12RS | REGVAL_GCTL_TIM34RS );
+       GPTGCTL1_0 &= ~ ( REGVAL_GCTL_TIM12RS | REGVAL_GCTL_TIM34RS);
        IFR0 = (1 << REGBIT_IER0_TINT0);
+       /* Juggle timing values to return the current setting */
        previous = current_timer;
        current_timer = tim;
+       /* Setup counter and period registers for timer0 */
+       GPTCNT3_0 = GPTCNT3_1; // Read CNT3, copy CNT4 to shadow
+       GPTCNT4_0 = GPTCNT4_1; // Load CNT4 from shadow copy
+       GPTCNT1_0 = GPTCNT1_1; // Read CNT1, copy CNT2 to shadow
+       GPTCNT2_0 = GPTCNT2_1; // Load CNT2 from shadow copy
+       GPTPRD2_0 = (uint16_t) (tim >> 16   );
+       GPTPRD1_0 = (uint16_t)  tim          ;
        /* Poll the running timer1 */
-       // tim = bottom_time () + TIME_MSEC(1500);
-       intval = tim - bottom_time ();
-// intval = intval & 0x0000ffff;
+       cnt1 = GPTCNT1_0;
+       cnt2 = GPTCNT2_0;
+       intval = tim - ((GPTCNT2_0 << 16) | GPTCNT1_0);
        if ((intval == 0) || (intval >> 31)) {
-               /* Cause interrupt right now, do not run the timer */
+               // Invoke handler right now, do not run timer0
                top_timer_expiration (tim);
                current_timer = 0;
-bottom_led_set (0, 1);
-{ uint32_t ctr = 6500000; while (ctr > 0) ctr--; }
-bottom_led_set (0, 0);
-{ uint32_t ctr = 6500000; while (ctr > 0) ctr--; }
                return previous;
        }
-       /* Setup counter value and period */
-       GPTCNT3_0 = GPTCNT3_1;  /* also copies GPTCNT4_1 to shadow register */
-       GPTCNT4_0 = GPTCNT4_1;  /* retrieve shadow register for GPTCNT4_1 */
-       GPTCNT2_0 =
-       GPTCNT1_0 = 0x0000;
-       GPTPRD2_0 = (uint16_t) (intval >> 16   );
-       GPTPRD1_0 = (uint16_t)  intval          ; //(intval & 0xffff);
-       /* Finally, enable timer1 so it can cause interrupts */
+       /* Finally, enable timer1 so it starts counting time */
        GPTGCTL1_0 |= REGVAL_GCTL_TIM12RS | REGVAL_GCTL_TIM34RS;
-bottom_led_set (0, 1);
-{ uint32_t ctr = 650000; while (ctr > 0) ctr--; }
-bottom_led_set (0, 0);
-{ uint32_t ctr = 650000; while (ctr > 0) ctr--; }
        return previous;
 }
 
 
 /* Timer interrupt handler for timer0 expiration */
 interrupt void tic55x_tint0_isr (void) {
-#if 0
-       extern bool tic55x_top_has_been_interrupted;
+       extern volatile bool tic55x_top_has_been_interrupted;
        timing_t now = bottom_time ();
        current_timer = 0;
        top_timer_expiration (now);
        tic55x_top_has_been_interrupted = true;
-#endif
 }
 
 
@@ -134,8 +126,9 @@ void tic55x_setup_timers (void) {
        GPTCTL1_0 = REGVAL_CTL12_ENAMODE_ONETIME;
        GPTCTL1_1 = REGVAL_CTL12_ENAMODE_CONTINUOUS;
        GPTGCTL1_0 = REGVAL_GCTL_TIMMODE_DUAL32CHAINED;
-       GPTGCTL1_1 = REGVAL_GCTL_TIMMODE_DUAL32CHAINED | REGVAL_GCTL_TIM12RS | REGVAL_GCTL_TIM34RS;
+       GPTGCTL1_1 = REGVAL_GCTL_TIMMODE_DUAL32CHAINED | REGVAL_GCTL_TIM34RS | REGVAL_GCTL_TIM12RS;
        /* Clear, then permit interrupts from timer0 */
        IFR0  = (1 << REGBIT_IER0_TINT0);
+       IER0 |= (1 << REGBIT_IER0_TINT0);
 }
 
diff --git a/src/driver/util/linuxtuntest.h b/src/driver/util/linuxtuntest.h
deleted file mode 100644 (file)
index f8a604a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-
-#include <stdint.h>
-
-typedef uint64_t timing_t;
-
-#define TIMER_NULL 0
-
-#define TIME_MSEC 1
-#define TIME_SEC  1000
-
index 4c82dc5..452434c 100644 (file)
 #include <0cpm/led.h>
 
 
-#define complete_top_main top_main
+volatile led_colour_t ledstate = LED_STABLE_ON;
+volatile timing_t nextirq;
+
+
+#define snoozing_top_main top_main
 
 
 void doesitcount_top_main (void) {
@@ -39,100 +43,77 @@ void noirq_top_main (void) {
                if (TIME_BEFORE (nextirq, bottom_time ())) {
                        nextstate ^= LED_STABLE_ON ^ LED_STABLE_OFF;
                        bottom_led_set (LED_IDX_MESSAGE, nextstate);
-                       // nextirq = bottom_time () + TIME_MSEC(500);
                        nextirq += TIME_MSEC(500);
                }
        }
 }
 
 
+void top_timer_expiration (timing_t exptime) {
+       uint16_t ctr;
+       ledstate ^= LED_STABLE_ON ^ LED_STABLE_OFF;
+       nextirq += TIME_MSEC(500);
+       bottom_timer_set (nextirq);
+}
+
+
 void irqpolling_top_main (void) {
-       timing_t nextirq;
-redo:
-       nextirq = bottom_time () + TIME_MSEC(1500);
-bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON);
-{ uint16_t ctr = 65000; while (ctr > 0) ctr--; }
-bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
-{ uint16_t ctr = 65000; while (ctr > 0) ctr--; }
+       nextirq = bottom_time () + TIME_MSEC(500);
        bottom_timer_set (nextirq);
-bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON);
-{ uint16_t ctr = 65000; while (ctr > 0) ctr--; }
-bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
-{ uint16_t ctr = 65000; while (ctr > 0) ctr--; }
        while (true) {
+               bottom_led_set (LED_IDX_MESSAGE, ledstate);
 #ifdef INCLUDE_BOTTOM_IRQ_ACCESS_HALFWAY_DEVELOPMENT_HACK
-               if ("irq_flag_is_set") {
+               if ("irq_flag_is_set_AND_can_be_polled_with_certainty") {
                        "clear_irq_flag";
-                       bottom_timer_expiration (bottom_time () + TIME_MSEC(1500));
+                       top_timer_expiration (nextirq);
                }
 #else
-               if ((GPTCNT1_0==0) && (GPTCNT2_0==0)) {
+               // Flaky-timed code example for TIC55x follows
+               if (IFR0 & (1 << REGBIT_IER0_TINT0)) {
                        IFR0 = (1 << REGBIT_IER0_TINT0);
-                       // bottom_timer_expiration (bottom_time () + TIME_MSEC(1500));
-                       bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
-                       goto done;
-               } else {
-                       uint16_t ctr;
-                       uint16_t ctr1a, ctr1b;
-                       ctr1a = GPTCNT1_0;
-                       ctr1b = GPTCNT2_0;
-                       bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
-                       ctr = 65000;
-                       while (ctr > 0) {
-                               ctr--;
-                       }
-                       if ((ctr1a != GPTCNT1_0) || (ctr1b != GPTCNT2_0)) {
-                               bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON);
-                               ctr = 65000;
-                               while (ctr > 0) {
-                                       ctr--;
-                               }
-                       }
+                       nextirq += TIME_MSEC(500);
+                       top_timer_expiration (nextirq);
                }
 #endif
        }
-done:
-while (!bottom_phone_is_offhook ()) {
-       ;
-}
-while (bottom_phone_is_offhook ()) {
-       ;
-}
-goto redo;
 }
 
+void interrupted_top_main (void) {
+       nextirq = bottom_time () + TIME_MSEC(500);
+       bottom_timer_set (nextirq);
+       bottom_critical_region_end ();
+       while (true) {
+               bottom_led_set (LED_IDX_MESSAGE, ledstate);
+       }
+}
 
-volatile bool busy = false;
-
-void top_timer_expiration (timing_t exptime) {
-       uint16_t ctr;
-       // static led_colour_t nextstate = LED_STABLE_OFF;
-       // nextstate ^= LED_STABLE_ON ^ LED_STABLE_OFF;
-       // bottom_led_set (LED_IDX_MESSAGE, nextstate);
-       bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
-       // ctr = 65000;
-       // while (ctr > 0) {
-       //      ctr--;
-       // }
-       //ULTIMATELY// nextstate ^= LED_STABLE_ON ^ LED_STABLE_OFF;
-       //ULTIMATELY// bottom_led_set (LED_IDX_MESSAGE, nextstate);
-       // bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON);
-       // bottom_timer_set (exptime + TIME_MSEC(1500));
+void snoozing_top_main (void) {
+       led_colour_t curcol = LED_STABLE_OFF;
+       nextirq = bottom_time () + TIME_MSEC(500);
+       bottom_timer_set (nextirq);
+       bottom_critical_region_end ();
+       while (true) {
+               bottom_sleep_prepare ();
+               if (curcol == ledstate) {
+                       bottom_sleep_commit (SLEEP_SNOOZE);
+               }
+               curcol = ledstate;
+               bottom_led_set (LED_IDX_MESSAGE, curcol);
+       }
 }
 
 void complete_top_main (void) {
-       timing_t nextirq;
-       bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON);
-       nextirq = bottom_time () + TIME_MSEC(1500);
-       busy = true;
-       // bottom_timer_set (nextirq);
-       // bottom_critical_region_end ();
+       led_colour_t curcol = LED_STABLE_OFF;
+       nextirq = bottom_time () + TIME_MSEC(500);
+       bottom_timer_set (nextirq);
+       bottom_critical_region_end ();
        while (true) {
-               if (busy) {
-                       bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON );
-               } else {
-                       bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
+               bottom_sleep_prepare ();
+               if (curcol == ledstate) {
+                       bottom_sleep_commit (SLEEP_HIBERNATE);
                }
+               curcol = ledstate;
+               bottom_led_set (LED_IDX_MESSAGE, curcol);
        }
 }