diff options
-rw-r--r-- | fw/.gitignore | 11 | ||||
-rw-r--r-- | fw/8b10b.c | 190 | ||||
-rw-r--r-- | fw/8b10b.h | 38 | ||||
-rw-r--r-- | fw/8b10b_test.c | 78 | ||||
-rw-r--r-- | fw/Makefile | 101 | ||||
-rw-r--r-- | fw/base.c | 21 | ||||
-rw-r--r-- | fw/cmsis_exports.c | 0 | ||||
-rw-r--r-- | fw/global.h | 48 | ||||
-rw-r--r-- | fw/main.c | 103 | ||||
-rw-r--r-- | fw/openocd.cfg | 16 | ||||
-rw-r--r-- | fw/startup_stm32f030x6.s | 273 | ||||
-rw-r--r-- | fw/stm32_flash.ld | 136 | ||||
-rw-r--r-- | fw/system_stm32f0xx.c | 336 | ||||
-rw-r--r-- | fw/tools/gen_cmsis_exports.py | 30 |
14 files changed, 1381 insertions, 0 deletions
diff --git a/fw/.gitignore b/fw/.gitignore new file mode 100644 index 0000000..3e36fab --- /dev/null +++ b/fw/.gitignore @@ -0,0 +1,11 @@ +*.elf +*.o +*.expand +*.hex +*.lst +*.map +*.bin +sources.c +sources.tar.xz +sources.tar.xz.zip +8b10b_test diff --git a/fw/8b10b.c b/fw/8b10b.c new file mode 100644 index 0000000..550e87c --- /dev/null +++ b/fw/8b10b.c @@ -0,0 +1,190 @@ + +#include "8b10b.h" + +static const struct entry_5b6b map_5b6b[32] = { + {0b100111, 0b011000}, /* D.00 */ + {0b011101, 0b100010}, /* D.01 */ + {0b101101, 0b010010}, /* D.02 */ + {0b110001, 0b110001}, /* D.03 */ + {0b110101, 0b001010}, /* D.04 */ + {0b101001, 0b101001}, /* D.05 */ + {0b011001, 0b011001}, /* D.06 */ + {0b111000, 0b000111}, /* D.07 */ + {0b111001, 0b000110}, /* D.08 */ + {0b100101, 0b100101}, /* D.09 */ + {0b010101, 0b010101}, /* D.10 */ + {0b110100, 0b110100}, /* D.11 */ + {0b001101, 0b001101}, /* D.12 */ + {0b101100, 0b101100}, /* D.13 */ + {0b011100, 0b011100}, /* D.14 */ + {0b010111, 0b101000}, /* D.15 */ + {0b011011, 0b100100}, /* D.16 */ + {0b100011, 0b100011}, /* D.17 */ + {0b010011, 0b010011}, /* D.18 */ + {0b110010, 0b110010}, /* D.19 */ + {0b001011, 0b001011}, /* D.20 */ + {0b101010, 0b101010}, /* D.21 */ + {0b011010, 0b011010}, /* D.22 */ + {0b111010, 0b000101}, /* D.23 */ + {0b110011, 0b001100}, /* D.24 */ + {0b100110, 0b100110}, /* D.25 */ + {0b010110, 0b010110}, /* D.26 */ + {0b110110, 0b001001}, /* D.27 */ + {0b001110, 0b001110}, /* D.28 */ + {0b101110, 0b010001}, /* D.29 */ + {0b011110, 0b100001}, /* D.30 */ + {0b101011, 0b010100} /* D.31 */ +}; + +static const int8_t map_6b5b[64] = { + [0b000101] = 23, /* rd = +1 */ + [0b000110] = 8, /* rd = +1 */ + [0b000111] = 7, /* rd = +1 */ + [0b001001] = 27, /* rd = +1 */ + [0b001010] = 4, /* rd = +1 */ + [0b001011] = 20, /* rd = +1 */ + [0b001100] = 24, /* rd = +1 */ + [0b001101] = 12, /* rd = +1 */ + [0b001101] = 12, /* rd = -1 */ + [0b001110] = 28, /* rd = +1 */ + [0b010001] = 29, /* rd = +1 */ + [0b010010] = 2, /* rd = +1 */ + [0b010011] = 18, /* rd = +1 */ + [0b010100] = 31, /* rd = +1 */ + [0b010101] = 10, /* rd = +1 */ + [0b010101] = 10, /* rd = -1 */ + [0b010110] = 26, /* rd = +1 */ + [0b010111] = 15, /* rd = -1 */ + [0b011000] = -1, /* rd = +1 */ + [0b011001] = 6, /* rd = +1 */ + [0b011010] = 22, /* rd = +1 */ + [0b011011] = 16, /* rd = -1 */ + [0b011100] = 14, /* rd = -1 */ + [0b011101] = 1, /* rd = -1 */ + [0b011110] = 30, /* rd = -1 */ + [0b100001] = 30, /* rd = +1 */ + [0b100010] = 1, /* rd = +1 */ + [0b100011] = 17, /* rd = -1 */ + [0b100100] = 16, /* rd = +1 */ + [0b100101] = 9, /* rd = -1 */ + [0b100110] = 25, /* rd = -1 */ + [0b100111] = -1, /* rd = -1 */ + [0b101000] = 15, /* rd = +1 */ + [0b101001] = 5, /* rd = -1 */ + [0b101010] = 21, /* rd = -1 */ + [0b101011] = 31, /* rd = -1 */ + [0b101100] = 13, /* rd = -1 */ + [0b101101] = 2, /* rd = -1 */ + [0b101110] = 29, /* rd = -1 */ + [0b110001] = 3, /* rd = -1 */ + [0b110010] = 19, /* rd = -1 */ + [0b110011] = 24, /* rd = -1 */ + [0b110100] = 11, /* rd = -1 */ + [0b110101] = 4, /* rd = -1 */ + [0b110110] = 27, /* rd = -1 */ + [0b111000] = 7, /* rd = -1 */ + [0b111001] = 8, /* rd = -1 */ + [0b111010] = 23 /* rd = -1 */ +}; + +static const struct entry_5b6b K28 = {0b001111, 0b110000}; + +static const struct entry_3b4b map_d_3b4b[7] = { + {0b1011, 0b0100}, /* D.x.0 */ + {0b1001, 0b1001}, /* D.x.1 */ + {0b0101, 0b0101}, /* D.x.2 */ + {0b1100, 0b0011}, /* D.x.3 */ + {0b1101, 0b0010}, /* D.x.4 */ + {0b1010, 0b1010}, /* D.x.5 */ + {0b0110, 0b0110} /* D.x.6 */ +}; + +static const struct entry_3b4b Dx_P7 = {0b1110, 0b0001}, + Dx_A7 = {0b0111, 0b1000}; + +static const struct entry_3b4b map_3b4b_k[8] = { + {0b1011, 0b0100}, /* K.x.0 */ + {0b0110, 0b1001}, /* K.x.1 */ + {0b1010, 0b0101}, /* K.x.2 */ + {0b1100, 0b0011}, /* K.x.3 */ + {0b1101, 0b0010}, /* K.x.4 */ + {0b0101, 0b1010}, /* K.x.5 */ + {0b1001, 0b0110}, /* K.x.6 */ + {0b0111, 0b1000} /* K.x.7 */ +}; + +static const int8_t map_4b3b[16] = { + [0b0001] = 7, /* DxP7 rd = +1 */ + [0b0010] = 4, /* rd = +1 */ + [0b0011] = 3, /* rd = +1 */ + [0b0100] = -1, /* rd = +1 */ + [0b0101] = 2, /* rd = -1 */ + [0b0110] = 6, /* rd = -1 */ + [0b0111] = 7, /* DxA7 rd = -1 */ + [0b1000] = 7, /* DxA7 rd = +1 */ + [0b1001] = 1, /* rd = -1 */ + [0b1010] = 5, /* rd = -1 */ + [0b1011] = -1, /* rd = -1 */ + [0b1100] = 3, /* rd = -1 */ + [0b1101] = 4, /* rd = -1 */ + [0b1110] = 7, /* DxP7 rd = -1 */ + [0b1111] = 0, /* invalid */ + [0b0000] = 0 /* invalid */ +}; + +static const uint16_t k_sym_map[K_CODES_LAST] = { + [K28_0] = 0b0011110100, + [K28_1] = 0b0011111001, + [K28_2] = 0b0011110101, + [K28_3] = 0b0011110011, + [K28_4] = 0b0011110010, + [K28_5] = 0b0011111010, + [K28_6] = 0b0011110110, + [K28_7] = 0b0011111000, + [K23_7] = 0b1110101000, + [K27_7] = 0b1101101000, + [K29_7] = 0b1011101000, + [K30_7] = 0b0111101000 +}; + +void xfr_8b10b_reset(struct state_8b10b *st) { + st->rx = 0; + st->bit_ctr = 0; /* unsynchronized */ +} + +int xfr_8b10b_feed_bit(struct state_8b10b *st, int bit) { + uint32_t pattern = st->rx = (st->rx<<1 | !!bit) & 0x3ff; + uint16_t comma = k_sym_map[K28_1]; + if (pattern == comma || pattern == ((~comma)&0x3ff)) { + st->bit_ctr = 1; + return -K28_1; + } + + if (st->bit_ctr == 10) { + st->bit_ctr = 1; + + for (int i=1; i<sizeof(k_sym_map)/sizeof(k_sym_map[0]); i++) { + if (pattern == k_sym_map[i]) + return -i; + } + + int p3b = map_4b3b[pattern & 0xf]; + int p5b = map_6b5b[pattern >> 4]; + + if (p3b == 0 || p5b == 0) + return -DECODING_ERROR; + + p3b = (p3b == -1) ? 0 : p3b; + p5b = (p5b == -1) ? 0 : p5b; + return p3b<<5 | p5b; + + } else if (st->bit_ctr > 0) { + st->bit_ctr++; + } /* else we do not have sync yet */ + return -DECODING_IN_PROGRESS; +} + +bool xfr_8b10b_has_sync(struct state_8b10b *st) { + return st->bit_ctr != 0; +} + diff --git a/fw/8b10b.h b/fw/8b10b.h new file mode 100644 index 0000000..84763b1 --- /dev/null +++ b/fw/8b10b.h @@ -0,0 +1,38 @@ +#ifndef __8B10B_H__ +#define __8B10B_H__ + +#include <stdint.h> +#include <stdbool.h> + +enum k_code { + K28_0=1, K28_1, K28_2, K28_3, + K28_4, K28_5, K28_6, K28_7, + K23_7, K27_7, K29_7, K30_7, + K_CODES_LAST +}; + +enum decoder_return_codes { + _K_CODES_LAST = K_CODES_LAST, + DECODING_ERROR, + DECODING_IN_PROGRESS +}; + +struct entry_3b4b { + uint8_t rd_neg, rd_pos; +}; + +struct entry_5b6b { + uint8_t rd_neg, rd_pos; +}; + +struct state_8b10b { + uint32_t rx; + int bit_ctr; +}; + + +void xfr_8b10b_reset(struct state_8b10b *st); +int xfr_8b10b_feed_bit(struct state_8b10b *st, int bit); +bool xfr_8b10b_has_sync(struct state_8b10b *st); + +#endif diff --git a/fw/8b10b_test.c b/fw/8b10b_test.c new file mode 100644 index 0000000..d11e6b2 --- /dev/null +++ b/fw/8b10b_test.c @@ -0,0 +1,78 @@ + +#include <stdio.h> + +#include "8b10b.h" + +static const char * const rc_names[] = { + [K28_0] = "K.28.0", + [K28_1] = "K.28.1", + [K28_2] = "K.28.2", + [K28_3] = "K.28.3", + [K28_4] = "K.28.4", + [K28_5] = "K.28.5", + [K28_6] = "K.28.6", + [K28_7] = "K.28.7", + [K23_7] = "K.23.7", + [K27_7] = "K.27.7", + [K29_7] = "K.29.7", + [K30_7] = "K.30.7", + [DECODING_ERROR] = "ERROR", + [DECODING_IN_PROGRESS] = "." +}; + +int main(void) { + struct state_8b10b st; + + xfr_8b10b_reset(&st); + + int c; + int comment = 0; + while ((c=fgetc(stdin)) != EOF) { + int bit; + + if (comment) { + if (c == '\n') + comment = 0; + continue; + } + + if (c == '\r' || c == ' ' || c == '\t' || c == '\n') + continue; + + if (c == '#') { + comment = 1; + continue; + } + + if (c == '0') { + bit = 0; + } else if (c == '1') { + bit = 1; + } else { + fprintf(stderr, "Parse error: Bit must be 0 or 1, not '%c'. Exiting.\n", c); + return 1; + } + + int read_result = xfr_8b10b_feed_bit(&st, bit); + char sync_status = xfr_8b10b_has_sync(&st) ? 'S' : 'U'; + + if (read_result >= 0) { + fprintf(stdout, "%c%02x ", sync_status, read_result); + + } else { + if (-read_result > sizeof(rc_names)/sizeof(rc_names[0])) { + fprintf(stderr, "Illegal read result %d. Exiting.\n", read_result); + return 2; + } + + const char * const msg = rc_names[-read_result]; + if (!msg) { + fprintf(stderr, "Illegal read result %d. Exiting.\n", read_result); + return 2; + } + + fprintf(stdout, "%c%s ", sync_status, msg); + } + } +} + diff --git a/fw/Makefile b/fw/Makefile new file mode 100644 index 0000000..1098717 --- /dev/null +++ b/fw/Makefile @@ -0,0 +1,101 @@ +# Megumin LED display firmware +# Copyright (C) 2018 Sebastian Götte <code@jaseg.net> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +CUBE_PATH ?= $(wildcard ~)/resource/STM32CubeF0 +CMSIS_PATH ?= $(CUBE_PATH)/Drivers/CMSIS +CMSIS_DEV_PATH ?= $(CMSIS_PATH)/Device/ST/STM32F0xx +HAL_PATH ?= $(CUBE_PATH)/Drivers/STM32F0xx_HAL_Driver + +MAC_ADDR ?= 0xdeadbeef + +CC := arm-none-eabi-gcc +LD := arm-none-eabi-ld +OBJCOPY := arm-none-eabi-objcopy +OBJDUMP := arm-none-eabi-objdump +SIZE := arm-none-eabi-size + +CFLAGS = -g -Wall -std=gnu11 -O0 -fdump-rtl-expand -DMAC_ADDR=$(MAC_ADDR) +CFLAGS += -mlittle-endian -mcpu=cortex-m0 -march=armv6-m -mthumb +#CFLAGS += -ffunction-sections -fdata-sections +LDFLAGS = -nostartfiles +#LDFLAGS += -specs=rdimon.specs -DSEMIHOSTING +LDFLAGS += -Wl,-Map=main.map -nostdlib +#LDFLAGS += -Wl,--gc-sections +LIBS = -lgcc +#LIBS += -lrdimon + +# Technically we're using an STM32F030F4, but apart from the TSSOP20 package that one is largely identical to the +# STM32F030*6 and there is no separate device header provided for it, so we're faking a *6 device here. This is +# even documented in stm32f0xx.h. Thanks ST! +CFLAGS += -DSTM32F030x6 -DHSE_VALUE=8000000 + +LDFLAGS += -Tstm32_flash.ld +CFLAGS += -I$(CMSIS_DEV_PATH)/Include -I$(CMSIS_PATH)/Include -I$(HAL_PATH)/Inc -Iconfig -Wno-unused +LDFLAGS += -L$(CMSIS_PATH)/Lib/GCC -larm_cortexM0l_math + +################################################### + +.PHONY: program clean + +all: main.elf + +cmsis_exports.c: $(CMSIS_DEV_PATH)/Include/stm32f030x6.h $(CMSIS_PATH)/Include/core_cm0.h + python3 tools/gen_cmsis_exports.py $^ > $@ + +%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $^ +# $(CC) -E $(CFLAGS) -o $(@:.o=.pp) $^ + +%.o: %.s + $(CC) -c $(CFLAGS) -o $@ $^ +# $(CC) -E $(CFLAGS) -o $(@:.o=.pp) $^ + +%.dot: %.elf + r2 -a arm -qc 'aa;agC' $< 2>/dev/null >$@ + +sources.tar.xz: main.c Makefile + tar -caf $@ $^ + +# don't ask... +sources.tar.xz.zip: sources.tar.xz + zip $@ $^ + +sources.c: sources.tar.xz.zip + xxd -i $< | head -n -1 | sed 's/=/__attribute__((section(".source_tarball"))) =/' > $@ + +main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f0xx_ll_utils.o base.o cmsis_exports.o 8b10b.o sources.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + $(OBJCOPY) -O ihex $@ $(@:.elf=.hex) + $(OBJCOPY) -O binary $@ $(@:.elf=.bin) + $(OBJDUMP) -St $@ >$(@:.elf=.lst) + $(SIZE) $@ + +program: main.elf openocd.cfg + openocd -f openocd.cfg -c "program $< verify reset exit" + +8b10b_test: 8b10b_test.c 8b10b.c + gcc -o $@ $^ + +clean: + rm -f **.o + rm -f main.elf main.hex main.bin main.map main.lst + rm -f **.expand + rm -f cmsis_exports.c + rm -f sources.tar.xz + rm -f sources.tar.xz.zip + rm -f sources.c + rm -f *.dot + diff --git a/fw/base.c b/fw/base.c new file mode 100644 index 0000000..277c662 --- /dev/null +++ b/fw/base.c @@ -0,0 +1,21 @@ + +#include <unistd.h> + +int __errno = 0; +void *_impure_ptr = NULL; + +void __sinit(void) { +} + +void *memset(void *s, int c, size_t n) { + char *end = (char *)s + n; + for (char *p = (char *)s; p < end; p++) + *p = (char)c; + return s; +} + +size_t strlen(const char *s) { + const char *start = s; + while (*s++); + return s - start - 1; +} diff --git a/fw/cmsis_exports.c b/fw/cmsis_exports.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/fw/cmsis_exports.c diff --git a/fw/global.h b/fw/global.h new file mode 100644 index 0000000..03d3920 --- /dev/null +++ b/fw/global.h @@ -0,0 +1,48 @@ +/* Megumin LED display firmware + * Copyright (C) 2018 Sebastian Götte <code@jaseg.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GLOBAL_H__ +#define __GLOBAL_H__ + +/* Workaround for sub-par ST libraries */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#include <stm32f0xx.h> +#include <stm32f0xx_ll_utils.h> +#include <stm32f0xx_ll_spi.h> +#pragma GCC diagnostic pop + +#include <system_stm32f0xx.h> + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <unistd.h> + +/* Microcontroller part number: STM32F030F4C6 */ + +/* Things used for module status reporting. */ +#define FIRMWARE_VERSION 2 +#define HARDWARE_VERSION 4 + +#define TS_CAL1 (*(uint16_t *)0x1FFFF7B8) +#define VREFINT_CAL (*(uint16_t *)0x1FFFF7BA) + +extern volatile unsigned int sys_time; +extern volatile unsigned int sys_time_seconds; + +#endif/*__GLOBAL_H__*/ diff --git a/fw/main.c b/fw/main.c new file mode 100644 index 0000000..b599cff --- /dev/null +++ b/fw/main.c @@ -0,0 +1,103 @@ +/* Megumin LED display firmware + * Copyright (C) 2018 Sebastian Götte <code@jaseg.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "global.h" + +volatile unsigned int sys_time = 0; +volatile unsigned int sys_time_seconds = 0; + +int main(void) { + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR&RCC_CR_HSERDY)); + RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk; + RCC->CFGR |= (2<<RCC_CFGR_PLLMUL_Pos) | RCC_CFGR_PLLSRC_HSE_PREDIV; /* PLL x4 -> 32.0MHz */ + RCC->CFGR2 &= ~RCC_CFGR2_PREDIV_Msk; + RCC->CFGR2 |= RCC_CFGR2_PREDIV_DIV2; /* prediv :2 -> 4.0MHz */ + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR&RCC_CR_PLLRDY)); + RCC->CFGR |= (2<<RCC_CFGR_SW_Pos); + SystemCoreClockUpdate(); + + /* Turn on lots of neat things */ + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_FLITFEN; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_DBGMCUEN | RCC_APB2ENR_TIM1EN; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; + + GPIOA->MODER |= + (3<<GPIO_MODER_MODER0_Pos) /* PA0 - Vmeas_A */ + | (3<<GPIO_MODER_MODER1_Pos) /* PA1 - Vmeas_B */ + | (1<<GPIO_MODER_MODER2_Pos) /* PA2 - LOAD */ + | (1<<GPIO_MODER_MODER3_Pos) /* PA3 - CH0 */ + | (1<<GPIO_MODER_MODER4_Pos) /* PA4 - CH3 */ + | (0<<GPIO_MODER_MODER5_Pos) /* PA5 - TP1 */ + | (1<<GPIO_MODER_MODER6_Pos) /* PA6 - CH2 */ + | (1<<GPIO_MODER_MODER7_Pos) /* PA7 - CH1 */ + | (0<<GPIO_MODER_MODER9_Pos) /* PA9 - TP2 */ + | (0<<GPIO_MODER_MODER10_Pos);/* PA10 - TP3 */ + + /* Set shift register IO GPIO output speed */ + GPIOA->OSPEEDR |= + (2<<GPIO_OSPEEDR_OSPEEDR2_Pos) /* LOAD */ + | (2<<GPIO_OSPEEDR_OSPEEDR3_Pos) /* CH0 */ + | (2<<GPIO_OSPEEDR_OSPEEDR4_Pos) /* CH3 */ + | (2<<GPIO_OSPEEDR_OSPEEDR6_Pos) /* CH2 */ + | (2<<GPIO_OSPEEDR_OSPEEDR7_Pos); /* CH1 */ + + SysTick_Config(SystemCoreClock/1000); /* 1ms interval */ + + void set_outputs(uint8_t val) { + int a=!!(val&1), b=!!(val&2), c=!!(val&4), d=!!(val&8); + GPIOA->ODR &= ~(!a<<3 | !b<<7 | c<<6 | d<<4); + GPIOA->ODR |= a<<3 | b<<7 | !c<<6 | !d<<4; + } + while (42) { +#define FOO 500000 + for (int i=0; i<FOO; i++) ; + set_outputs(0x1); + for (int i=0; i<FOO; i++) ; + set_outputs(0x2); + for (int i=0; i<FOO; i++) ; + set_outputs(0x4); + for (int i=0; i<FOO; i++) ; + set_outputs(0x8); + } +} + +void NMI_Handler(void) { +} + +void HardFault_Handler(void) __attribute__((naked)); +void HardFault_Handler() { + asm volatile ("bkpt"); +} + +void SVC_Handler(void) { +} + + +void PendSV_Handler(void) { +} + +void SysTick_Handler(void) { + static int n = 0; + sys_time++; + if (n++ == 1000) { + n = 0; + sys_time_seconds++; + } +} + diff --git a/fw/openocd.cfg b/fw/openocd.cfg new file mode 100644 index 0000000..4c52fdc --- /dev/null +++ b/fw/openocd.cfg @@ -0,0 +1,16 @@ +telnet_port 4444 +gdb_port 3333 + +source [find interface/stlink-v2.cfg] +#interface jlink +#interface stlink-v2 +#adapter_khz 10000 +#transport select swd + +#source /usr/share/openocd/scripts/target/stm32f0x.cfg +source [find target/stm32f0x_stlink.cfg] + +init +arm semihosting enable + +#flash bank sysflash.alias stm32f0x 0x00000000 0 0 0 $_TARGETNAME diff --git a/fw/startup_stm32f030x6.s b/fw/startup_stm32f030x6.s new file mode 100644 index 0000000..2f0eb42 --- /dev/null +++ b/fw/startup_stm32f030x6.s @@ -0,0 +1,273 @@ +/**
+ ******************************************************************************
+ * @file startup_stm32f030x6.s
+ * copied from: STM32Cube/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc
+ * @author MCD Application Team
+ * @version V2.3.1
+ * @date 04-November-2016
+ * @brief STM32F030x4/STM32F030x6 devices vector table for Atollic TrueSTUDIO toolchain.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M0 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+ .syntax unified
+ .cpu cortex-m0
+ .fpu softvfp
+ .thumb
+
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+
+ .section .text.Reset_Handler
+ .weak Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ ldr r0, =_estack
+ mov sp, r0 /* set stack pointer */
+
+/* Copy the data segment initializers from flash to SRAM */
+ movs r1, #0
+ b LoopCopyDataInit
+
+CopyDataInit:
+ ldr r3, =_sidata
+ ldr r3, [r3, r1]
+ str r3, [r0, r1]
+ adds r1, r1, #4
+
+LoopCopyDataInit:
+ ldr r0, =_sdata
+ ldr r3, =_edata
+ adds r2, r0, r1
+ cmp r2, r3
+ bcc CopyDataInit
+ ldr r2, =_sbss
+ b LoopFillZerobss
+/* Zero fill the bss segment. */
+FillZerobss:
+ movs r3, #0
+ str r3, [r2]
+ adds r2, r2, #4
+
+
+LoopFillZerobss:
+ ldr r3, = _ebss
+ cmp r2, r3
+ bcc FillZerobss
+
+/* Call the clock system intitialization function.*/
+ bl SystemInit
+/* Call static constructors */
+// bl __libc_init_array
+/* Call the application's entry point.*/
+ bl main
+
+LoopForever:
+ b LoopForever
+
+
+.size Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief This is the code that gets called when the processor receives an
+ * unexpected interrupt. This simply enters an infinite loop, preserving
+ * the system state for examination by a debugger.
+ *
+ * @param None
+ * @retval : None
+*/
+ .section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex M0. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+ .size g_pfnVectors, .-g_pfnVectors
+
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word 0
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+ .word WWDG_IRQHandler /* Window WatchDog */
+ .word 0 /* Reserved */
+ .word RTC_IRQHandler /* RTC through the EXTI line */
+ .word FLASH_IRQHandler /* FLASH */
+ .word RCC_IRQHandler /* RCC */
+ .word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
+ .word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
+ .word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */
+ .word 0 /* Reserved */
+ .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
+ .word DMA1_Channel2_3_IRQHandler /* DMA1 Channel 2 and Channel 3 */
+ .word DMA1_Channel4_5_IRQHandler /* DMA1 Channel 4 and Channel 5 */
+ .word ADC1_IRQHandler /* ADC1 */
+ .word TIM1_BRK_UP_TRG_COM_IRQHandler /* TIM1 Break, Update, Trigger and Commutation */
+ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
+ .word 0 /* Reserved */
+ .word TIM3_IRQHandler /* TIM3 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word TIM14_IRQHandler /* TIM14 */
+ .word 0 /* Reserved */
+ .word TIM16_IRQHandler /* TIM16 */
+ .word TIM17_IRQHandler /* TIM17 */
+ .word I2C1_IRQHandler /* I2C1 */
+ .word 0 /* Reserved */
+ .word SPI1_IRQHandler /* SPI1 */
+ .word 0 /* Reserved */
+ .word USART1_IRQHandler /* USART1 */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+
+ .weak NMI_Handler
+ .thumb_set NMI_Handler,Default_Handler
+
+ .weak HardFault_Handler
+ .thumb_set HardFault_Handler,Default_Handler
+
+ .weak SVC_Handler
+ .thumb_set SVC_Handler,Default_Handler
+
+ .weak PendSV_Handler
+ .thumb_set PendSV_Handler,Default_Handler
+
+ .weak SysTick_Handler
+ .thumb_set SysTick_Handler,Default_Handler
+
+ .weak WWDG_IRQHandler
+ .thumb_set WWDG_IRQHandler,Default_Handler
+
+ .weak RTC_IRQHandler
+ .thumb_set RTC_IRQHandler,Default_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Default_Handler
+
+ .weak RCC_IRQHandler
+ .thumb_set RCC_IRQHandler,Default_Handler
+
+ .weak EXTI0_1_IRQHandler
+ .thumb_set EXTI0_1_IRQHandler,Default_Handler
+
+ .weak EXTI2_3_IRQHandler
+ .thumb_set EXTI2_3_IRQHandler,Default_Handler
+
+ .weak EXTI4_15_IRQHandler
+ .thumb_set EXTI4_15_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel1_IRQHandler
+ .thumb_set DMA1_Channel1_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel2_3_IRQHandler
+ .thumb_set DMA1_Channel2_3_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel4_5_IRQHandler
+ .thumb_set DMA1_Channel4_5_IRQHandler,Default_Handler
+
+ .weak ADC1_IRQHandler
+ .thumb_set ADC1_IRQHandler,Default_Handler
+
+ .weak TIM1_BRK_UP_TRG_COM_IRQHandler
+ .thumb_set TIM1_BRK_UP_TRG_COM_IRQHandler,Default_Handler
+
+ .weak TIM1_CC_IRQHandler
+ .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+ .weak TIM3_IRQHandler
+ .thumb_set TIM3_IRQHandler,Default_Handler
+
+ .weak TIM14_IRQHandler
+ .thumb_set TIM14_IRQHandler,Default_Handler
+
+ .weak TIM16_IRQHandler
+ .thumb_set TIM16_IRQHandler,Default_Handler
+
+ .weak TIM17_IRQHandler
+ .thumb_set TIM17_IRQHandler,Default_Handler
+
+ .weak I2C1_IRQHandler
+ .thumb_set I2C1_IRQHandler,Default_Handler
+
+ .weak SPI1_IRQHandler
+ .thumb_set SPI1_IRQHandler,Default_Handler
+
+ .weak USART1_IRQHandler
+ .thumb_set USART1_IRQHandler,Default_Handler
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/fw/stm32_flash.ld b/fw/stm32_flash.ld new file mode 100644 index 0000000..cba7577 --- /dev/null +++ b/fw/stm32_flash.ld @@ -0,0 +1,136 @@ +
+ENTRY(Reset_Handler)
+
+MEMORY {
+ FLASH (rx): ORIGIN = 0x08000000, LENGTH = 0x3C00
+ CONFIGFLASH (rw): ORIGIN = 0x08003C00, LENGTH = 0x400
+ RAM (xrw): ORIGIN = 0x20000000, LENGTH = 4K
+}
+
+/* highest address of the user mode stack */
+_estack = 0x20001000;
+
+SECTIONS {
+ /* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
+ .isr_vector : {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+ . = ALIGN(4);
+ } >FLASH
+
+ /* the program code is stored in the .text section, which goes to Flash */
+ .text : {
+ . = ALIGN(4);
+
+ *(.text) /* normal code */
+ *(.text.*) /* -ffunction-sections code */
+ *(.rodata) /* read-only data (constants) */
+ *(.rodata*) /* -fdata-sections read only data */
+ *(.glue_7) /* TBD - needed ? */
+ *(.glue_7t) /* TBD - needed ? */
+
+ *(.source_tarball)
+
+ /* Necessary KEEP sections (see http://sourceware.org/ml/newlib/2005/msg00255.html) */
+ KEEP (*(.init))
+ KEEP (*(.fini))
+ KEEP (*(.source_tarball))
+
+ . = ALIGN(4);
+ _etext = .;
+ /* This is used by the startup in order to initialize the .data section */
+ _sidata = _etext;
+ } >FLASH
+
+ /*
+ .configflash : {
+ . = ALIGN(0x400);
+ *(.configdata)
+ _econfig = .;
+ } >FLASH
+ */
+
+ /* This is the initialized data section
+ The program executes knowing that the data is in the RAM
+ but the loader puts the initial values in the FLASH (inidata).
+ It is one task of the startup to copy the initial values from FLASH to RAM. */
+ .data : AT ( _sidata ) {
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .data secion */
+ _sdata = . ;
+ _data = . ;
+
+ *(.data)
+ *(.data.*)
+ *(.RAMtext)
+
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .data secion */
+ _edata = . ;
+ } >RAM
+
+ /* This is the uninitialized data section */
+ .bss : {
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .bss secion */
+ _sbss = .;
+ _bss = .;
+
+ *(.bss)
+ *(.bss.*) /* patched by elias - allows the use of -fdata-sections */
+ *(COMMON)
+
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .bss secion */
+ _ebss = . ;
+ } >RAM
+
+ PROVIDE ( end = _ebss);
+ PROVIDE (_end = _ebss);
+
+ __exidx_start = .;
+ __exidx_end = .;
+
+ /* after that it's only debugging information. */
+
+ /* remove the debugging information from the standard libraries */
+/* /DISCARD/ : {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }*/
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+}
diff --git a/fw/system_stm32f0xx.c b/fw/system_stm32f0xx.c new file mode 100644 index 0000000..a43c3d6 --- /dev/null +++ b/fw/system_stm32f0xx.c @@ -0,0 +1,336 @@ +/**
+ ******************************************************************************
+ * @file system_stm32f0xx.c
+ * copied from: STM32Cube/Drivers/CMSIS/Device/ST/STM32F0xx/Source/Templates
+ * @author MCD Application Team
+ * @version V2.3.1
+ * @date 04-November-2016
+ * @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File.
+ *
+ * 1. This file provides two functions and one global variable to be called from
+ * user application:
+ * - SystemInit(): This function is called at startup just after reset and
+ * before branch to main program. This call is made inside
+ * the "startup_stm32f0xx.s" file.
+ *
+ * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+ * by the user application to setup the SysTick
+ * timer or configure other parameters.
+ *
+ * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+ * be called whenever the core clock is changed
+ * during program execution.
+ *
+ * 2. After each device reset the HSI (8 MHz) is used as system clock source.
+ * Then SystemInit() function is called, in "startup_stm32f0xx.s" file, to
+ * configure the system clock before to branch to main program.
+ *
+ * 3. This file configures the system clock as follows:
+ *=============================================================================
+ * Supported STM32F0xx device
+ *-----------------------------------------------------------------------------
+ * System Clock source | HSI
+ *-----------------------------------------------------------------------------
+ * SYSCLK(Hz) | 8000000
+ *-----------------------------------------------------------------------------
+ * HCLK(Hz) | 8000000
+ *-----------------------------------------------------------------------------
+ * AHB Prescaler | 1
+ *-----------------------------------------------------------------------------
+ * APB1 Prescaler | 1
+ *-----------------------------------------------------------------------------
+ *=============================================================================
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32f0xx_system
+ * @{
+ */
+
+/** @addtogroup STM32F0xx_System_Private_Includes
+ * @{
+ */
+
+#include "stm32f0xx.h"
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F0xx_System_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F0xx_System_Private_Defines
+ * @{
+ */
+#if !defined (HSE_VALUE)
+ #define HSE_VALUE ((uint32_t)8000000) /*!< Default value of the External oscillator in Hz.
+ This value can be provided and adapted by the user application. */
+#endif /* HSE_VALUE */
+
+#if !defined (HSI_VALUE)
+ #define HSI_VALUE ((uint32_t)8000000) /*!< Default value of the Internal oscillator in Hz.
+ This value can be provided and adapted by the user application. */
+#endif /* HSI_VALUE */
+
+#if !defined (HSI48_VALUE)
+#define HSI48_VALUE ((uint32_t)48000000) /*!< Default value of the HSI48 Internal oscillator in Hz.
+ This value can be provided and adapted by the user application. */
+#endif /* HSI48_VALUE */
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F0xx_System_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F0xx_System_Private_Variables
+ * @{
+ */
+ /* This variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock there is no need to
+ call the 2 first functions listed above, since SystemCoreClock variable is
+ updated automatically.
+ */
+uint32_t SystemCoreClock = 8000000;
+
+const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F0xx_System_Private_FunctionPrototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F0xx_System_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Setup the microcontroller system.
+ * Initialize the default HSI clock source, vector table location and the PLL configuration is reset.
+ * @param None
+ * @retval None
+ */
+void SystemInit(void)
+{
+ /* Reset the RCC clock configuration to the default reset state ------------*/
+ /* Set HSION bit */
+ RCC->CR |= (uint32_t)0x00000001U;
+
+#if defined (STM32F051x8) || defined (STM32F058x8)
+ /* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits */
+ RCC->CFGR &= (uint32_t)0xF8FFB80CU;
+#else
+ /* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE, MCOSEL[2:0], MCOPRE[2:0] and PLLNODIV bits */
+ RCC->CFGR &= (uint32_t)0x08FFB80CU;
+#endif /* STM32F051x8 or STM32F058x8 */
+
+ /* Reset HSEON, CSSON and PLLON bits */
+ RCC->CR &= (uint32_t)0xFEF6FFFFU;
+
+ /* Reset HSEBYP bit */
+ RCC->CR &= (uint32_t)0xFFFBFFFFU;
+
+ /* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
+ RCC->CFGR &= (uint32_t)0xFFC0FFFFU;
+
+ /* Reset PREDIV[3:0] bits */
+ RCC->CFGR2 &= (uint32_t)0xFFFFFFF0U;
+
+#if defined (STM32F072xB) || defined (STM32F078xx)
+ /* Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFFCFE2CU;
+#elif defined (STM32F071xB)
+ /* Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFFFCEACU;
+#elif defined (STM32F091xC) || defined (STM32F098xx)
+ /* Reset USART3SW[1:0], USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFF0FEACU;
+#elif defined (STM32F030x6) || defined (STM32F030x8) || defined (STM32F031x6) || defined (STM32F038xx) || defined (STM32F030xC)
+ /* Reset USART1SW[1:0], I2C1SW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFFFFEECU;
+#elif defined (STM32F051x8) || defined (STM32F058xx)
+ /* Reset USART1SW[1:0], I2C1SW, CECSW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFFFFEACU;
+#elif defined (STM32F042x6) || defined (STM32F048xx)
+ /* Reset USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFFFFE2CU;
+#elif defined (STM32F070x6) || defined (STM32F070xB)
+ /* Reset USART1SW[1:0], I2C1SW, USBSW and ADCSW bits */
+ RCC->CFGR3 &= (uint32_t)0xFFFFFE6CU;
+ /* Set default USB clock to PLLCLK, since there is no HSI48 */
+ RCC->CFGR3 |= (uint32_t)0x00000080U;
+#else
+ #warning "No target selected"
+#endif
+
+ /* Reset HSI14 bit */
+ RCC->CR2 &= (uint32_t)0xFFFFFFFEU;
+
+ /* Disable all interrupts */
+ RCC->CIR = 0x00000000U;
+
+}
+
+/**
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ * The SystemCoreClock variable contains the core clock (HCLK), it can
+ * be used by the user application to setup the SysTick timer or configure
+ * other parameters.
+ *
+ * @note Each time the core clock (HCLK) changes, this function must be called
+ * to update SystemCoreClock variable value. Otherwise, any configuration
+ * based on this variable will be incorrect.
+ *
+ * @note - The system frequency computed by this function is not the real
+ * frequency in the chip. It is calculated based on the predefined
+ * constant and the selected clock source:
+ *
+ * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
+ *
+ * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
+ *
+ * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.
+ *
+ * (*) HSI_VALUE is a constant defined in stm32f0xx_hal.h file (default value
+ * 8 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ *
+ * (**) HSE_VALUE is a constant defined in stm32f0xx_hal.h file (default value
+ * 8 MHz), user has to ensure that HSE_VALUE is same as the real
+ * frequency of the crystal used. Otherwise, this function may
+ * have wrong result.
+ *
+ * - The result of this function could be not correct when using fractional
+ * value for HSE crystal.
+ *
+ * @param None
+ * @retval None
+ */
+void SystemCoreClockUpdate (void)
+{
+ uint32_t tmp = 0, pllmull = 0, pllsource = 0, predivfactor = 0;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ tmp = RCC->CFGR & RCC_CFGR_SWS;
+
+ switch (tmp)
+ {
+ case RCC_CFGR_SWS_HSI: /* HSI used as system clock */
+ SystemCoreClock = HSI_VALUE;
+ break;
+ case RCC_CFGR_SWS_HSE: /* HSE used as system clock */
+ SystemCoreClock = HSE_VALUE;
+ break;
+ case RCC_CFGR_SWS_PLL: /* PLL used as system clock */
+ /* Get PLL clock source and multiplication factor ----------------------*/
+ pllmull = RCC->CFGR & RCC_CFGR_PLLMUL;
+ pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
+ pllmull = ( pllmull >> 18) + 2;
+ predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1;
+
+ if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV)
+ {
+ /* HSE used as PLL clock source : SystemCoreClock = HSE/PREDIV * PLLMUL */
+ SystemCoreClock = (HSE_VALUE/predivfactor) * pllmull;
+ }
+#if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F091xC) || defined(STM32F098xx)
+ else if (pllsource == RCC_CFGR_PLLSRC_HSI48_PREDIV)
+ {
+ /* HSI48 used as PLL clock source : SystemCoreClock = HSI48/PREDIV * PLLMUL */
+ SystemCoreClock = (HSI48_VALUE/predivfactor) * pllmull;
+ }
+#endif /* STM32F042x6 || STM32F048xx || STM32F072xB || STM32F078xx || STM32F091xC || STM32F098xx */
+ else
+ {
+#if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F070x6) \
+ || defined(STM32F078xx) || defined(STM32F071xB) || defined(STM32F072xB) \
+ || defined(STM32F070xB) || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC)
+ /* HSI used as PLL clock source : SystemCoreClock = HSI/PREDIV * PLLMUL */
+ SystemCoreClock = (HSI_VALUE/predivfactor) * pllmull;
+#else
+ /* HSI used as PLL clock source : SystemCoreClock = HSI/2 * PLLMUL */
+ SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
+#endif /* STM32F042x6 || STM32F048xx || STM32F070x6 ||
+ STM32F071xB || STM32F072xB || STM32F078xx || STM32F070xB ||
+ STM32F091xC || STM32F098xx || STM32F030xC */
+ }
+ break;
+ default: /* HSI used as system clock */
+ SystemCoreClock = HSI_VALUE;
+ break;
+ }
+ /* Compute HCLK clock frequency ----------------*/
+ /* Get HCLK prescaler */
+ tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
+ /* HCLK clock frequency */
+ SystemCoreClock >>= tmp;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/fw/tools/gen_cmsis_exports.py b/fw/tools/gen_cmsis_exports.py new file mode 100644 index 0000000..ba3422b --- /dev/null +++ b/fw/tools/gen_cmsis_exports.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +import re +import os + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('cmsis_device_header', nargs='+', type=argparse.FileType('rb')) + args = parser.parse_args() + + print('#ifndef __GENERATED_CMSIS_HEADER_EXPORTS__') + print('#define __GENERATED_CMSIS_HEADER_EXPORTS__') + print() + for header in args.cmsis_device_header: + lines = header.readlines() + name = os.path.basename(header.name) + print('#include <{}>'.format(name)) + print() + + print('/* {} */'.format(name)) + for l in lines: + match = re.match(b'^#define (\w+)\s+\W*(\w+_TypeDef|\w+_Type).*$', l) + if match: + inst, typedef = match.groups() + inst, typedef = inst.decode(), typedef.decode() + print('{} *{} = {};'.format(typedef, inst.lower(), inst)) + print() + print('#endif//__GENERATED_CMSIS_HEADER_EXPORTS__') + |