Bootloader fixes and updates

- Add canary value for bootloader entry
- Fix initial GPIO config for this application
This commit is contained in:
true 2023-11-12 16:59:53 -08:00
parent 60bd8d88b7
commit 00e0dcecf3
16 changed files with 391 additions and 161 deletions

View File

@ -26,7 +26,7 @@
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.1731985094" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/HK32F030}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.2105898051" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.1554269278" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.1585453989" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.value.g3" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.1585453989" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.value.g" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.definedsymbols.1865848605" name="Define symbols (-D)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.definedsymbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="HK32F030MF4P6"/>
<listOptionValue builtIn="false" value="DEBUG"/>
@ -34,7 +34,7 @@
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.442647076" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.1307943124" name="MCU GCC Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.275567753" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g3" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.275567753" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.107146637" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.value.os" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths.1426651896" name="Include paths (-I)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../code/Inc"/>
@ -67,6 +67,7 @@
<listOptionValue builtIn="false" value="-Wl,--print-memory-usage "/>
<listOptionValue builtIn="false" value="-flto"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.additionalobjs.1911493690" name="Additional object files" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.additionalobjs" useByScannerDiscovery="false" valueType="userObjs"/>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input.126424436" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
@ -125,20 +126,23 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.1732678459" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g0" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.255812759" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.value.os" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths.1226273585" name="Include paths (-I)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../Core/Inc"/>
<listOptionValue builtIn="false" value="../Driver"/>
<listOptionValue builtIn="false" value="../Driver/CMSIS"/>
<listOptionValue builtIn="false" value="../Driver/CMSIS/CM0"/>
<listOptionValue builtIn="false" value="../Driver/CMSIS/CM0/Core"/>
<listOptionValue builtIn="false" value="../Driver/CMSIS/HK32F030M"/>
<listOptionValue builtIn="false" value="../Driver/CMSIS/HK32F030M/Include"/>
<listOptionValue builtIn="false" value="../Driver/HK32F030M_Driver"/>
<listOptionValue builtIn="false" value="../Driver/HK32F030M_Driver/inc"/>
<listOptionValue builtIn="false" value="../Driver/Debug"/>
<listOptionValue builtIn="false" value="../code/inc"/>
<listOptionValue builtIn="false" value="../driver"/>
<listOptionValue builtIn="false" value="../driver/CMSIS"/>
<listOptionValue builtIn="false" value="../driver/CMSIS/CM0"/>
<listOptionValue builtIn="false" value="../driver/CMSIS/CM0/Core"/>
<listOptionValue builtIn="false" value="../driver/CMSIS/HK32F030M"/>
<listOptionValue builtIn="false" value="../driver/CMSIS/HK32F030M/Include"/>
<listOptionValue builtIn="false" value="../driver/HK32F030M_Driver"/>
<listOptionValue builtIn="false" value="../driver/HK32F030M_Driver/inc"/>
<listOptionValue builtIn="false" value="../driver/Debug"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols.961335129" name="Define symbols (-D)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="HK32F030MF4P6"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.otherflags.1089769918" name="Other flags" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.otherflags" useByScannerDiscovery="true" valueType="stringList">
<listOptionValue builtIn="false" value="-flto"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.2142076333" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.658452460" name="MCU G++ Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler">
@ -147,6 +151,9 @@
</tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.1697196118" name="MCU GCC Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script.1268634419" name="Linker Script (-T)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script" value="../hk32f030mf4p6.ld" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.otherflags.1190913368" name="Other flags" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.otherflags" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="-flto"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input.14629567" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>

View File

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1638107307847132480" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-654819543574176800" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1732493928911893298" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-654819543574176800" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@ -33,8 +33,13 @@ typedef enum {
extern uint32_t bootcheck;
BL_flash_status flash_erase_page(uint32_t addr);
BL_flash_status flash_write(uint32_t addr, uint8_t *data, uint16_t length);
void jump_to_user_app();

View File

@ -64,7 +64,7 @@
//#include "hk32f030m_i2c.h"
//#include "hk32f030m_iwdg.h"
#include "hk32f030m_pwr.h"
//#include "hk32f030m_spi.h"
#include "hk32f030m_spi.h"
//#include "hk32f030m_tim.h"
#include "hk32f030m_usart.h"
//#include "hk32f030m_iwdg.h"

View File

@ -0,0 +1,47 @@
/*
* sk_led.h
*
* Created on: Jul 17, 2023
* Author: true
*/
#ifndef CODE_INC_LED_SK_H_
#define CODE_INC_LED_SK_H_
#include <stdint.h>
#include "hk32f030m.h"
#define SK6X_PORT GPIOD
#define SK6X_PIN (1 << 4)
#define SK6X_LED_COUNT 5
#ifdef USE_SK_LEDS
void led_init();
void led_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b);
void led_set_all(uint8_t r, uint8_t g, uint8_t b);
void led_tx();
#else
#define led_init()
#define led_set(i, r, g, b)
#define led_set_all(r, g, b)
#define led_tx()
#endif
#endif /* CODE_INC_LED_SK_H_ */

View File

@ -28,7 +28,6 @@
void user_io_init();
void user_led_init();

View File

@ -64,12 +64,13 @@
/* Status report for the functions. */
typedef enum {
X_OK = 0x00u, /**< The action was successful. */
X_ERROR_CRC = 0x01u, /**< CRC calculation error. */
X_ERROR_NUMBER = 0x02u, /**< Packet number mismatch error. */
X_ERROR_UART = 0x04u, /**< UART communication error. */
X_ERROR_FLASH = 0x08u, /**< Flash related error. */
X_ERROR = 0xFFu /**< Generic error. */
X_OK = 0x00u, /**< The action was successful. */
X_ERROR_CRC = 0x01u, /**< CRC calculation error. */
X_ERROR_NUMBER = 0x02u, /**< Packet number mismatch error. */
X_ERROR_UART = 0x04u, /**< UART communication error. */
X_ERROR_FLASH = 0x08u, /**< Flash related error. */
X_TIMEOUT = 0xfe,
X_ERROR = 0xFFu /**< Generic error. */
} BL_xmodem_status;

View File

@ -8,6 +8,8 @@
#include "hk32f030m.h"
#include "flash.h"
#include "led_sk.h"
/**
@ -42,6 +44,10 @@ __attribute__ ((long_call, section(".ramfunc"))) BL_flash_status flash_write(uin
FLASH_Unlock();
// note: using the halfword programming method instead of the byte method
// uses approximately 20 more bytes of program space, and might only
// be slightly faster.
/* Loop through the data. */
for (uint32_t i = 0u; (i < length) && (status == FLASH_OK); i++) {
if (addr >= USER_APP_END_ADDR) {
@ -72,39 +78,28 @@ void jump_to_user_app()
{
void (*user_app)(void);
// stop systick interrupt; reset to defaults
SysTick->CTRL = 0;
SysTick->LOAD = 0xffffff;
SysTick->VAL = 0xffffff;
// check reset key to know what to do
if (bootcheck == 0x1337b007) {
// configure jump location
user_app = (void (*)(void))(*(volatile uint32_t *)(USER_APP_START_ADDR + 4));
// stop USART; reset to defaults
USART1->CR1 = 0;
USART1->CR1 = 0;
USART1->BRR = 0;
// configure stack pointer
__set_MSP(*(volatile uint32_t*)USER_APP_START_ADDR);
// configure GPIO back to default
GPIOA->PUPDR = (uint32_t)0xffff; // although marked as reserved, it is the default per datasheet
GPIOA->MODER = (uint32_t)0xffff;
GPIOB->MODER = (uint32_t)0xfbff;
GPIOD->MODER = (uint32_t)0xfbff;
// configure interrupt vector table
// SCB->VTOR = USER_APP_START_ADDR;
// disable configured interrupts
// NVIC->ICER[0] = 0;
// cortex m0 doesn't have VTOR to remap vector table.
// to address this, HK MCU has a flash offset thing which
// remaps 256 bytes specified by an offset, to to 0x08000000
FLASH->INT_VEC_OFFSET = USER_APP_START_ADDR & 0x3ffc;
// configure jump location
user_app = (void (*)(void))(*(volatile uint32_t *)(USER_APP_START_ADDR + 4));
// configure stack pointer
__set_MSP(*(volatile uint32_t*)USER_APP_START_ADDR);
// configure interrupt vector table
// SCB->VTOR = USER_APP_START_ADDR;
// cortex m0 doesn't have VTOR to remap vector table.
// to address this, HK MCU has a flash offset thing which
// remaps 256 bytes specified by an offset, to to 0x08000000
FLASH->INT_VEC_OFFSET = USER_APP_START_ADDR & 0x3ffc;
// let's do this
user_app();
// let's do this
user_app();
} else {
// we want the MCU to be at default settings
// so set our flag, then reboot
bootcheck = 0x1337b007;
NVIC_SystemReset();
}
}

View File

@ -120,13 +120,8 @@ __attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void)
led ^= 1;
#if LED_ACT_DIR == 0
if (led) LED_PORT->BRR = (1 << LED_PIN);
else LED_PORT->BSRR = (1 << LED_PIN);
#else
if (led) LED_PORT->BSRR = (1 << LED_PIN);
else LED_PORT->BRR = (1 << LED_PIN);
#endif
}
/******************************************************************************/

View File

@ -0,0 +1,100 @@
/*
* sk_led.c
*
* Created on: July 17, 2023
* Author: true
*
* communicates with SK68xx LEDs using bitbang.
*
* not yet implemented.
*/
#include <led_sk.h>
#include <stdint.h>
#include "hk32f030m.h"
#define SPI_TX_PORT GPIOD
#define SPI_MOSI_PINSRC GPIO_PinSource2
#define SK_SET() SK6X_PORT->BSRR = SK6X_PIN;
#define SK_CLR() SK6X_PORT->BRR = SK6X_PIN;
#define SK_SEND_BIT1() __NOP(); __NOP(); SK_CLR(); __NOP();
#define SK_SEND_BIT0() SK_CLR(); __NOP(); __NOP(); __NOP();
uint8_t sk6x_led[SK6X_LED_COUNT][3] = {0}; // G-R-B order
const uint8_t adxl_cmds[] = {0x80, 0x80, 0x80};
#ifdef USE_SK_LEDS
void led_init()
{
uint8_t idx;
// enable SPI with appropriate settings to talk to ADXL
GPIO_PinAFConfig(SPI_TX_PORT, SPI_MOSI_PINSRC, GPIO_AF_2);
// disable ADXL interrupts, configure INT1 pin active low (so idle high)
volatile uint8_t *spi_dr = (volatile uint8_t *)((uint32_t)SPI1 + 0x0c);
// transfer all of our data
idx = 0;
while (idx < sizeof(adxl_cmds)) {
// transmit FIFO has space? if so, send byte
if ((SPI1->SR & SPI_SR_FTLVL) != SPI_SR_FTLVL) {
*spi_dr = adxl_cmds[idx];
idx++;
}
}
}
void led_tx()
{
uint8_t i;
uint16_t j;
uint8_t b;
uint8_t *p;
p = sk6x_led[0];
for (i = 0; i < SK6X_LED_COUNT; i++) {
b = *p;
p++;
j = 0x100;
do {
j >>= 1;
SK_SET();
if (!(b & j)) { SK_SEND_BIT0(); } else { SK_SEND_BIT1(); }
} while (j);
}
}
void led_set(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
sk6x_led[idx][0] = g;
sk6x_led[idx][1] = r;
sk6x_led[idx][2] = b;
}
void led_set_all(uint8_t r, uint8_t g, uint8_t b)
{
uint8_t i;
for (i = 0; i < SK6X_LED_COUNT; i++) {
led_set(i, r, g, b);
}
}
#endif

View File

@ -20,15 +20,90 @@
__attribute__((section(".noinit"))) uint32_t bootcheck;
void welcome_banner()
{
uint8_t i;
comm_tx_str("\r\n\r\n");
for (i = 0; i < 31; i++) {
comm_tx_byte('=');
}
comm_tx_str("\r\ntrueControl HK32F Loader v0.0.3\r\n");
for (i = 0; i < 31; i++) {
comm_tx_byte('=');
}
}
int main(void)
{
uint32_t i;
uint32_t x;
uint32_t btn;
uint8_t flash_empty = 0;
// ensure the bootloader is write protected
// TODO
x = *(volatile uint32_t *)USER_APP_START_ADDR; // first byte of user flash
if ((x == 0x00000000) || (x == 0xffffffff)) {
flash_empty = 1;
}
// configure button and LED
// if we software reset, but have contents in flash
if (!flash_empty && (RCC->CSR & RCC_CSR_SFTRSTF)) {
// and have the bootload done key loaded,
if (bootcheck == 0x1337b007) {
// then forego all of this shit and jump to the user app
jump_to_user_app();
}
}
/*
// set with a debugger to enable this codepath (testing)
volatile uint8_t do_this = 0;
// make sure bootloader is write protected before we write anything to main flash
const uint8_t pages = (uint8_t)(OB_WRP_Pages0to3 | OB_WRP_Pages4to7);
uint8_t pagecheck = (uint8_t)(~FLASH_OB_GetWRP());
if (do_this && (pagecheck & pages) != pages) {
uint32_t flash_cr;
uint16_t wrp0;
uint32_t wrp_addr = FLASH_OB_WRP_ADDRESS;
uint16_t i;
wrp0 = (uint16_t)((pages << 8) | (~pages & 0xff));
FLASH_Unlock();
FLASH_OB_Unlock();
flash_cr = FLASH->CR;
for(i = 0; i < 2; i++) {
FLASH->CR = flash_cr | FLASH_CR_OPTER;
FLASH->AR = wrp_addr;
FLASH->CR = flash_cr | FLASH_CR_OPTER | FLASH_CR_STRT;
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
wrp_addr++;
}
FLASH->CR = flash_cr | FLASH_CR_OPTPG;
OB->WRP0 = wrp0;
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
FLASH->CR = flash_cr;
NVIC_SystemReset();
}
*/
// start clocks used by peripherals
RCC->AHBENR = RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | \
RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD;
RCC->APB2ENR = RCC_APB2Periph_USART1;
// set up user IO
user_io_init();
// get button state
@ -38,41 +113,39 @@ int main(void)
#endif
// bootloader activation methods
i = *(volatile uint32_t *)USER_APP_START_ADDR; // first byte of user flash
if (btn || (i == 0x00000000) || (i = 0xffffffff)) { // is button pushed, or flash empty?
// bootloader is activated; configure systick to flash LED
user_led_init();
// configure serial comms and print welcome banner
// todo: implement autobaud?
if (btn || flash_empty) { // is button pushed, or flash empty or null?
// bootloader is activated
// this is where you can can blink an LED... at least
// when you don't fuck up your circuit so the LED doesn't work
// in our case we start up systick to do the blinker for us
SysTick_Config(8000000 / 20);
// configure serial comms
comm_init();
comm_tx_byte('\r');
comm_tx_byte('\n');
for (i = 0; i < 31; i++) {
comm_tx_byte('=');
}
comm_tx_str("\r\ntrueControl HK32F Loader v0.0.2\r\n");
for (i = 0; i < 31; i++) {
comm_tx_byte('=');
}
welcome_banner();
// wait for firmware load or reset
while(1) {
while (1) {
// announce bootloader start
comm_tx_str("\r\n\r\nsend firmware file using XMODEM\r\n\r\n");
comm_tx_str("\r\n\r\nsend firm.bin file using XMODEM\r\n\r\n");
// start listening for data and letting user know to send XMODEM data
if (xmodem_receive() == X_OK) {
comm_tx_str("\r\nflash updated; booting.\r\n\r\n");
x = xmodem_receive();
if (x == X_OK) {
comm_tx_str("\r\nfw updated; starting...\r\n\r\n");
break;
}
// if xmodem exits, there was a failure. repeat the process.
comm_tx_str("\r\nfailed to update; try again.\r\n");
// if we've spammed enough, then reboot so the banner is shown again
if (x == X_TIMEOUT) {
welcome_banner();
} else {
// if xmodem_receive exits, there was a failure. repeat the process.
comm_tx_str("\r\nfailed to update. try again.\r\n");
}
}
}

View File

@ -44,9 +44,11 @@ void comm_init()
// enable GPIO clock
// RCC_AHBPeriphClockCmd(USART_TX_GPIO_CLK | USART_RX_GPIO_CLK, ENABLE);
// configure USART GPIO
GPIO_PinAFConfig(USART_TX_PORT, USART_TX_PINSRC, GPIO_AF_1);
GPIO_PinAFConfig(USART_RX_PORT, USART_RX_PINSRC, GPIO_AF_1);
// attach USART peripheral to pins
// GPIO_PinAFConfig(USART_TX_PORT, USART_TX_PINSRC, GPIO_AF_1);
// GPIO_PinAFConfig(USART_RX_PORT, USART_RX_PINSRC, GPIO_AF_1);
GPIOB->AFR[0] = 0x00010000;
GPIOD->AFR[0] = 0x00000010;
/* these have been configured in user_io.c to save space
USART_RX_PORT->MODER &= ~(GPIO_MODER_MODER0 << 2 * USART_RX_PIN);
@ -59,18 +61,18 @@ void comm_init()
*/
// enable USART clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// configure USART peripheral manually
// we do this as the library bloats flash space (division, verbose, ...)
USART1->CR1 = 0; // disable USART
USART1->CR1 = USART_Mode_Rx | USART_Mode_Tx; // 8 bits, no parity, tx/rx enabled
USART1->CR2 = 0; // 1 stop bit
USART1->CR3 = 0;
USART1->CR1 = USART_Mode_Rx | USART_Mode_Tx; // 8 bits, no parity, tx/rx enabled
USART1->BRR = 0x45; // 115200 baud rate @8MHz (per datasheet)
// enable USART
USART1->CR1 |= USART_CR1_UE;
USART1->CR1 = USART_Mode_Rx | USART_Mode_Tx | USART_CR1_UE;
}
/**
@ -86,15 +88,15 @@ BL_comm_status comm_rx(uint8_t *data, uint16_t length)
for (i = 0; i < length; i++) {
timeout = COMM_TIMEOUT;
while (!(USART1->ISR & USART_ISR_RXNE_Msk) && timeout) {
while (!(USART1->ISR & USART_ISR_RXNE) && timeout) {
timeout--;
}
if (timeout) {
// there is new data waiting for us
// we didn't time out and now there is new data waiting for us
data[i] = USART1->RDR;
} else {
// there is no data returned in time
// no data returned in time
return COMM_ERROR;
}
}
@ -111,7 +113,7 @@ BL_comm_status comm_tx_byte(uint8_t data)
{
USART_SendData(USART1, data);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
while (!(USART1->ISR & USART_ISR_TXE));
return COMM_OK;
}
@ -132,7 +134,7 @@ BL_comm_status comm_tx_str(char *data)
comm_tx_byte(data[i]);
}
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
while (!(USART1->ISR & USART_ISR_TC));
return COMM_OK;
}

View File

@ -13,10 +13,10 @@
void user_io_init()
{
// enable gpio clocks
RCC_AHBPeriphClockCmd(BTN_CLK | LED_CLK | RCC_AHBPeriph_GPIOB, ENABLE);
/* --original method, not space efficient
// enable gpio clocks
// RCC_AHBPeriphClockCmd(BTN_CLK | LED_CLK | RCC_AHBPeriph_GPIOB, ENABLE);
// configure led
#if LED_ACT_DIR == 0
LED_PORT->BSRR = (1 << LED_PIN); // idle high
@ -59,16 +59,15 @@ void user_io_init()
// configure LED as PP output, USART TX as AF
LED_PORT->OTYPER = 0;
LED_PORT->OSPEEDR = 0;
LED_PORT->MODER = 0x800 | (GPIO_Mode_OUT << (2 * LED_PIN)) | (GPIO_Mode_AF << (2 * 1));
LED_PORT->ODR = 0;
LED_PORT->MODER = 0x800
| (GPIO_Mode_OUT << (2 * 7))
| (GPIO_Mode_AF << (2 * 1));
// configure I2C SCK as low PP output
GPIOC->ODR = 0;
GPIOC->MODER = (GPIO_Mode_OUT << (2 * 6));
// configure USART RX as AF
GPIOB->MODER = 0x800 | (GPIO_Mode_AF << (2 * 4));
GPIOB->MODER = 0x800 | (GPIO_Mode_AF << (2 * 4));
}
void user_led_init()
{
// led blinking timer; set LED flash rate here
SysTick_Config(8000000 / 20);
}

View File

@ -17,9 +17,10 @@
/* Global variables. */
static uint8_t xmodem_packet_number = 1u; /**< Packet number counter. */
static uint32_t xmodem_flash_w_addr = 0u; /**< Address where we have to write. */
static uint8_t x_first_packet_rcvd = 0; /**< First packet or not. */
static uint8_t xmodem_packet_number; /**< Packet number counter. */
static uint32_t xmodem_flash_w_addr; /**< Address where we have to write. */
static uint8_t x_first_packet_rcvd; /**< First packet or not. */
/* Local functions. */
static uint16_t xmodem_calc_crc(uint8_t *data, uint16_t length);
@ -43,6 +44,8 @@ BL_xmodem_status xmodem_receive(void)
xmodem_packet_number = 1u;
xmodem_flash_w_addr = USER_APP_START_ADDR;
uint8_t x_c_sent = 0;
/* Loop until there isn't any error (or until we jump to the user application). */
while (status == X_OK) {
uint8_t header = 0x00u;
@ -52,6 +55,13 @@ BL_xmodem_status xmodem_receive(void)
/* Spam the host (until we receive something) with ACSII "C", to notify it, we want to use CRC-16. */
if ((status_c != COMM_OK) && (x_first_packet_rcvd == 0)) {
// return with timeout if we've tried too many times
// this is so main can repeat our banner
x_c_sent++;
if (x_c_sent >= 240) {
return X_TIMEOUT;
}
comm_tx_byte(X_C);
}
@ -101,8 +111,7 @@ BL_xmodem_status xmodem_receive(void)
/* Abort from host. */
case X_CAN: {
status = X_ERROR;
break;
return X_ERROR;
}
/* Wrong header. */

View File

@ -121,47 +121,49 @@ void SystemInit(void)
*/
static void SetSysClock(void)
{
/*reload the hsi trimming value to the bit3~bit13 of RCC_CR register */
uint32_t u32HSIFLASH = 0;
uint32_t u32RCC_CR = 0;
uint32_t u32HSITemp = 0;
uint16_t u16HSITempH = 0;
uint16_t u16HSITempL = 0;
u32HSIFLASH = *(uint32_t *) 0x1FFFF820;
u16HSITempH = (uint16_t)(u32HSIFLASH>>16);
u16HSITempL = (uint16_t)(u32HSIFLASH);
if(!(u16HSITempH & u16HSITempL))
{
u32HSITemp = RCC->CR;
u32HSITemp &= (uint32_t)((uint32_t)~(RCC_CR_HSITRIM|RCC_CR_HSICAL));
u32RCC_CR = (uint32_t)(((u16HSITempL & 0x001F) <<3) | (((u16HSITempL>>5) & 0x003F)<<8));
RCC->CR |= u32RCC_CR;
}
/*end*/
#if(SYSCLK_SOURCE==SYSCLK_SRC_HSI8M)
// reload the HSI trimming value to bits 3~13 of RCC_CR register
// note: cannot find documentation for the actual values of this register
// but upon looking it appears to be inverted nybbles
// no idea what the high 5 bits are for...
uint32_t u32HSIFLASH = 0;
uint32_t u32HSITemp = 0;
uint16_t u16HSITempH = 0;
uint16_t u16HSITempL = 0;
u32HSIFLASH = *(uint32_t *)0x1FFFF820;
u16HSITempH = (uint16_t)(u32HSIFLASH >> 16);
u16HSITempL = (uint16_t)(u32HSIFLASH);
if((u16HSITempH ^ u16HSITempL) == 0xffff) {
// valid constants found; load to registers
u32HSITemp = RCC->CR & ~(RCC_CR_HSITRIM | RCC_CR_HSICAL);
u32HSITemp |= (uint32_t)(
((u16HSITempL & 0x001F) << 3) | // HSITRIM (RCC_CR[7:3], 5 bits)
(((u16HSITempL) & 0x07e0) << 3)); // HSICAL (RCC_RC[13:8], 6 bits)
RCC->CR = u32HSITemp;
}
// set system clock
#if (SYSCLK_SOURCE == SYSCLK_SRC_HSI8M)
SetSysClockToHSI();
#elif(SYSCLK_SOURCE == SYSCLK_SRC_HSI16M)
#elif (SYSCLK_SOURCE == SYSCLK_SRC_HSI16M)
SetSysClockToHSI();
#elif(SYSCLK_SOURCE == SYSCLK_SRC_HSI32M)
#elif (SYSCLK_SOURCE == SYSCLK_SRC_HSI32M)
SetSysClockToHSI();
#elif(SYSCLK_SOURCE == SYSCLK_SRC_LSI)
#elif (SYSCLK_SOURCE == SYSCLK_SRC_LSI)
SetSysClockToLSI();
#elif(SYSCLK_SOURCE == SYSCLK_SCR_EXTCLK_IO)
#elif (SYSCLK_SOURCE == SYSCLK_SCR_EXTCLK_IO)
SetSysClockToEXTCLK();
#endif
/* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */
// If none of the define above is enabled, the HSI is used as System clock source (default after reset)
}
#ifdef SYSCLK_FREQ_HSI
static void SetSysClockToHSI(void)
{
__IO uint32_t StartUpCounter = 0, HSIStatus = 0;
__IO uint32_t ACRreg = 0;
__IO uint32_t RCCHCLKReg = 0;
__IO uint32_t RCCPCLKReg = 0;
uint32_t work;
/* Enable HSI */
RCC->CR |= RCC_CR_HSION;
@ -179,26 +181,14 @@ static void SetSysClockToHSI(void)
} while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSIRDY) != RESET) {
HSIStatus = (uint32_t)0x01;
} else {
HSIStatus = (uint32_t)0x00;
}
if (HSIStatus == (uint32_t)0x01) {
/* Flash wait state */
ACRreg = FLASH->ACR;
ACRreg &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR = (uint32_t)(SET_FLASH_LATENCY | ACRreg);
FLASH->ACR = SET_FLASH_LATENCY;
/* HCLK = configured divided value from SYSCLK (which will later be set to HSI32M) */
RCCHCLKReg = RCC->CFGR;
RCCHCLKReg &= (uint32_t)((uint32_t)~RCC_CFGR_HPRE_Msk);
RCC->CFGR = (uint32_t)(SET_HPRE_DIV | RCCHCLKReg);
/* PCLK = HCLK */
RCCPCLKReg = RCC->CFGR;
RCCPCLKReg &= (uint32_t)((uint32_t)~RCC_CFGR_PPRE_Msk);
RCC->CFGR = (uint32_t)(RCC_CFGR_PPRE_DIV1|RCCPCLKReg);
work = RCC->CFGR;
work &= (uint32_t)((uint32_t)~(RCC_CFGR_HPRE | RCC_CFGR_PPRE));
RCC->CFGR = (uint32_t)(SET_HPRE_DIV | RCC_CFGR_PPRE_DIV1 | work);
/* Select HSI32M as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
@ -210,7 +200,7 @@ static void SetSysClockToHSI(void)
/* If clock fails to start, the application will have wrong clock configuration.
* User can add some code here to deal with this error
*/
}
}
}
#elif (SYSCLK_SOURCE == SYSCLK_SRC_LSI)

View File

@ -29,8 +29,9 @@ _Min_Stack_Size = 0x800; /* required amount of stack: 2048 bytes */
/* Specify the memory areas */
MEMORY
{
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
RAM (rwx) : ORIGIN = 0x20000004, LENGTH = 4K - 4
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
NOINIT (rwx) : ORIGIN = 0x20000000, LENGTH = 4
}
/* Define output sections */
@ -100,6 +101,13 @@ SECTIONS
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Uninitialized, non-zeroed data */
.noinit (NOLOAD):
{
/* place all symbols in input sections that start with .noinit */
KEEP(*(*.noinit*))
} > NOINIT
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :