changeset 40:a38003b97de6

Use debug cycle counter to handle delays.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 01 Apr 2013 20:06:03 +1030
parents 969bb070b181
children 2db4bb90cfca
files delay.c hw.c main.c
diffstat 3 files changed, 36 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/delay.c	Mon Apr 01 19:45:38 2013 +1030
+++ b/delay.c	Mon Apr 01 20:06:03 2013 +1030
@@ -1,83 +1,36 @@
+#include <assert.h>
 #include <stdint.h>
 #include "stm32f10x.h"
 #include "delay.h"
 
 /* Sleep for nCount usec
- * TDS1012 on 2.5usec/div shows...
- *   30usec = 29.60usec 
- *   60usec = 59.20usec 
- *
- * XXX: not sure disable IRQ stuff is working as I see occasional (small) extra delays
  */
 void
 delay(uint32_t nCount) {
-    __disable_irq();
-    for(; nCount != 0; nCount--) {
-#ifdef SYSCLK_FREQ_72MHz
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
+    uint32_t dly, cnt, clk_per_usec, max_dly;
+    volatile uint32_t *DWT_CYCCNT = (uint32_t *)0xe0001004;
 
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
+    __disable_irq();
 
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
-	__asm__("nop");
+#ifdef SYSCLK_FREQ_72MHz
+    clk_per_usec = 72;
+    max_dly = (1<<31) / clk_per_usec; /* Really half the maximum (still ~30 seconds at 72MHz) */
 #else
-#error Unknown clock frequency
+#error "Unknown clock frequency"
 #endif
-    }
+    assert(nCount < max_dly);
+    
+    cnt = *DWT_CYCCNT; /* Get current cycle count */
+    dly = nCount * clk_per_usec;
+    dly += cnt; /* Compute cycle count to stop at */
+    if (dly < cnt)
+	/* Stop count wrapped, wait until the counter wraps around */
+	while (*DWT_CYCCNT > cnt)
+	    ;
+    /* Wait until we get to the stop count */
+    while (*DWT_CYCCNT < dly)
+	;
+    
     __enable_irq();
 }
 
--- a/hw.c	Mon Apr 01 19:45:38 2013 +1030
+++ b/hw.c	Mon Apr 01 20:06:03 2013 +1030
@@ -363,4 +363,12 @@
     }
 
 #endif
+
+    // From http://forums.arm.com/index.php?/topic/13949-cycle-count-in-cortex-m3/
+    // via http://stackoverflow.com/questions/11530593/cycle-counter-on-arm-cortex-m4-or-m3/11530829#11530829
+    volatile uint32_t *DWT_CONTROL = (uint32_t *)0xe0001000;
+    volatile uint32_t *SCB_DEMCR = (uint32_t *)0xe000edfc;
+
+    *SCB_DEMCR = *SCB_DEMCR | 0x01000000;
+    *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter
 }
--- a/main.c	Mon Apr 01 19:45:38 2013 +1030
+++ b/main.c	Mon Apr 01 20:06:03 2013 +1030
@@ -350,25 +350,14 @@
 	} else if (!strcmp("assert", argv[0])) {
 	    assert(0 == 1);
 	} else if (!strcmp("cyc", argv[0])) {
-	    // From http://forums.arm.com/index.php?/topic/13949-cycle-count-in-cortex-m3/
-	    // via http://stackoverflow.com/questions/11530593/cycle-counter-on-arm-cortex-m4-or-m3/11530829#11530829
-	    uint32_t c1, c2, c;
-	    volatile uint32_t *DWT_CYCCNT = (uint32_t *)0xe0001004;
-	    volatile uint32_t *DWT_CONTROL = (uint32_t *)0xe0001000;
-	    volatile uint32_t *SCB_DEMCR = (uint32_t *)0xe000edfc;
+	    if (argc != 2) {
+		fputs("Incorrect number of arguments\r\n", stdout);
+		goto out;
+	    }
+    
+	    delay(atoi(argv[1]));
 
-	    *SCB_DEMCR = *SCB_DEMCR | 0x01000000;
-	    *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter
-	    c1 = *DWT_CYCCNT;
-	    for (volatile int i = 0; i < 1000; i++)
-		;
-	    c2 = *DWT_CYCCNT;
-	    if (c2 > c1)
-		c = c2 - c1;
-	    else {
-		c = (0xffffffff - c1) + c2;
-	    }
-	    printf("Took %ld cycles\r\n", c);
+	    fputs("Done\r\n", stdout);
 	} else if (!strcmp("zz", argv[0])) {
 	    NVIC_SystemReset();
 	} else {