]> mj.ucw.cz Git - home-hw.git/commitdiff
ocm3 test: debugging utilities
authorMartin Mares <mj@ucw.cz>
Sun, 30 Jun 2019 16:59:54 +0000 (18:59 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 30 Jun 2019 16:59:54 +0000 (18:59 +0200)
test-opencm3/Makefile
test-opencm3/test.c
test-opencm3/util-debug.c [new file with mode: 0644]
test-opencm3/util.h [new file with mode: 0644]

index 11acf15ddda38a83158b82742824f264ef08bea0..afae34600f9a3894d27610d661cbe945a589ceda 100644 (file)
@@ -1,5 +1,5 @@
 BINARY=test
-OBJS=test.o
+OBJS=test.o util-debug.o
 
 OPENCM3_DIR=/home/mj/stm/libopencm3
 DEVICE=stm32f103x8
index a38394cb2b1d7f255d16fed07665dcd2cee8459d..f02195d232f84c1e31e8d33e5ceb5236efdfabba 100644 (file)
@@ -1,20 +1,18 @@
-#include <stdint.h>
+#include "util.h"
 
 #include <libopencm3/cm3/nvic.h>
 #include <libopencm3/cm3/systick.h>
 #include <libopencm3/stm32/rcc.h>
 #include <libopencm3/stm32/gpio.h>
-
-typedef uint8_t byte;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef unsigned int uint;
+#include <libopencm3/stm32/usart.h>
 
 static void clock_setup(void)
 {
        rcc_clock_setup_in_hse_8mhz_out_72mhz();
 
+       rcc_periph_clock_enable(RCC_GPIOA);
        rcc_periph_clock_enable(RCC_GPIOC);
+       rcc_periph_clock_enable(RCC_USART1);
 }
 
 static void gpio_setup(void)
@@ -43,16 +41,34 @@ static void delay_ms(uint ms)
                ;
 }
 
+static void usart_setup(void)
+{
+               gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
+
+               usart_set_baudrate(USART1, 115200);
+               usart_set_databits(USART1, 8);
+               usart_set_stopbits(USART1, USART_STOPBITS_1);
+               usart_set_mode(USART1, USART_MODE_TX);
+               usart_set_parity(USART1, USART_PARITY_NONE);
+               usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
+
+               usart_enable(USART1);
+}
+
 int main(void)
 {
        clock_setup();
        gpio_setup();
        tick_setup();
+       usart_setup();
 
-       /* Blink the LED (PC13) on the board. */
+       int cc = 32;
        for (;;) {
-               gpio_toggle(GPIOC, GPIO13);     /* LED on/off */
-               delay_ms(1000);
+               gpio_toggle(GPIOC, GPIO13);
+               debug_putc(cc);
+               cc++;
+               if (cc >= 126) cc = 32;
+               delay_ms(100);
        }
 
        return 0;
diff --git a/test-opencm3/util-debug.c b/test-opencm3/util-debug.c
new file mode 100644 (file)
index 0000000..a1698cf
--- /dev/null
@@ -0,0 +1,166 @@
+#include "util.h"
+
+#include <libopencm3/stm32/usart.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef DEBUG_SEMIHOSTING
+
+void semi_put_char(char c)
+{
+       // This is tricky, we need to work around GCC bugs
+       volatile char cc = c;
+       asm volatile (
+               "mov r0, #0x03\n"   /* SYS_WRITEC */
+               "mov r1, %[msg]\n"
+               "bkpt #0xAB\n"
+               :
+               : [msg] "r" (&cc)
+               : "r0", "r1"
+       );
+}
+
+void semi_write_string(char *c)
+{
+       asm volatile (
+               "mov r0, #0x04\n"   /* SYS_WRITE0 */
+               "mov r1, %[msg]\n"
+               "bkpt #0xAB\n"
+               :
+               : [msg] "r" (c)
+               : "r0", "r1"
+       );
+}
+
+#endif
+
+void debug_putc(int c)
+{
+#ifdef DEBUG_SEMIHOSTING
+       static char debug_buf[128];
+       static int debug_i;
+       debug_buf[debug_i++] = c;
+       if (c == '\n' || debug_i >= sizeof(debug_buf) - 1) {
+               debug_buf[debug_i] = 0;
+               semi_write_string(debug_buf);
+               debug_i = 0;
+       }
+#endif
+#ifdef DEBUG_USART
+       if (c == '\n')
+               usart_send_blocking(USART1, '\r');
+       usart_send_blocking(USART1, c);
+#endif
+}
+
+void debug_puts(const char *s)
+{
+       while (*s)
+               debug_putc(*s++);
+}
+
+enum printf_flags {
+       PF_ZERO_PAD = 1,
+       PF_SIGNED = 2,
+       PF_NEGATIVE = 4,
+       PF_UPPERCASE = 8,
+       PF_LEFT = 16,
+};
+
+static void printf_string(const char *s, uint width, uint flags)
+{
+       uint len = strlen(s);
+       uint pad = (len < width) ? width - len : 0;
+       char pad_char = (flags & PF_ZERO_PAD) ? '0' : ' ';
+
+       if (flags & PF_LEFT)
+               debug_puts(s);
+       while (pad--)
+               debug_putc(pad_char);
+       if (!(flags & PF_LEFT))
+               debug_puts(s);
+}
+
+static void printf_number(uint i, uint width, uint flags, uint base)
+{
+       char buf[16];
+       char *w = buf + sizeof(buf);
+
+       if (flags & PF_SIGNED) {
+               if ((int) i < 0) {
+                       i = - (int) i;
+                       flags |= PF_NEGATIVE;
+               }
+       }
+
+       *--w = 0;
+       do {
+               uint digit = i % base;
+               if (digit < 10)
+                       *--w = '0' + digit;
+               else
+                       *--w = ((flags & PF_UPPERCASE) ? 'A' : 'a') + digit - 10;
+               i /= base;
+       }
+       while (i);
+
+       if (flags & PF_NEGATIVE)
+               *--w = '-';
+
+       printf_string(w, width, flags);
+}
+
+void debug_printf(const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+
+       while (*fmt) {
+               int c = *fmt++;
+               if (c != '%') {
+                       debug_putc(c);
+                       continue;
+               }
+
+               uint width = 0;
+               uint flags = 0;
+
+               if (*fmt == '-') {
+                       fmt++;
+                       flags |= PF_LEFT;
+               }
+
+               if (*fmt == '0') {
+                       fmt++;
+                       flags |= PF_ZERO_PAD;
+               }
+
+               while (*fmt >= '0' && *fmt <= '9')
+                       width = 10*width + *fmt++ - '0';
+
+               c = *fmt++;
+               switch (c) {
+                       case 'd':
+                               printf_number(va_arg(args, int), width, flags | PF_SIGNED, 10);
+                               break;
+                       case 'u':
+                               printf_number(va_arg(args, int), width, flags, 10);
+                               break;
+                       case 'X':
+                               flags |= PF_UPPERCASE;
+                               // fall-thru
+                       case 'x':
+                               printf_number(va_arg(args, int), width, flags, 16);
+                               break;
+                       case 's':
+                               printf_string(va_arg(args, char *), width, flags);
+                               break;
+                       default:
+                               debug_putc(c);
+                               continue;
+               }
+       }
+
+       va_end(args);
+}
diff --git a/test-opencm3/util.h b/test-opencm3/util.h
new file mode 100644 (file)
index 0000000..6d8c9cc
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef unsigned int uint;
+typedef uint8_t byte;
+typedef uint16_t u16;
+typedef int16_t s16;
+typedef uint32_t u32;
+typedef int32_t s32;
+
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+static inline uint get_u16_le(byte *p)
+{
+       return (p[1] << 8) | p[0];
+}
+
+static inline uint get_u16_be(byte *p)
+{
+       return (p[0] << 8) | p[1];
+}
+
+static inline uint get_u32_le(byte *p)
+{
+       return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
+}
+
+static inline uint get_u32_be(byte *p)
+{
+       return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+}
+
+static inline void put_u16_le(byte *p, u16 x)
+{
+       p[0] = x;
+       p[1] = x >> 8;
+}
+
+static inline void put_u16_be(byte *p, u16 x)
+{
+       p[0] = x >> 8;
+       p[1] = x;
+}
+
+static inline void put_u32_be(byte *p, u32 x)
+{
+       p[0] = x >> 24;
+       p[1] = (x >> 16) & 0xff;
+       p[2] = (x >> 8) & 0xff;
+       p[3] = x & 0xff;
+}
+
+static inline void put_u32_le(byte *p, u32 x)
+{
+       p[3] = x >> 24;
+       p[2] = (x >> 16) & 0xff;
+       p[1] = (x >> 8) & 0xff;
+       p[0] = x & 0xff;
+}
+
+// debug.c
+
+// #define DEBUG_SEMIHOSTING
+#define DEBUG_USART USART1
+
+void debug_printf(const char *fmt, ...);
+void debug_puts(const char *s);
+void debug_putc(int c);