diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b694c6..2a36a0c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,6 +119,8 @@ jobs: - 'imxrt1020_evk' - 'imxrt1060_evk' - 'metro_m7_1011' + #stm32f3 + - 'stm32f303disco' # stm32f4 - 'feather_stm32f405_express' - 'stm32f411ve_discovery' diff --git a/.gitmodules b/.gitmodules index 1408d1d..3907601 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,9 @@ [submodule "lib/sct_neopixel"] path = lib/sct_neopixel url = https://github.com/gsteiert/sct_neopixel + [submodule "lib/st/stm32f3xx_hal_driver"] + path = lib/st/stm32f3xx_hal_driver + url = https://github.com/STMicroelectronics/stm32f3xx_hal_driver + [submodule "lib/st/cmsis_device_f3"] + path = lib/st/cmsis_device_f3 + url = https://github.com/STMicroelectronics/cmsis_device_f3.git diff --git a/lib/st/cmsis_device_f3 b/lib/st/cmsis_device_f3 new file mode 160000 index 0000000..6cb335b --- /dev/null +++ b/lib/st/cmsis_device_f3 @@ -0,0 +1 @@ +Subproject commit 6cb335bfffcc63caa4e8104cc11ba239556b6f42 diff --git a/lib/st/stm32f3xx_hal_driver b/lib/st/stm32f3xx_hal_driver new file mode 160000 index 0000000..a0007fb --- /dev/null +++ b/lib/st/stm32f3xx_hal_driver @@ -0,0 +1 @@ +Subproject commit a0007fb36cb5eaf2f875aaa133fd06de818c38ae diff --git a/ports/make.mk b/ports/make.mk index 9030922..6f6d863 100644 --- a/ports/make.mk +++ b/ports/make.mk @@ -27,7 +27,7 @@ check_defined = \ __check_defined = \ $(if $(value $1),, \ $(error Undefined make flag: $1$(if $2, ($2)))) - + #-------------- Select the board to build for. ------------ BOARD_LIST = $(sort $(subst /.,,$(subst boards/,,$(wildcard boards/*/.)))) diff --git a/ports/stm32f3/Makefile b/ports/stm32f3/Makefile new file mode 100644 index 0000000..369d0c7 --- /dev/null +++ b/ports/stm32f3/Makefile @@ -0,0 +1,79 @@ +UF2_FAMILY_ID = 0x6b846188 +CROSS_COMPILE = arm-none-eabi- + +ST_HAL_DRIVER = lib/st/stm32f3xx_hal_driver +ST_CMSIS = lib/st/cmsis_device_f3 +CMSIS_5 = lib/CMSIS_5 + +# List of git submodules that is included as part of the UF2 version +GIT_SUBMODULES = CMSIS_5 st/cmsis_device_f3 st/stm32f3xx_hal_driver tinyusb + +include ../make.mk + +# Port Compiler Flags +CFLAGS += \ + -flto \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_STM32F3 + +# suppress warning caused by vendor mcu driver +CFLAGS += -Wno-error=cast-align -Wno-error=unused-parameter + +LD_FILES ?= $(PORT_DIR)/linker/STM32F303VCTx_FLASH.ld + +# Port source +PORT_SRC_C += \ + $(addprefix $(CURRENT_PATH)/, $(wildcard *.c)) \ + $(ST_CMSIS)/Source/Templates/system_stm32f3xx.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_flash.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_flash_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32f3xx_hal_uart.c + +SRC_C += \ + $(PORT_SRC_C) \ + lib/tinyusb/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + +# Port include +INC += \ + $(TOP)/$(CMSIS_5)/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc + +include ../rules.mk + +# flash target ROM bootloader +flash-dfu-util: $(BUILD)/$(OUTNAME).bin + dfu-util -R -a 0 --dfuse-address 0x08000000 -D $< + +#-------------- Self-update -------------- +SELF_CFLAGS = $(CFLAGS) -DTINYUF2_SELF_UPDATE +SELF_LDFLAGS = $(LDFLAGS) +SELF_LD_FILES ?= $(LD_FILES) +SELF_ASFLAGS = $(ASFLAGS) + +include ../self_update.mk + +# self-update uf2 file +$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).uf2: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex + @echo CREATE $@ + $(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^ + +$(SELF_BUILD_OBJ)/$(SELF_OUTNAME).hex: $(SELF_BUILD_OBJ)/$(SELF_OUTNAME).elf + @echo CREATE $@ + @$(OBJCOPY) -O ihex $^ $@ + +# required for self-update elf compile +$(SELF_BUILD_OBJ)/self_update/$(OUTNAME).c: + @echo "const unsigned long bindata_len = 1;" > $@ + @echo "const unsigned char bindata[] __attribute__((aligned(16))) = { 0 };" >> $@ + #$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o $@ diff --git a/ports/stm32f3/board_flash.c b/ports/stm32f3/board_flash.c new file mode 100644 index 0000000..152d723 --- /dev/null +++ b/ports/stm32f3/board_flash.c @@ -0,0 +1,160 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * 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 "board_api.h" +#include "tusb.h" // for logging + +#define FLASH_CACHE_SIZE 512 +#define FLASH_CACHE_INVALID_ADDR 0xffffffff + +//--------------------------------------------------------------------+ +//define flash space, reserve first 8 sectors for bootloader up to 3FFF +//--------------------------------------------------------------------+ + +#define BOARD_FLASH_SECTORS 64 +#define BOARD_FIRST_FLASH_SECTOR_TO_ERASE 8 + +#define APP_LOAD_ADDRESS 0x08004000 + +/* flash parameters */ +#define SIZE 2048 + +static uint8_t erasedSectors[BOARD_FLASH_SECTORS]; + +uint32_t flash_func_sector_size(unsigned sector) +{ + if (sector < BOARD_FLASH_SECTORS) { + return SIZE; + } + + return 0; +} + +static bool is_blank(uint32_t addr, uint32_t size) +{ + for (uint32_t i = 0; i < size; i += sizeof(uint32_t)) { + if (*(uint32_t*)(addr + i) != 0xffffffff) { + return false; + } + } + return true; +} + + //ADDR data +void flash_write(uint32_t dst, const uint8_t *src, int len) +{ + // assume sector 0-7 (bootloader) is same size as sector 1 + uint32_t addr = APP_LOAD_ADDRESS; + uint32_t sector = 0; + int erased = false; + uint32_t size = 0; + + for ( unsigned i = 0; i < BOARD_FLASH_SECTORS; i++ ) + { + size = flash_func_sector_size(i); + if ( addr + size > dst ) + { + sector = i + 1; + erased = erasedSectors[i]; + erasedSectors[i] = 1; // don't erase anymore - we will continue writing here! + break; + } + addr += size; + } + + if (sector == 0) + { + TU_LOG1("invalid sector"); + } + + HAL_FLASH_Unlock(); + + if (!erased && !is_blank(addr, size)) + { + uint32_t SectorError = 0; + + TU_LOG1("Erase: %08lX size = %lu\n", addr, size); + + FLASH_EraseInitTypeDef EraseInit; + EraseInit.TypeErase = FLASH_TYPEERASE_PAGES; + EraseInit.PageAddress = addr; + EraseInit.NbPages = ((0x08040000 - addr)/size); + + HAL_FLASHEx_Erase(&EraseInit, &SectorError); + FLASH_WaitForLastOperation(HAL_MAX_DELAY); + + if (SectorError != 0xFFFFFFFF) + { + TU_LOG1("failed to erase!"); + } + } + + for (int i = 0; i < len; i += 4) + { + HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, dst + i, (uint64_t) (*(uint32_t*)(src + i)) ); + } + + if (memcmp((void*)dst, src, len) != 0) + { + TU_LOG1("failed to write"); + } +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +void board_flash_init(void) +{ + +} + +uint32_t board_flash_size(void) +{ + return BOARD_FLASH_SIZE; +} + +void board_flash_read(uint32_t addr, void* buffer, uint32_t len) +{ + memcpy(buffer, (void*) addr, len); +} + +void board_flash_flush(void) +{ +} + +// TODO not working quite yet +void board_flash_write (uint32_t addr, void const *data, uint32_t len) +{ + // TODO skip matching contents + flash_write(addr, data, len); +} + + +#ifdef TINYUF2_SELF_UPDATE +void board_self_update(const uint8_t * bootloader_bin, uint32_t bootloader_len) +{ + (void) bootloader_bin; + (void) bootloader_len; +} +#endif diff --git a/ports/stm32f3/boards.c b/ports/stm32f3/boards.c new file mode 100644 index 0000000..013fd18 --- /dev/null +++ b/ports/stm32f3/boards.c @@ -0,0 +1,327 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * 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 "board_api.h" +#include "stm32f3xx_hal.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +#define STM32_UUID ((uint32_t *)0x1FFFF7AC) + +static UART_HandleTypeDef UartHandle; + +void board_init(void) +{ + clock_init(); + SystemCoreClockUpdate(); + + // disable systick + board_timer_stop(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStruct; + + #ifdef BUTTON_PIN + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + #endif + + #ifdef LED_PIN + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + board_led_write(0); + #endif + + #if NEOPIXEL_NUMBER + GPIO_InitStruct.Pin = NEOPIXEL_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(NEOPIXEL_PORT, &GPIO_InitStruct); + #endif + + #if defined(UART_DEV) && CFG_TUSB_DEBUG + UART_CLOCK_ENABLE(); + + GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART2; + HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct); + + UartHandle.Instance = UART_DEV; + UartHandle.Init.BaudRate = 115200; + UartHandle.Init.WordLength = UART_WORDLENGTH_8B; + UartHandle.Init.StopBits = UART_STOPBITS_1; + UartHandle.Init.Parity = UART_PARITY_NONE; + UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + UartHandle.Init.Mode = UART_MODE_TX_RX; + HAL_UART_Init(&UartHandle); + #endif +} + +void board_dfu_init(void) +{ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_REMAPINTERRUPT_USB_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF14_USB; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // Enable USB clock + __HAL_RCC_USB_CLK_ENABLE(); +} + +void board_dfu_complete(void) +{ + NVIC_SystemReset(); +} + +bool board_app_valid(void) +{ + if((((*(uint32_t*)BOARD_FLASH_APP_START) - BOARD_RAM_START) <= BOARD_RAM_SIZE)) // && ((*(uint32_t*)BOARD_FLASH_APP_START + 4) > BOARD_FLASH_APP_START) && ((*(uint32_t*)BOARD_FLASH_APP_START + 4) < BOARD_FLASH_APP_START + BOARD_FLASH_SIZE) + { + return true; + } else + { + return false; + } +} + +void board_app_jump(void) +{ + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); + + #ifdef BUTTON_PIN + HAL_GPIO_DeInit(BUTTON_PORT, BUTTON_PIN); + #endif + + #ifdef LED_PIN + HAL_GPIO_DeInit(LED_PORT, LED_PIN); + #endif + + #if NEOPIXEL_NUMBER + HAL_GPIO_DeInit(NEOPIXEL_PORT, NEOPIXEL_PIN); + #endif + + #if defined(UART_DEV) && CFG_TUSB_DEBUG + HAL_UART_DeInit(&UartHandle); + HAL_GPIO_DeInit(UART_GPIO_PORT, UART_TX_PIN | UART_RX_PIN); + #endif + + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12 | GPIO_PIN_11); + + __HAL_RCC_GPIOA_CLK_DISABLE(); + __HAL_RCC_GPIOB_CLK_DISABLE(); + __HAL_RCC_GPIOC_CLK_DISABLE(); + __HAL_RCC_GPIOD_CLK_DISABLE(); + __HAL_RCC_GPIOE_CLK_DISABLE(); + + HAL_RCC_DeInit(); + HAL_DeInit(); + + // TODO protect bootloader region + + volatile uint32_t const * app_vector = (volatile uint32_t const*) BOARD_FLASH_APP_START; + + /* switch exception handlers to the application */ + SCB->VTOR = (uint32_t) BOARD_FLASH_APP_START; + + // Set stack pointer + __set_MSP(app_vector[0]); + + // Jump to Application Entry + asm("bx %0" ::"r"(app_vector[1])); +} + +uint8_t board_usb_get_serial(uint8_t serial_id[16]) +{ + uint8_t const len = 12; + memcpy(serial_id, STM32_UUID, len); + return len; +} + +//--------------------------------------------------------------------+ +// LED pattern +//--------------------------------------------------------------------+ + +void board_led_write(uint32_t state) +{ + HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +#if NEOPIXEL_NUMBER +#define MAGIC_800_INT 900000 // ~1.11 us -> 1.2 field +#define MAGIC_800_T0H 2800000 // ~0.36 us -> 0.44 field +#define MAGIC_800_T1H 1350000 // ~0.74 us -> 0.84 field + +static inline uint8_t apply_percentage(uint8_t brightness) +{ + return (uint8_t) ((brightness*NEOPIXEL_BRIGHTNESS) >> 8); +} + +void board_rgb_write(uint8_t const rgb[]) +{ + // neopixel color order is GRB + uint8_t const pixels[3] = { apply_percentage(rgb[1]), apply_percentage(rgb[0]), apply_percentage(rgb[2]) }; + uint32_t const numBytes = 3; + + uint8_t const *p = pixels, *end = p + numBytes; + uint8_t pix = *p++, mask = 0x80; + uint32_t start = 0; + uint32_t cyc = 0; + + //assumes 800_000Hz frequency + //Theoretical values here are 800_000 -> 1.25us, 2500000->0.4us, 1250000->0.8us + //TODO: try to get dynamic weighting working again + uint32_t const sys_freq = HAL_RCC_GetSysClockFreq(); + uint32_t const interval = sys_freq/MAGIC_800_INT; + uint32_t const t0 = sys_freq/MAGIC_800_T0H; + uint32_t const t1 = sys_freq/MAGIC_800_T1H; + + __disable_irq(); + + // Enable DWT in debug core. Useable when interrupts disabled, as opposed to Systick->VAL + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + DWT->CYCCNT = 0; + + for(;;) { + cyc = (pix & mask) ? t1 : t0; + start = DWT->CYCCNT; + + HAL_GPIO_WritePin(NEOPIXEL_PORT, NEOPIXEL_PIN, 1); + while((DWT->CYCCNT - start) < cyc); + + HAL_GPIO_WritePin(NEOPIXEL_PORT, NEOPIXEL_PIN, 0); + while((DWT->CYCCNT - start) < interval); + + if(!(mask >>= 1)) { + if(p >= end) break; + pix = *p++; + mask = 0x80; + } + } + + __enable_irq(); +} + +#else + +void board_rgb_write(uint8_t const rgb[]) +{ + (void) rgb; +} + +#endif + +//--------------------------------------------------------------------+ +// Timer +//--------------------------------------------------------------------+ + +void board_timer_start(uint32_t ms) +{ + SysTick_Config( (SystemCoreClock/1000) * ms ); +} + +void board_timer_stop(void) +{ + SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; +} + +void SysTick_Handler (void) +{ + board_timer_handler(); +} + +int board_uart_write(void const * buf, int len) +{ +#if defined(UART_DEV) && CFG_TUSB_DEBUG + HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xffff); + return len; +#else + (void) buf; (void) len; + (void) UartHandle; + return 0; +#endif +} + +#ifndef TINYUF2_SELF_UPDATE + +// Forward USB interrupt events to TinyUSB IRQ Handler +void USB_HP_IRQHandler(void) +{ + tud_int_handler(0); +} + +// USB low-priority interrupt (Channel 75): Triggered by all USB events +// (Correct transfer, USB reset, etc.). The firmware has to check the +// interrupt source before serving the interrupt. +void USB_LP_IRQHandler(void) +{ + tud_int_handler(0); +} + +// USB wakeup interrupt (Channel 76): Triggered by the wakeup event from the USB +// Suspend mode. +void USBWakeUp_RMP_IRQHandler(void) +{ + tud_int_handler(0); +} + +#endif + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) +{ + +} diff --git a/ports/stm32f3/boards.h b/ports/stm32f3/boards.h new file mode 100644 index 0000000..25880e1 --- /dev/null +++ b/ports/stm32f3/boards.h @@ -0,0 +1,60 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries + * + * 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 BOARDS_H_ +#define BOARDS_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "stm32f3xx.h" +#include "stm32f3xx_hal_conf.h" + +#include "board.h" + +// Flash Start Address of Application +#define BOARD_FLASH_APP_START 0x08004000 +#define BOARD_RAM_START 0x20000000 +#define BOARD_RAM_SIZE 0x9FFF + +// Double Reset tap to enter DFU +#define TINYUF2_DFU_DOUBLE_TAP 1 + +//#define USE_RGB NEOPIXEL_NUMBER + +// Brightness percentage from 1 to 255 +#ifndef NEOPIXEL_BRIGHTNESS +#define NEOPIXEL_BRIGHTNESS 0x10 +#endif + +#ifdef LED_PIN +#define TINYUF2_LED 1 +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* BOARDS_H_ */ diff --git a/ports/stm32f3/boards/stm32f303disco/board.h b/ports/stm32f3/boards/stm32f303disco/board.h new file mode 100644 index 0000000..9c9e187 --- /dev/null +++ b/ports/stm32f3/boards/stm32f303disco/board.h @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Ha Thach for Adafruit Industries + * + * 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 BOARD_H_ +#define BOARD_H_ + +//--------------------------------------------------------------------+ +// LED +//--------------------------------------------------------------------+ + +#define LED_PORT GPIOE +#define LED_PIN GPIO_PIN_10 +#define LED_STATE_ON 1 + +//#define BUTTON_PORT GPIOA +//#define BUTTON_PIN GPIO_PIN_0 +//#define BUTTON_STATE_ACTIVE 1 + + +//--------------------------------------------------------------------+ +// Neopixel +//--------------------------------------------------------------------+ + +//// Number of neopixels +#define NEOPIXEL_NUMBER 0 + +//#define NEOPIXEL_PORT GPIOC +//#define NEOPIXEL_PIN GPIO_PIN_0 +// +//// Brightness percentage from 1 to 255 +//#define NEOPIXEL_BRIGHTNESS 0x10 + + +//--------------------------------------------------------------------+ +// Flash +//--------------------------------------------------------------------+ + +// Flash size of the board +#define BOARD_FLASH_SIZE (256 * 1024) + +//--------------------------------------------------------------------+ +// USB UF2 +//--------------------------------------------------------------------+ + +// TODO VID/PID aren't assigned for this board +#define USB_VID 0xcafe +#define USB_PID 0xffff +#define USB_MANUFACTURER "ST" +#define USB_PRODUCT "STM32F303 Discovery" + +#define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT +#define UF2_BOARD_ID "STM32F303 discovery" +#define UF2_VOLUME_LABEL "F303BOOT" +#define UF2_INDEX_URL "https://www.st.com/en/evaluation-tools/stm32f3discovery.html" + +//--------------------------------------------------------------------+ +// UART +//--------------------------------------------------------------------+ + +#define UART_DEV USART1 +#define UART_CLOCK_ENABLE __HAL_RCC_USART1_CLK_ENABLE +#define UART_GPIO_PORT GPIOC +#define UART_GPIO_AF GPIO_AF7_USART1 +#define UART_TX_PIN GPIO_PIN_4 +#define UART_RX_PIN GPIO_PIN_5 + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +static inline void clock_init(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit; + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + HAL_RCCEx_GetPeriphCLKConfig(&RCC_PeriphClkInit); + RCC_PeriphClkInit.USBClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; + HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit); + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); + + /* Enable Power Clock */ + __HAL_RCC_PWR_CLK_ENABLE(); +} + +#endif diff --git a/ports/stm32f3/boards/stm32f303disco/board.mk b/ports/stm32f3/boards/stm32f303disco/board.mk new file mode 100644 index 0000000..90403f5 --- /dev/null +++ b/ports/stm32f3/boards/stm32f303disco/board.mk @@ -0,0 +1,12 @@ +CFLAGS += \ + -DSTM32F303xC \ + -DHSE_VALUE=8000000U + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f303xc.s + +# For flash-jlink target +JLINK_DEVICE = stm32f303vc + +flash: flash-stlink +erase: erase-stlink diff --git a/ports/stm32f3/linker/STM32F303VCTx_FLASH.ld b/ports/stm32f3/linker/STM32F303VCTx_FLASH.ld new file mode 100644 index 0000000..d1f8268 --- /dev/null +++ b/ports/stm32f3/linker/STM32F303VCTx_FLASH.ld @@ -0,0 +1,188 @@ +/* +***************************************************************************** +** + +** File : LinkerScript.ld +** +** Abstract : Linker script for STM32F303VCTx Device with +** 256KByte FLASH, 40KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +** (c)Copyright Ac6. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Ac6 permit registered System Workbench for MCU users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the System Workbench for MCU toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ +_board_dfu_dbl_tap = _estack; +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x800;; /* required amount of heap */ +_Min_Stack_Size = 0x800;; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 40K - 4 +CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 8K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/ports/stm32f3/stm32f3xx_hal_conf.h b/ports/stm32f3/stm32f3xx_hal_conf.h new file mode 100644 index 0000000..8915708 --- /dev/null +++ b/ports/stm32f3/stm32f3xx_hal_conf.h @@ -0,0 +1,360 @@ +/** + ****************************************************************************** + * @file stm32f3xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *