diff --git a/release.Makefile b/release.Makefile index dbc6779..6e6d45c 100644 --- a/release.Makefile +++ b/release.Makefile @@ -35,6 +35,7 @@ all: dapboot-bluepill.bin \ dapboot-olimexstm32h103.bin \ dapboot-bluepillplusstm32.bin \ dapboot-bttskrminie3v2.bin \ + dapboot-bluepill-ch32.bin \ dapboot-bluepill-high.bin \ dapboot-maplemini-high.bin \ dapboot-stlink-high.bin \ @@ -92,6 +93,12 @@ dapboot-bttskrminie3v2.bin: | $(BUILD_DIR) $(Q)$(MAKE) TARGET=BTTSKRMINIE3V2 -C src/ $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) +dapboot-bluepill-ch32.bin: | $(BUILD_DIR) + @printf " BUILD $(@)\n" + $(Q)$(MAKE) TARGET=BLUEPILL_CH32 -C src/ clean + $(Q)$(MAKE) TARGET=BLUEPILL_CH32 -C src/ + $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) + dapboot-bluepill-high.bin: | $(BUILD_DIR) @printf " BUILD $(@)\n" $(Q)$(MAKE) TARGET=BLUEPILL_HIGH -C src/ clean diff --git a/src/dfu.c b/src/dfu.c index b8fa42f..4c63861 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -395,3 +395,7 @@ void dfu_setup(usbd_device* usbd_dev, on_state_change(current_dfu_state); } } + +bool dfu_is_idle(void){ + return current_dfu_state == STATE_DFU_IDLE; +} diff --git a/src/dfu.h b/src/dfu.h index d447b22..8bf2b04 100644 --- a/src/dfu.h +++ b/src/dfu.h @@ -38,4 +38,6 @@ extern void dfu_setup(usbd_device* usbd_dev, StateChangeCallback on_state_change, StatusChangeCallback on_status_change); +bool dfu_is_idle (void); + #endif diff --git a/src/stm32f103/bluepill-ch32/config.h b/src/stm32f103/bluepill-ch32/config.h new file mode 100644 index 0000000..cd5534a --- /dev/null +++ b/src/stm32f103/bluepill-ch32/config.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Devan Lai + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + +#ifndef APP_BASE_ADDRESS +#define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) +#endif +#ifndef FLASH_PAGE_SIZE +#define FLASH_PAGE_SIZE 1024 +#endif +#ifndef DFU_UPLOAD_AVAILABLE +#define DFU_UPLOAD_AVAILABLE 1 +#endif +#ifndef DFU_DOWNLOAD_AVAILABLE +#define DFU_DOWNLOAD_AVAILABLE 1 +#endif + +#ifndef HAVE_LED +#define HAVE_LED 1 +#endif +#ifndef LED_OPEN_DRAIN +#define LED_OPEN_DRAIN 1 +#endif +#ifndef LED_GPIO_PORT +#define LED_GPIO_PORT GPIOC +#endif +#ifndef LED_GPIO_PIN +#define LED_GPIO_PIN GPIO13 +#endif + +#ifndef HAVE_BUTTON +#define HAVE_BUTTON 1 +#endif +#ifndef BUTTON_ACTIVE_HIGH +#define BUTTON_ACTIVE_HIGH 1 +#endif +#ifndef BUTTON_GPIO_PORT +#define BUTTON_GPIO_PORT GPIOB +#endif +#ifndef BUTTON_GPIO_PIN +#define BUTTON_GPIO_PIN GPIO2 +#endif +// Blue-Pull has 100k resistors on PB2, so we can't use weak pulls to read it. +#ifndef BUTTON_USES_PULL +#define BUTTON_USES_PULL 0 +#endif + +#ifndef BUTTON_SAMPLE_DELAY_CYCLES +#define BUTTON_SAMPLE_DELAY_CYCLES 1440000 +#endif + +#ifndef HAVE_USB_PULLUP_CONTROL +#define HAVE_USB_PULLUP_CONTROL 0 +#endif + +#ifndef USES_GPIOB +#define USES_GPIOB 1 +#endif + +#ifndef USES_GPIOC +#define USES_GPIOC 1 +#endif + +#ifndef CH32F1 +#define CH32F1 1 +#endif + +#endif diff --git a/src/stm32f103/flash_wch_ext.h b/src/stm32f103/flash_wch_ext.h new file mode 100644 index 0000000..26ecafa --- /dev/null +++ b/src/stm32f103/flash_wch_ext.h @@ -0,0 +1,11 @@ +#ifndef _FLASH_CH_F1_H_ +#define _FLASH_CH_F1_H_ + +#define FLASH_MODEKEYP MMIO32(FLASH_MEM_INTERFACE_BASE + 0x24) + +#define FLASH_CR_PAGE_PROGRAM (1<<16) +#define FLASH_CR_PAGE_ERASE (1<<17) +#define FLASH_CR_BUF_LOAD (1<<18) +#define FLASH_CR_BUF_RST (1<<19) + +#endif diff --git a/src/stm32f103/target_stm32f103.c b/src/stm32f103/target_stm32f103.c index 1965c0e..e1136c8 100644 --- a/src/stm32f103/target_stm32f103.c +++ b/src/stm32f103/target_stm32f103.c @@ -24,8 +24,13 @@ #include #include #include +#include +#include +#include +#include "flash_wch_ext.h" #include "dapboot.h" +#include "dfu.h" #include "target.h" #include "config.h" #include "backup.h" @@ -63,6 +68,10 @@ _Static_assert((FLASH_BASE + FLASH_SIZE_OVERRIDE >= APP_BASE_ADDRESS), #define CMD_BOOT 0x4F42UL #endif + +void target_flash_erase_page(uint32_t adr); +bool target_flash_page ( uint32_t *adr, size_t sz, const uint16_t *buf); + void target_clock_setup(void) { #ifdef USE_HSI /* Set the system clock to 48MHz from the internal RC oscillator. @@ -110,6 +119,12 @@ void target_gpio_setup(void) { gpio_clear(LED_GPIO_PORT, LED_GPIO_PIN); } gpio_set_mode(LED_GPIO_PORT, mode, conf, LED_GPIO_PIN); + + /* add systick for LED blinking */ + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); + systick_set_reload(899999); + systick_interrupt_enable(); + systick_counter_enable(); } #endif @@ -231,6 +246,94 @@ void target_relocate_vector_table(void) { SCB_VTOR = APP_BASE_ADDRESS & 0xFFFF; } +#if defined(CH32F1) && (CH32F1 == 1) +void target_flash_unlock(void){ + FLASH_KEYR = FLASH_KEYR_KEY1; + FLASH_KEYR = FLASH_KEYR_KEY2; + FLASH_MODEKEYP = FLASH_KEYR_KEY1; + FLASH_MODEKEYP = FLASH_KEYR_KEY2; +} + +void target_flash_lock(void) { + FLASH_CR |= FLASH_CR_LOCK; +} + +void target_flash_erase_page(uint32_t adr) { + adr &= ~(0x7f); + FLASH_CR |= FLASH_CR_PAGE_ERASE; + FLASH_AR = adr; + FLASH_CR |= FLASH_CR_STRT; + while ( FLASH_SR & FLASH_SR_BSY ) { } + FLASH_CR &= ~FLASH_CR_PAGE_ERASE; + *(volatile uint32_t*)0x40022034 = *(volatile uint32_t*)(adr^ 0x00000100); // taken from example +} + +bool target_flash_page ( uint32_t *adr, size_t sz, const uint16_t *buf) { + /* if not aligned return false */ + uint32_t prg_adr = (uint32_t) adr; + if ( (prg_adr & 0x7f) != 0 ) return false; + if ( sz > 64 ) return false; // should less than 128byte + FLASH_CR |= FLASH_CR_PAGE_PROGRAM; // enable page programing + FLASH_CR |= FLASH_CR_BUF_RST; // page buffer reset + while ( FLASH_SR & FLASH_SR_BSY ); + FLASH_CR &= ~FLASH_CR_PAGE_PROGRAM; + + while (sz) { + uint32_t cnt = 4; + FLASH_CR |= FLASH_CR_PAGE_PROGRAM; // enable page programing + uint32_t s_adr = (uint32_t) adr; + while ( (sz > 1) && cnt ) { + *adr = * ((uint32_t *)buf); + adr ++; + buf += 2; + sz -= 2; + cnt --; + } + if ( (sz != 0) && cnt ) { + *adr = 0xffff0000 | (*buf); + adr ++; + buf ++; + sz --; + cnt --; + } + FLASH_CR |= FLASH_CR_BUF_LOAD; + while ( FLASH_SR & FLASH_SR_BSY ); + FLASH_CR &= ~FLASH_CR_PAGE_PROGRAM; + *(volatile uint32_t*)0x40022034 = *(volatile uint32_t*)(s_adr ^ 0x00000100); // taken from example + } + + FLASH_CR |= FLASH_CR_PAGE_PROGRAM; // enable page programing + FLASH_AR = prg_adr; + FLASH_CR |= FLASH_CR_STRT; + while ( FLASH_SR & FLASH_SR_BSY ); + FLASH_CR &= ~FLASH_CR_PAGE_PROGRAM; + *(volatile uint32_t*)0x40022034 = *(volatile uint32_t*)(prg_adr ^ 0x00000100); // taken from example + if ( FLASH_SR & (FLASH_SR_PGERR | FLASH_SR_WRPRTERR) ) { + FLASH_SR |= FLASH_SR_PGERR | FLASH_SR_WRPRTERR; + return false; + } + return true; +} + +bool target_flash_program_array(uint16_t* dest, const uint16_t* data, size_t half_word_count) { + size_t cnt; + + if ( ( ((uint32_t) dest ) & 0x7f ) != 0 ) return false; + + for ( cnt = 0; cnt < half_word_count ; cnt+=64 ){ + uint32_t ptr = cnt*2 + ((uint32_t) dest); + size_t sz = half_word_count -cnt; + if ( sz > 64) sz = 64; + target_flash_erase_page( ptr ); + if ( ! target_flash_page( (uint32_t *) ptr, sz, data + cnt ) ) return false; + for ( uint32_t i = 0; i < sz; i++) if ( dest[cnt+i] != data[cnt+i]) return false; + } + + return true; +} + +#else + void target_flash_unlock(void) { flash_unlock(); } @@ -276,3 +379,17 @@ bool target_flash_program_array(uint16_t* dest, const uint16_t* data, size_t hal return verified; } +#endif + +#if HAVE_LED +void sys_tick_handler(void) +{ + static uint8_t count = 0 ; + count ++; + if ( count >= ( dfu_is_idle() ? 5 : 1 ) ){ + count = 0; + gpio_toggle(LED_GPIO_PORT, LED_GPIO_PIN); + } +} + +#endif diff --git a/src/targets.mk b/src/targets.mk index 70aab59..7d2f56c 100644 --- a/src/targets.mk +++ b/src/targets.mk @@ -146,6 +146,12 @@ ifeq ($(TARGET),STM32L1_GENERIC) ARCH = STM32L1 DEFS += -DNDEBUG endif +ifeq ($(TARGET),BLUEPILL_CH32) + TARGET_COMMON_DIR := ./stm32f103 + TARGET_SPEC_DIR := ./stm32f103/bluepill-ch32 + LDSCRIPT := ./stm32f103/stm32f103x8.ld + ARCH = STM32F1 +endif ifndef ARCH $(error Unknown target $(TARGET))