summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2018-02-04 20:35:01 +0100
committerRichard Braun <rbraun@sceen.net>2018-02-04 20:44:43 +0100
commitfe159704128341b9a46c60cc14f80162f9d6d4dc (patch)
treeffbf1ed9fcb9a9943bf3e5e23c26ee80dbf83c2a
parentda04bfd0e49086f03f54d3f6ecf22a6455e228c4 (diff)
Port to OLIMEX-STM32-H407
-rw-r--r--Makefile8
-rw-r--r--openocd.cfg5
-rw-r--r--src/boot.c6
-rw-r--r--src/cpu.h4
-rw-r--r--src/flash.c50
-rw-r--r--src/flash.h31
-rw-r--r--src/gpio.c89
-rw-r--r--src/gpio.h31
-rw-r--r--src/kernel.lds.S17
-rw-r--r--src/rcc.c205
-rw-r--r--src/rcc.h42
-rw-r--r--src/systick.c14
-rw-r--r--src/uart.c48
13 files changed, 516 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 44ff058..5b13655 100644
--- a/Makefile
+++ b/Makefile
@@ -85,9 +85,10 @@ X1_CFLAGS += -Os
# source locations.
X1_CFLAGS += -g
-X1_CFLAGS += -mcpu=cortex-m3
+X1_CFLAGS += -mcpu=cortex-m4
X1_CFLAGS += -mthumb
+X1_CFLAGS += -fno-PIE
X1_CFLAGS += -fsigned-char
# Target a free standing environment as defined by C99.
@@ -178,11 +179,14 @@ SOURCES = \
src/condvar.c \
src/cpu.c \
src/cpu_asm.S \
+ src/flash.c \
+ src/gpio.c \
src/main.c \
src/mem.c \
src/mutex.c \
src/nvic.c \
src/panic.c \
+ src/rcc.c \
src/stdio.c \
src/string.c \
src/sw.c \
@@ -199,7 +203,7 @@ SOURCES += \
OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SOURCES)))
$(BINARY): $(LDS) $(OBJECTS)
- $(CC) -o $@ $(X1_LDFLAGS) -Xlinker -T $(LDS) $(OBJECTS) $(LIBS)
+ $(CC) $(X1_CPPFLAGS) $(X1_CFLAGS) -o $@ $(X1_LDFLAGS) -Xlinker -T $(LDS) $(OBJECTS) $(LIBS)
%.o: %.c
$(CC) $(X1_CPPFLAGS) $(X1_CFLAGS) -c -o $@ $<
diff --git a/openocd.cfg b/openocd.cfg
new file mode 100644
index 0000000..fa08472
--- /dev/null
+++ b/openocd.cfg
@@ -0,0 +1,5 @@
+source [find interface/ftdi/flyswatter2.cfg]
+source [find target/stm32f4x.cfg]
+
+reset_config trst_and_srst srst_nogate
+init
diff --git a/src/boot.c b/src/boot.c
index f17349c..ae9cfce 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -28,7 +28,10 @@
#include "boot.h"
#include "cpu.h"
+#include "flash.h"
+#include "gpio.h"
#include "main.h"
+#include "rcc.h"
extern char _lma_data_addr;
extern char _data_start;
@@ -51,5 +54,8 @@ boot_main(void)
{
cpu_intr_disable();
boot_copy_data();
+ flash_setup();
+ rcc_setup();
+ gpio_setup();
main();
}
diff --git a/src/cpu.h b/src/cpu.h
index 69d7921..dea58d9 100644
--- a/src/cpu.h
+++ b/src/cpu.h
@@ -31,6 +31,8 @@
#include <lib/macros.h>
+#define CPU_FREQ 168000000
+
#define CPU_STACK_ALIGN 8
#define CPU_EXC_STACK_SIZE 4096
@@ -165,7 +167,9 @@ cpu_intr_enabled(void)
static inline void
cpu_idle(void)
{
+#if LOW_POWER
asm volatile("wfi" : : : "memory");
+#endif
}
static inline void
diff --git a/src/flash.c b/src/flash.c
new file mode 100644
index 0000000..eaff0b2
--- /dev/null
+++ b/src/flash.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018 Richard Braun.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "flash.h"
+
+#define FLASH_BASE_ADDR 0x40023c00
+
+struct flash_regs {
+ uint32_t acr;
+ uint32_t keyr;
+ uint32_t optkeyr;
+ uint32_t sr;
+ uint32_t cr;
+ uint32_t optcr;
+};
+
+static volatile struct flash_regs *flash_regs = (void *)FLASH_BASE_ADDR;
+
+void
+flash_setup(void)
+{
+ /*
+ * See 3.5.1 Relation between CPU clock frequency
+ * and Flash memory read time.
+ *
+ * TODO Prefect and caches.
+ */
+ flash_regs->acr |= 5;
+}
diff --git a/src/flash.h b/src/flash.h
new file mode 100644
index 0000000..9fb3220
--- /dev/null
+++ b/src/flash.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018 Richard Braun.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _FLASH_H
+#define _FLASH_h
+
+/*
+ * Initialize the flash module.
+ */
+void flash_setup(void);
+
+#endif /* _FLASH_H */
diff --git a/src/gpio.c b/src/gpio.c
new file mode 100644
index 0000000..fa368c7
--- /dev/null
+++ b/src/gpio.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018 Richard Braun.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "gpio.h"
+
+#define GPIO_C_BASE_ADDR 0x40020800
+
+struct gpio_regs {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t idr;
+ uint32_t odr;
+ uint32_t bsrr;
+ uint32_t lckr;
+ uint32_t afrl;
+ uint32_t afrh;
+};
+
+static volatile struct gpio_regs *gpio_c_regs = (void *)GPIO_C_BASE_ADDR;
+
+static void
+gpio_compute_location(unsigned int io, unsigned int nr_bits,
+ uint32_t *shift, uint32_t *mask)
+{
+ *shift = (io * nr_bits);
+ *mask = ((1 << nr_bits) - 1) << *shift;
+}
+
+static void
+gpio_set(volatile struct gpio_regs *regs, unsigned int io,
+ uint32_t af, uint32_t speed, uint32_t pupd)
+{
+ uint32_t shift, mask, value;
+ volatile uint32_t *reg;
+
+ gpio_compute_location(io, 2, &shift, &mask);
+ value = (af == 0) ? 1 : 2;
+ regs->moder &= ~mask;
+ regs->moder |= value << shift;
+
+ gpio_compute_location(io, 2, &shift, &mask);
+ regs->ospeedr &= ~mask;
+ regs->ospeedr |= speed << shift;
+
+ gpio_compute_location(io, 2, &shift, &mask);
+ regs->pupdr &= ~mask;
+ regs->pupdr |= pupd << shift;
+
+ if (io < 8) {
+ reg = &regs->afrl;
+ } else {
+ reg = &regs->afrh;
+ io -= 8;
+ }
+
+ gpio_compute_location(io, 4, &shift, &mask);
+ *reg &= ~mask;
+ *reg |= af << shift;
+}
+
+void
+gpio_setup(void)
+{
+ gpio_set(gpio_c_regs, 6, 8, 1, 1);
+ gpio_set(gpio_c_regs, 7, 8, 1, 1);
+}
diff --git a/src/gpio.h b/src/gpio.h
new file mode 100644
index 0000000..4330b9c
--- /dev/null
+++ b/src/gpio.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018 Richard Braun.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _GPIO_H
+#define _GPIO_h
+
+/*
+ * Initialize the gpio module.
+ */
+void gpio_setup(void);
+
+#endif /* _GPIO_H */
diff --git a/src/kernel.lds.S b/src/kernel.lds.S
index 3872a87..219505e 100644
--- a/src/kernel.lds.S
+++ b/src/kernel.lds.S
@@ -29,8 +29,9 @@ ENTRY(boot_start)
*/
MEMORY
{
- FLASH : ORIGIN = 0x0, LENGTH = 0x100000
- RAM : ORIGIN = 0x20000000, LENGTH = 0x20000
+ FLASH_ALIAS : ORIGIN = 0x00000000, LENGTH = 0x100000
+ FLASH : ORIGIN = 0x08000000, LENGTH = 0x100000
+ RAM : ORIGIN = 0x20000000, LENGTH = 0x1C000
}
/*
@@ -54,6 +55,12 @@ PHDRS
vectors PT_LOAD FLAGS(5);
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
+
+ /*
+ * XXX Currently required to avoid warning, probably because of
+ * different alignments of .data and .bss.
+ */
+ bss PT_LOAD FLAGS(6);
}
/*
@@ -87,12 +94,12 @@ SECTIONS
{
.vectors : {
*(.vectors)
- } > FLASH : vectors
+ } > FLASH_ALIAS AT > FLASH : vectors
.text : {
*(.text*)
*(.rodata*)
- } > FLASH : text
+ } > FLASH_ALIAS AT > FLASH : text
_lma_data_addr = .;
@@ -106,7 +113,7 @@ SECTIONS
_bss_start = .;
*(.bss)
_bss_end = .;
- } > RAM AT > FLASH : data
+ } > RAM AT > FLASH : bss
/*
* The .eh_frame section is used by DWARF tools to unwind the stack,
diff --git a/src/rcc.c b/src/rcc.c
new file mode 100644
index 0000000..07c48b8
--- /dev/null
+++ b/src/rcc.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2018 Richard Braun.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <lib/macros.h>
+
+#include "rcc.h"
+
+#define RCC_BASE_ADDR 0x40023800
+
+#define RCC_CR_HSION 0x00000001
+#define RCC_CR_HSEON 0x00010000
+#define RCC_CR_HSERDY 0x00020000
+#define RCC_CR_PLLON 0x01000000
+#define RCC_CR_PLLRDY 0x02000000
+
+#define RCC_PLLCFGR_PLLM_MASK 0x0000003f
+#define RCC_PLLCFGR_PLLN_MASK 0x00007fc0
+#define RCC_PLLCFGR_PLLN_SHIFT 6
+#define RCC_PLLCFGR_PLLP_MASK 0x00030000
+#define RCC_PLLCFGR_PLLP_SHIFT 16
+#define RCC_PLLCFGR_PLLSRC_HSE 0x00400000
+#define RCC_PLLCFGR_PLLQ_MASK 0x0f000000
+#define RCC_PLLCFGR_PLLQ_SHIFT 24
+
+#define RCC_CFGR_SW_PLL 0x00000002
+#define RCC_CFGR_SW_MASK 0x00000003
+#define RCC_CFGR_SWS_PLL 0x00000008
+#define RCC_CFGR_SWS_MASK 0x0000000c
+#define RCC_CFGR_PPRE1_MASK 0x00001c00
+#define RCC_CFGR_PPRE1_SHIFT 10
+#define RCC_CFGR_PPRE2_MASK 0x0000e000
+#define RCC_CFGR_PPRE2_SHIFT 13
+
+#define RCC_AHB1ENR_GPIOCEN 0x00000004
+
+#define RCC_APB2RSTR_USART6RST 0x00000020
+
+#define RCC_APB2ENR_USART6EN 0x00000020
+
+struct rcc_regs {
+ uint32_t cr;
+ uint32_t pllcfgr;
+ uint32_t cfgr;
+ uint32_t cir;
+
+ uint32_t ahb1rstr;
+ uint32_t ahb2rstr;
+ uint32_t ahb3rstr;
+ uint32_t _reserved0;
+ uint32_t apb1rstr;
+ uint32_t apb2rstr;
+ uint32_t _reserved1;
+ uint32_t _reserved2;
+
+ uint32_t ahb1enr;
+ uint32_t ahb2enr;
+ uint32_t ahb3enr;
+ uint32_t _reserved3;
+ uint32_t apb1enr;
+ uint32_t apb2enr;
+ uint32_t _reserved4;
+ uint32_t _reserved5;
+
+ uint32_t ahb1lpenr;
+ uint32_t ahb2lpenr;
+ uint32_t ahb3lpenr;
+ uint32_t _reserved6;
+ uint32_t apb1lpenr;
+ uint32_t apb2lpenr;
+ uint32_t _reserved7;
+ uint32_t _reserved8;
+
+ uint32_t bdcr;
+ uint32_t csr;
+ uint32_t _reserved9;
+ uint32_t _reserved10;
+ uint32_t sscgr;
+ uint32_t plli2scfgr;
+};
+
+static volatile struct rcc_regs *rcc_regs = (void *)RCC_BASE_ADDR;
+
+static void
+rcc_setup_hse(volatile struct rcc_regs *regs)
+{
+ regs->cr |= RCC_CR_HSEON;
+
+ while (!(regs->cr & RCC_CR_HSERDY));
+}
+
+static void
+rcc_setup_pll(volatile struct rcc_regs *regs)
+{
+ uint32_t reg, value;
+
+ reg = regs->pllcfgr;
+
+ reg &= ~RCC_PLLCFGR_PLLM_MASK;
+ reg |= RCC_FREQ_HSE / RCC_FREQ_VCO_IN;
+
+ reg &= ~RCC_PLLCFGR_PLLN_MASK;
+ reg |= (RCC_FREQ_VCO_OUT / RCC_FREQ_VCO_IN) << RCC_PLLCFGR_PLLN_SHIFT;
+
+ value = ((RCC_FREQ_VCO_OUT / RCC_FREQ_PLLP) / 2) - 1;
+
+ reg &= ~RCC_PLLCFGR_PLLP_MASK;
+ reg |= value << RCC_PLLCFGR_PLLP_SHIFT;
+
+ reg &= ~RCC_PLLCFGR_PLLQ_MASK;
+ reg |= (RCC_FREQ_VCO_OUT / RCC_FREQ_PLLQ) << RCC_PLLCFGR_PLLQ_SHIFT;
+
+ reg |= RCC_PLLCFGR_PLLSRC_HSE;
+
+ regs->pllcfgr = reg;
+
+ regs->cr |= RCC_CR_PLLON;
+
+ while (!(regs->cr & RCC_CR_PLLRDY));
+}
+
+static void
+rcc_setup_ahb1(volatile struct rcc_regs *regs)
+{
+ regs->ahb1enr |= RCC_AHB1ENR_GPIOCEN;
+}
+
+static void
+rcc_setup_apb1(volatile struct rcc_regs *regs)
+{
+ uint32_t value;
+
+ value = RCC_FREQ_SYSCLK / RCC_FREQ_APB1;
+ assert(ISP2(value));
+ value = 0x4 | (__builtin_ffs(value) - 2);
+
+ regs->cfgr &= ~RCC_CFGR_PPRE1_MASK;
+ regs->cfgr |= value << RCC_CFGR_PPRE1_SHIFT;
+}
+
+static void
+rcc_setup_apb2(volatile struct rcc_regs *regs)
+{
+ uint32_t value;
+
+ value = RCC_FREQ_SYSCLK / RCC_FREQ_APB2;
+ assert(ISP2(value));
+ value = 0x4 | (__builtin_ffs(value) - 2);
+
+ regs->cfgr &= ~RCC_CFGR_PPRE2_MASK;
+ regs->cfgr |= value << RCC_CFGR_PPRE2_SHIFT;
+
+ regs->apb2enr |= RCC_APB2ENR_USART6EN;
+
+ regs->apb2rstr |= RCC_APB2RSTR_USART6RST;
+ regs->apb2rstr &= ~RCC_APB2RSTR_USART6RST;
+}
+
+static void
+rcc_select_sysclk(volatile struct rcc_regs *regs)
+{
+ regs->cfgr &= ~RCC_CFGR_SW_MASK;
+ regs->cfgr |= RCC_CFGR_SW_PLL;
+
+ while ((regs->cfgr & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL);
+}
+
+static void
+rcc_disable_hsi(volatile struct rcc_regs *regs)
+{
+ regs->cr &= ~RCC_CR_HSION;
+}
+
+void
+rcc_setup(void)
+{
+ rcc_setup_hse(rcc_regs);
+ rcc_setup_pll(rcc_regs);
+ rcc_setup_ahb1(rcc_regs);
+ rcc_setup_apb1(rcc_regs);
+ rcc_setup_apb2(rcc_regs);
+ rcc_select_sysclk(rcc_regs);
+ rcc_disable_hsi(rcc_regs);
+}
diff --git a/src/rcc.h b/src/rcc.h
new file mode 100644
index 0000000..5a01b97
--- /dev/null
+++ b/src/rcc.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018 Richard Braun.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _RCC_H
+#define _RCC_H
+
+#include "cpu.h"
+
+#define RCC_FREQ_SYSCLK CPU_FREQ
+#define RCC_FREQ_HSE 12000000
+#define RCC_FREQ_VCO_IN 2000000
+#define RCC_FREQ_VCO_OUT 336000000
+#define RCC_FREQ_PLLP RCC_FREQ_SYSCLK
+#define RCC_FREQ_PLLQ 48000000
+#define RCC_FREQ_APB1 42000000
+#define RCC_FREQ_APB2 84000000
+
+/*
+ * Initialize the rcc module.
+ */
+void rcc_setup(void);
+
+#endif /* _RCC_H */
diff --git a/src/systick.c b/src/systick.c
index 1307d98..f2d4924 100644
--- a/src/systick.c
+++ b/src/systick.c
@@ -22,14 +22,15 @@
#include <stdint.h>
+#include "cpu.h"
#include "panic.h"
#include "systick.h"
#include "thread.h"
#define SYSTICK_BASE_ADDR 0xe000e010
-#define SYSTICK_CSR_ENABLE 0x1
-#define SYSTICK_CSR_TICKINT 0x2
+#define SYSTICK_CSR_ENABLE 0x1
+#define SYSTICK_CSR_TICKINT 0x2
#define SYSTICK_CALIB_NOREF 0x80000000
#define SYSTICK_CALIB_SKEW 0x40000000
@@ -51,9 +52,7 @@ systick_check_calib(void)
calib = systick_regs->calib;
- if ((calib & SYSTICK_CALIB_NOREF)
- || (calib & SYSTICK_CALIB_SKEW)
- || (calib & SYSTICK_CALIB_TENMS_MASK) == 0) {
+ if (calib & SYSTICK_CALIB_NOREF) {
panic("systick: unusable");
}
}
@@ -61,12 +60,11 @@ systick_check_calib(void)
void
systick_setup(void)
{
- uint32_t tenms, counter;
+ uint32_t counter;
systick_check_calib();
- tenms = systick_regs->calib & SYSTICK_CALIB_TENMS_MASK;
- counter = (tenms * 100) / THREAD_SCHED_FREQ;
+ counter = (CPU_FREQ / 8) / THREAD_SCHED_FREQ;
systick_regs->rvr = counter;
systick_regs->cvr = 0;
systick_regs->csr = (SYSTICK_CSR_TICKINT | SYSTICK_CSR_ENABLE);
diff --git a/src/uart.c b/src/uart.c
index 456c6da..c61a1c3 100644
--- a/src/uart.c
+++ b/src/uart.c
@@ -31,11 +31,15 @@
#include <lib/macros.h>
#include "cpu.h"
+#include "rcc.h"
#include "uart.h"
#include "thread.h"
-#define UART_USART1_ADDR 0x40011000
-#define UART_USART1_IRQ 37
+#define UART_BAUD_RATE 115200
+#define UART_CLK RCC_FREQ_APB2
+
+#define UART_USART6_ADDR 0x40011400
+#define UART_USART6_IRQ 71
#define UART_SR_RXNE 0x00000020
#define UART_SR_TXE 0x00000080
@@ -45,6 +49,10 @@
#define UART_CR1_RXNEIE 0x00000020
#define UART_CR1_UE 0x00002000
+#define UART_BRR_FRACTION_MASK 0x0000000f
+#define UART_BRR_MANTISSA_MASK 0x0000fff0
+#define UART_BRR_MANTISSA_SHIFT 4
+
#define UART_BUFFER_SIZE 16
#if !ISP2(UART_BUFFER_SIZE)
@@ -61,7 +69,7 @@ struct uart_regs {
uint32_t gtpr;
};
-static volatile struct uart_regs *uart_usart1_regs;
+static volatile struct uart_regs *uart_regs = (void *)UART_USART6_ADDR;
/*
* Data shared between threads and the interrupt handler.
@@ -84,14 +92,14 @@ uart_irq_handler(void *arg)
spurious = true;
for (;;) {
- reg = uart_usart1_regs->sr;
+ reg = uart_regs->sr;
if (!(reg & UART_SR_RXNE)) {
break;
}
spurious = false;
- reg = uart_usart1_regs->dr;
+ reg = uart_regs->dr;
error = cbuf_pushb(&uart_cbuf, (uint8_t)reg, false);
if (error) {
@@ -108,42 +116,44 @@ uart_irq_handler(void *arg)
void
uart_setup(void)
{
+ uint32_t divx100, mantissa, fraction;
+
cbuf_init(&uart_cbuf, uart_buffer, sizeof(uart_buffer));
- uart_usart1_regs = (void *)UART_USART1_ADDR;
- uart_usart1_regs->cr1 |= UART_CR1_UE
- | UART_CR1_RXNEIE
- | UART_CR1_TE
- | UART_CR1_RE;
+ divx100 = UART_CLK / (16 * (UART_BAUD_RATE / 100));
+ fraction = ((divx100 % 100) * 16) / 100;
+ mantissa = divx100 / 100;
- cpu_irq_register(UART_USART1_IRQ, uart_irq_handler, NULL);
+ uart_regs->brr = ((mantissa << UART_BRR_MANTISSA_SHIFT)
+ & UART_BRR_MANTISSA_MASK)
+ | (fraction & UART_BRR_FRACTION_MASK);
+ uart_regs->cr1 |= UART_CR1_UE
+ | UART_CR1_RXNEIE
+ | UART_CR1_TE
+ | UART_CR1_RE;
+
+ cpu_irq_register(UART_USART6_IRQ, uart_irq_handler, NULL);
}
static void
uart_tx_wait(void)
{
- /*
- * XXX The QEMU stm32f2xx_usart driver doesn't seem to correctly emulate
- * the UART_SR_TXE bit.
- */
-#if 0
uint32_t sr;
for (;;) {
- sr = uart_usart1_regs->sr;
+ sr = uart_regs->sr;
if (sr & UART_SR_TXE) {
break;
}
}
-#endif
}
static void
uart_write_byte(uint8_t byte)
{
uart_tx_wait();
- uart_usart1_regs->dr = byte;
+ uart_regs->dr = byte;
}
void