diff --git a/bootloader_hk32f030m_uart_xmodem/.cproject b/bootloader_hk32f030m_uart_xmodem/.cproject index 4d7db8e..882a62b 100644 --- a/bootloader_hk32f030m_uart_xmodem/.cproject +++ b/bootloader_hk32f030m_uart_xmodem/.cproject @@ -26,7 +26,7 @@ - - + @@ -147,6 +151,9 @@ diff --git a/bootloader_hk32f030m_uart_xmodem/.settings/language.settings.xml b/bootloader_hk32f030m_uart_xmodem/.settings/language.settings.xml index ea8a9be..b89d454 100644 --- a/bootloader_hk32f030m_uart_xmodem/.settings/language.settings.xml +++ b/bootloader_hk32f030m_uart_xmodem/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/bootloader_hk32f030m_uart_xmodem/code/inc/flash.h b/bootloader_hk32f030m_uart_xmodem/code/inc/flash.h index 7c430ec..42d9cb3 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/inc/flash.h +++ b/bootloader_hk32f030m_uart_xmodem/code/inc/flash.h @@ -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(); diff --git a/bootloader_hk32f030m_uart_xmodem/code/inc/hk32f030m_conf.h b/bootloader_hk32f030m_uart_xmodem/code/inc/hk32f030m_conf.h index 6cfdcb2..60e21cb 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/inc/hk32f030m_conf.h +++ b/bootloader_hk32f030m_uart_xmodem/code/inc/hk32f030m_conf.h @@ -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" diff --git a/bootloader_hk32f030m_uart_xmodem/code/inc/led_sk.h b/bootloader_hk32f030m_uart_xmodem/code/inc/led_sk.h new file mode 100644 index 0000000..18466f3 --- /dev/null +++ b/bootloader_hk32f030m_uart_xmodem/code/inc/led_sk.h @@ -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 +#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_ */ diff --git a/bootloader_hk32f030m_uart_xmodem/code/inc/user_io.h b/bootloader_hk32f030m_uart_xmodem/code/inc/user_io.h index 5808a18..01d9949 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/inc/user_io.h +++ b/bootloader_hk32f030m_uart_xmodem/code/inc/user_io.h @@ -28,7 +28,6 @@ void user_io_init(); -void user_led_init(); diff --git a/bootloader_hk32f030m_uart_xmodem/code/inc/xmodem.h b/bootloader_hk32f030m_uart_xmodem/code/inc/xmodem.h index c9029c2..18546c7 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/inc/xmodem.h +++ b/bootloader_hk32f030m_uart_xmodem/code/inc/xmodem.h @@ -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; diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/flash.c b/bootloader_hk32f030m_uart_xmodem/code/src/flash.c index e54b261..63107e0 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/src/flash.c +++ b/bootloader_hk32f030m_uart_xmodem/code/src/flash.c @@ -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(); + } } diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/hk32f030m_it.c b/bootloader_hk32f030m_uart_xmodem/code/src/hk32f030m_it.c index f5ce4d7..826320c 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/src/hk32f030m_it.c +++ b/bootloader_hk32f030m_uart_xmodem/code/src/hk32f030m_it.c @@ -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 } /******************************************************************************/ diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/led_sk.c b/bootloader_hk32f030m_uart_xmodem/code/src/led_sk.c new file mode 100644 index 0000000..9fab330 --- /dev/null +++ b/bootloader_hk32f030m_uart_xmodem/code/src/led_sk.c @@ -0,0 +1,100 @@ +/* + * sk_led.c + * + * Created on: July 17, 2023 + * Author: true + * + * communicates with SK68xx LEDs using bitbang. + * + * not yet implemented. + */ + + +#include +#include + +#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 diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/main.c b/bootloader_hk32f030m_uart_xmodem/code/src/main.c index 4297186..2b5650d 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/src/main.c +++ b/bootloader_hk32f030m_uart_xmodem/code/src/main.c @@ -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"); + } } } diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/usart.c b/bootloader_hk32f030m_uart_xmodem/code/src/usart.c index d47d0a3..dae9f4d 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/src/usart.c +++ b/bootloader_hk32f030m_uart_xmodem/code/src/usart.c @@ -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; } diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/user_io.c b/bootloader_hk32f030m_uart_xmodem/code/src/user_io.c index d0f41f7..8df2568 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/src/user_io.c +++ b/bootloader_hk32f030m_uart_xmodem/code/src/user_io.c @@ -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); -} - diff --git a/bootloader_hk32f030m_uart_xmodem/code/src/xmodem.c b/bootloader_hk32f030m_uart_xmodem/code/src/xmodem.c index 8c2143e..e3059f6 100644 --- a/bootloader_hk32f030m_uart_xmodem/code/src/xmodem.c +++ b/bootloader_hk32f030m_uart_xmodem/code/src/xmodem.c @@ -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. */ diff --git a/bootloader_hk32f030m_uart_xmodem/driver/CMSIS/HK32F030M/Source/system_hk32f030m.c b/bootloader_hk32f030m_uart_xmodem/driver/CMSIS/HK32F030M/Source/system_hk32f030m.c index 587273c..25ce14b 100644 --- a/bootloader_hk32f030m_uart_xmodem/driver/CMSIS/HK32F030M/Source/system_hk32f030m.c +++ b/bootloader_hk32f030m_uart_xmodem/driver/CMSIS/HK32F030M/Source/system_hk32f030m.c @@ -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) diff --git a/bootloader_hk32f030m_uart_xmodem/hk32f030mf4p6.ld b/bootloader_hk32f030m_uart_xmodem/hk32f030mf4p6.ld index 19b05cc..eb8dc21 100644 --- a/bootloader_hk32f030m_uart_xmodem/hk32f030mf4p6.ld +++ b/bootloader_hk32f030m_uart_xmodem/hk32f030mf4p6.ld @@ -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 :