diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | openocd.cfg | 5 | ||||
-rw-r--r-- | src/boot.c | 6 | ||||
-rw-r--r-- | src/cpu.h | 4 | ||||
-rw-r--r-- | src/flash.c | 50 | ||||
-rw-r--r-- | src/flash.h | 31 | ||||
-rw-r--r-- | src/gpio.c | 89 | ||||
-rw-r--r-- | src/gpio.h | 31 | ||||
-rw-r--r-- | src/kernel.lds.S | 17 | ||||
-rw-r--r-- | src/rcc.c | 205 | ||||
-rw-r--r-- | src/rcc.h | 42 | ||||
-rw-r--r-- | src/systick.c | 14 | ||||
-rw-r--r-- | src/uart.c | 48 |
13 files changed, 516 insertions, 34 deletions
@@ -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 @@ -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(); } @@ -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 = ®s->afrl; + } else { + reg = ®s->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); @@ -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 |