浏览代码

blinky_test: A quick LED-blink test for valid medium-density
STM32F103 device.

Keir Fraser 5 年之前
父节点
当前提交
8cb833e52d
共有 5 个文件被更改,包括 141 次插入2 次删除
  1. 6 1
      Makefile
  2. 7 0
      blinky_test/Blinky.ld.S
  3. 6 0
      blinky_test/Makefile
  4. 122 0
      src/blinky.c
  5. 0 1
      src/console.c

+ 6 - 1
Makefile

@@ -5,7 +5,7 @@ export FW_MINOR := 3
 PROJ = Greaseweazle
 VER := v$(FW_MAJOR).$(FW_MINOR)
 
-SUBDIRS += src bootloader
+SUBDIRS += src bootloader blinky_test
 
 .PHONY: all clean dist mrproper flash start serial
 
@@ -23,11 +23,16 @@ clean:
 dist:
 	rm -rf $(PROJ)-*
 	mkdir -p $(PROJ)-$(VER)/scripts/greaseweazle
+	mkdir -p $(PROJ)-$(VER)/alt
 	$(MAKE) clean
 	$(MAKE) all
 	cp -a $(PROJ)-$(VER).hex $(PROJ)-$(VER)/
 	cp -a $(PROJ)-$(VER).upd $(PROJ)-$(VER)/
 	$(MAKE) clean
+	$(MAKE) -C blinky_test -f $(ROOT)/Rules.mk \
+		Blinky.elf Blinky.bin Blinky.hex
+	cp -a blinky_test/Blinky.hex $(PROJ)-$(VER)/alt/Blinky_Test-$(VER).hex
+	$(MAKE) clean
 	cp -a COPYING $(PROJ)-$(VER)/
 	cp -a README.md $(PROJ)-$(VER)/
 	cp -a gw.py $(PROJ)-$(VER)/

+ 7 - 0
blinky_test/Blinky.ld.S

@@ -0,0 +1,7 @@
+#define FLASH_BASE 0x08000000
+#define FLASH_LEN  64K
+
+#define RAM_BASE   0x20000000
+#define RAM_LEN    20K
+
+#include "../scripts/stm32f1.ld.S"

+ 6 - 0
blinky_test/Makefile

@@ -0,0 +1,6 @@
+RPATH = ../src
+
+OBJS += vectors.o
+OBJS += stm32f10x.o
+OBJS += blinky.o
+OBJS += util.o

+ 122 - 0
src/blinky.c

@@ -0,0 +1,122 @@
+/*
+ * blinky.c
+ * 
+ * LED blink test to validate STM32F103C8 chips. This test will find
+ * remarked and cloned low-density devices with less than 20kB RAM,
+ * and/or missing timer TIM4.
+ * 
+ * Tests are applied in the following order:
+ *  1. If TIM4 is missing, the onboard LED (pin B12 or C13) will not light.
+ *  2. If there is not at least 20kB SRAM, the onboard LED will remain light.
+ *  3. If TIM4 and >=20kB SRAM are both present, the LED will blink at 2Hz.
+ * 
+ * As the LED blinks, a character is written to USART1 at 9600 baud (8n1).
+ * 
+ * Written & released by Keir Fraser <keir.xen@gmail.com>
+ * 
+ * This is free and unencumbered software released into the public domain.
+ * See the file COPYING for more details, or visit <http://unlicense.org>.
+ */
+
+int EXC_reset(void) __attribute__((alias("main")));
+
+void IRQ_30(void) __attribute__((alias("IRQ_tim4")));
+#define IRQ_TIM4 30
+
+#ifndef NDEBUG
+/* Keep the linker happy. */
+int printk(const char *format, ...) { return 0; }
+#endif
+
+static void IRQ_tim4(void)
+{
+    static bool_t x;
+
+    /* Quiesce the IRQ source. */
+    tim4->sr = 0;
+
+    /* Blink the LED. */
+    gpio_write_pin(gpiob, 12, x);
+    gpio_write_pin(gpioc, 13, x);
+    x ^= 1;
+
+    /* Write to the serial line. */
+    usart1->dr = '.';
+}
+
+/* Pseudorandom LFSR. */
+static uint32_t srand = 0x87a2263c;
+static uint32_t rand(void)
+{
+    uint32_t x = srand;
+    x ^= x << 13;
+    x ^= x >> 17;
+    x ^= x << 5;
+    srand = x;
+    return x;
+}
+
+int main(void)
+{
+    /* Relocate DATA. Initialise BSS. */
+    if (_sdat != _ldat)
+        memcpy(_sdat, _ldat, _edat-_sdat);
+    memset(_sbss, 0, _ebss-_sbss);
+
+    stm32_init();
+
+    /* Configure USART1: 9600,8n1. */
+    rcc->apb2enr |= RCC_APB2ENR_USART1EN;
+    gpio_configure_pin(gpioa, 9, AFO_pushpull(_10MHz));
+    gpio_configure_pin(gpioa, 10, GPI_pull_up);
+    usart1->brr = SYSCLK / 9600;
+    usart1->cr1 = (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE);
+
+    /* Configure LED pin(s). LED is connected to VDD. */
+    gpio_configure_pin(gpiob, 12, GPO_opendrain(_2MHz, HIGH));
+    gpio_configure_pin(gpioc, 13, GPO_opendrain(_2MHz, HIGH));
+
+    /* (Attempt to) Configure TIM4 to overflow at 2Hz. */
+    tim4->psc = sysclk_us(100)-1;
+    tim4->arr = 5000-1;
+    tim4->dier = TIM_DIER_UIE;
+    tim4->cr2 = 0;
+    tim4->cr1 = TIM_CR1_URS | TIM_CR1_CEN;
+
+    /* Enable TIM4 IRQ, to be triggered at 2Hz. */
+    IRQx_set_prio(IRQ_TIM4, TIMER_IRQ_PRI);
+    IRQx_clear_pending(IRQ_TIM4);
+    IRQx_enable(IRQ_TIM4);
+
+    /* Endlessly test SRAM by filling with pseudorandom junk and then 
+     * testing the values read back okay. */
+    for (;;) {
+        uint32_t *p = (uint32_t *)_ebss, sr = srand;
+        while (p < (uint32_t *)(0x20000000 + 20*1024))
+            *p++ = rand();
+        srand = sr;
+        p = (uint32_t *)_ebss;
+        while (p < (uint32_t *)(0x20000000 + 20*1024))
+            if (*p++ != rand())
+                goto ram_fail;
+    }
+
+ram_fail:
+    /* On SRAM failure we light the LED(s) and hang. */
+    IRQ_global_disable();
+    gpio_write_pin(gpiob, 12, LOW);
+    gpio_write_pin(gpioc, 13, LOW);
+    for (;;) ;
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "Linux"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

+ 0 - 1
src/console.c

@@ -74,7 +74,6 @@ void console_init(void)
     /* BAUD, 8n1. */
     usart1->brr = SYSCLK / BAUD;
     usart1->cr1 = (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE);
-    usart1->cr3 = USART_CR3_DMAT;
 }
 
 /* Debug helper: if we get stuck somewhere, calling this beforehand will cause