瀏覽代碼

Substantially simplify debug logging to serial

Keir Fraser 5 年之前
父節點
當前提交
0bf9567c22
共有 4 個文件被更改,包括 17 次插入85 次删除
  1. 6 0
      inc/intrinsics.h
  2. 0 4
      inc/util.h
  3. 10 80
      src/console.c
  4. 1 1
      src/stm32f10x.c

+ 6 - 0
inc/intrinsics.h

@@ -59,6 +59,12 @@ struct exception_frame {
 #define IRQ_global_disable() asm volatile ("cpsid i" ::: "memory")
 #define IRQ_global_enable() asm volatile ("cpsie i" ::: "memory")
 
+#define IRQ_global_save(flags) ({               \
+    (flags) = read_special(primask) & 1;        \
+    IRQ_global_disable(); })
+#define IRQ_global_restore(flags) ({            \
+    if (flags == 0) IRQ_global_enable(); })
+
 /* Save/restore IRQ priority levels. 
  * NB. IRQ disable via MSR is self-synchronising. I have confirmed this on 
  * Cortex-M3: any pending IRQs are handled before they are disabled by 

+ 0 - 4
inc/util.h

@@ -85,7 +85,6 @@ extern uint8_t board_id;
 
 /* Serial console control */
 void console_init(void);
-void console_sync(void);
 void console_crash_on_input(void);
 
 /* Serial console output */
@@ -97,7 +96,6 @@ int printk(const char *format, ...)
 #else /* NDEBUG */
 
 #define console_init() ((void)0)
-#define console_sync() IRQ_global_disable()
 #define console_crash_on_input() ((void)0)
 static inline int vprintk(const char *format, va_list ap) { return 0; }
 static inline int printk(const char *format, ...) { return 0; }
@@ -130,8 +128,6 @@ void EXC_unused(void);
 #define RESET_IRQ_PRI         0
 #define INDEX_IRQ_PRI         2
 #define TIMER_IRQ_PRI         4
-#define USB_IRQ_PRI          14
-#define CONSOLE_IRQ_PRI      15
 
 /*
  * Local variables:

+ 10 - 80
src/console.c

@@ -11,88 +11,41 @@
 
 #define BAUD 3000000 /* 3Mbaud */
 
-#define DMA1_CH4_IRQ 14
-void IRQ_14(void) __attribute__((alias("IRQ_dma1_ch4_tc")));
-
 #define USART1_IRQ 37
 
-/* We stage serial output in a ring buffer. DMA occurs from the ring buffer;
- * the consumer index being updated each time a DMA sequence completes. */
-static char ring[2048];
-#define MASK(x) ((x)&(sizeof(ring)-1))
-static unsigned int cons, prod, dma_sz;
-
-/* The console can be set into synchronous mode in which case DMA is disabled 
- * and the transmit-empty flag is polled manually for each byte. */
-static bool_t sync_console;
-
-static void kick_tx(void)
+static void ser_putc(uint8_t c)
 {
-    if (sync_console) {
-
-        while (cons != prod) {
-            while (!(usart1->sr & USART_SR_TXE))
-                cpu_relax();
-            usart1->dr = ring[MASK(cons++)];
-        }
-
-    } else if (!dma_sz && (cons != prod)) {
-
-        dma_sz = min(MASK(prod-cons), sizeof(ring)-MASK(cons));
-        dma1->ch4.cmar = (uint32_t)(unsigned long)&ring[MASK(cons)];
-        dma1->ch4.cndtr = dma_sz;
-        dma1->ch4.ccr = (DMA_CCR_MSIZE_8BIT |
-                         /* The manual doesn't allow byte accesses to usart. */
-                         DMA_CCR_PSIZE_16BIT |
-                         DMA_CCR_MINC |
-                         DMA_CCR_DIR_M2P |
-                         DMA_CCR_TCIE |
-                         DMA_CCR_EN);
-
-    }
-}
-
-static void IRQ_dma1_ch4_tc(void)
-{
-    /* Clear the DMA controller. */
-    dma1->ch4.ccr = 0;
-    dma1->ifcr = DMA_IFCR_CGIF(4);
-
-    /* Update ring state. */
-    cons += dma_sz;
-    dma_sz = 0;
-
-    /* Kick off more transmit activity. */
-    kick_tx();
+    while (!(usart1->sr & USART_SR_TXE))
+        cpu_relax();
+    usart1->dr = c;
 }
 
 int vprintk(const char *format, va_list ap)
 {
     static char str[128];
+    unsigned int flags;
     char *p, c;
     int n;
 
-    IRQ_global_disable();
+    IRQ_global_save(flags);
 
     n = vsnprintf(str, sizeof(str), format, ap);
 
     p = str;
-    while (((c = *p++) != '\0') && ((prod-cons) != (sizeof(ring) - 1))) {
+    while ((c = *p++) != '\0') {
         switch (c) {
         case '\r': /* CR: ignore as we generate our own CR/LF */
             break;
         case '\n': /* LF: convert to CR/LF (usual terminal behaviour) */
-            ring[MASK(prod++)] = '\r';
+            ser_putc('\r');
             /* fall through */
         default:
-            ring[MASK(prod++)] = c;
+            ser_putc(c);
             break;
         }
     }
 
-    kick_tx();
-
-    IRQ_global_enable();
+    IRQ_global_restore(flags);
 
     return n;
 }
@@ -109,23 +62,6 @@ int printk(const char *format, ...)
     return n;
 }
 
-void console_sync(void)
-{
-    if (sync_console)
-        return;
-
-    IRQ_global_disable();
-
-    sync_console = TRUE;
-
-    /* Wait for DMA completion and then kick off synchronous mode. */
-    while (dma1->ch4.cndtr)
-        cpu_relax();
-    IRQ_dma1_ch4_tc();
-
-    /* Leave IRQs globally disabled. */
-}
-
 void console_init(void)
 {
     /* Turn on the clocks. */
@@ -139,12 +75,6 @@ void console_init(void)
     usart1->brr = SYSCLK / BAUD;
     usart1->cr1 = (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE);
     usart1->cr3 = USART_CR3_DMAT;
-
-    /* Initialise DMA1 channel 4 and its completion interrupt. */
-    dma1->ch4.cpar = (uint32_t)(unsigned long)&usart1->dr;
-    dma1->ifcr = DMA_IFCR_CGIF(4);
-    IRQx_set_prio(DMA1_CH4_IRQ, CONSOLE_IRQ_PRI);
-    IRQx_enable(DMA1_CH4_IRQ);
 }
 
 /* Debug helper: if we get stuck somewhere, calling this beforehand will cause 

+ 1 - 1
src/stm32f10x.c

@@ -191,7 +191,7 @@ void gpio_configure_pin(GPIO gpio, unsigned int pin, unsigned int mode)
 
 void system_reset(void)
 {
-    console_sync();
+    IRQ_global_disable();
     printk("Resetting...\n");
     /* Wait for serial console TX to idle. */
     while (!(usart1->sr & USART_SR_TXE) || !(usart1->sr & USART_SR_TC))