Initial bootloader implementation
Took a publicly available XMODEM bootloader and made it work on HK32F. Known issues: - Erase is super slow on this MCU. The upload routine erases all flash before loading, which means the first packet seems to hang. This also erases possibly persistent data stored in unused pages on flash.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#include "systick_delay.h"
|
||||
#include "hk32f030m.h"
|
||||
|
||||
static uint32_t fac_us = 0;
|
||||
static uint32_t fac_ms = 0;
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SysTick_Init
|
||||
* Description : SysTick Initialize
|
||||
* Input : none
|
||||
* Output : none
|
||||
* Return : none
|
||||
* Set SysTick clock source to 1/8 of HCLK
|
||||
*******************************************************************************/
|
||||
void SysTick_Init(void)
|
||||
{
|
||||
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
|
||||
fac_us = SystemCoreClock / 8000000;
|
||||
fac_ms = SystemCoreClock / 8000;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SysTick_DelayUs
|
||||
* Description : delay by microseconds
|
||||
* Input : nus -- number of microseconds
|
||||
* Output : none
|
||||
* Return : none
|
||||
*******************************************************************************/
|
||||
void SysTick_DelayUs(uint32_t nus)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
if (nus > 0)
|
||||
{
|
||||
SysTick->LOAD = nus * fac_us; // Set Reload Value
|
||||
SysTick->VAL = 0x00; // Set Current Value to 0
|
||||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Start counter
|
||||
// Block when SysTick is running and counter flag not set
|
||||
do
|
||||
{
|
||||
temp = SysTick->CTRL;
|
||||
}
|
||||
while ((temp & SysTick_CTRL_ENABLE_Msk) && !(temp & SysTick_CTRL_COUNTFLAG_Msk));
|
||||
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // Stop counter
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SysTick_DelayMs
|
||||
* Description : Delay by milliseconds
|
||||
SysTick->LOAD is 24-bit so the max delay = 0xFFFFFF*8*1000 / SYSCLK
|
||||
* Input : nms -- number of milliseconds
|
||||
*******************************************************************************/
|
||||
void SysTick_DelayMs(uint16_t nms)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
if (nms > 0)
|
||||
{
|
||||
SysTick->LOAD = nms * fac_ms; // Set Reload Value (24-bit)
|
||||
SysTick->VAL = 0x00; // Set Current Value to 0
|
||||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // Start counter
|
||||
// Block when SysTick is running and counter flag not set
|
||||
do
|
||||
{
|
||||
temp = SysTick->CTRL;
|
||||
}
|
||||
while ((temp & SysTick_CTRL_ENABLE_Msk) && !(temp & SysTick_CTRL_COUNTFLAG_Msk));
|
||||
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // Stop counter
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef __SYSTICK_H
|
||||
#define __SYSTICK_H
|
||||
|
||||
#include "hk32f030m.h"
|
||||
|
||||
void SysTick_Init(void);
|
||||
void SysTick_DelayUs(uint32_t nus);
|
||||
void SysTick_DelayMs(uint16_t nms);
|
||||
|
||||
#endif
|
||||
115
bootloader_hk32f030m_uart_xmodem/driver/Debug/uart_printf.c
Normal file
115
bootloader_hk32f030m_uart_xmodem/driver/Debug/uart_printf.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "uart_printf.h"
|
||||
|
||||
#define UART_PRINTF_BAUDRATE 115200
|
||||
|
||||
uint8_t HEX_TABLE[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
|
||||
void UART_PrintfInit(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
|
||||
#if UART_PORTx == UART_PORT_TX_A3_RX_D6
|
||||
// Enable GPIO and UART clock
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOD, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
|
||||
// AF config
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_1);
|
||||
// PA3 As USART TX
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
// PD6 As USART RX
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
#elif UART_PORTx == UART_PORT_TX_A3_RX_B4
|
||||
// Enable GPIO and UART clock
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
|
||||
// AF config
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); // TX
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_4); // RX
|
||||
// PA3 As USART TX
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
// PB4 As USART RX
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
#endif
|
||||
USART_InitStructure.USART_BaudRate = UART_PRINTF_BAUDRATE;
|
||||
// 8-bit, 1 stop bit, no parity, no hardware flow control
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
// Enable Tx
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
// Init and enable UART1
|
||||
USART_Init(USART1, &USART_InitStructure);
|
||||
USART_Cmd(USART1, ENABLE);
|
||||
}
|
||||
|
||||
void UART_SendByte(uint8_t ch)
|
||||
{
|
||||
/* Send one byte to USART */
|
||||
USART_SendData(USART1, ch);
|
||||
/* Block till tx empty flag is set */
|
||||
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
|
||||
}
|
||||
|
||||
void UART_SendArray(uint8_t *array, uint16_t num)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
UART_SendByte(array[i]);
|
||||
}
|
||||
/* Block till transmission is completed */
|
||||
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
|
||||
}
|
||||
|
||||
void UART_SendString(char *str)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
UART_SendByte(*str++);
|
||||
}
|
||||
/* Block till transmission is completed */
|
||||
while (USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
|
||||
}
|
||||
|
||||
void UART_TxHex(uint8_t *hex, uint8_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
UART_SendByte(HEX_TABLE[*(hex + len) >> 4 & 0xF]);
|
||||
UART_SendByte(HEX_TABLE[*(hex + len) & 0xF]);
|
||||
}
|
||||
}
|
||||
|
||||
int __io_putchar(int ch)
|
||||
{
|
||||
UART_SendByte((uint8_t)ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
int DataIdx;
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
__io_putchar(*ptr++);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
18
bootloader_hk32f030m_uart_xmodem/driver/Debug/uart_printf.h
Normal file
18
bootloader_hk32f030m_uart_xmodem/driver/Debug/uart_printf.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __UART_PRINTF_H
|
||||
#define __UART_PRINTF_H
|
||||
|
||||
#include "hk32f030m.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#define UART_PORT_TX_A3_RX_D6 0
|
||||
#define UART_PORT_TX_A3_RX_B4 1
|
||||
#define UART_PORTx UART_PORT_TX_A3_RX_D6
|
||||
|
||||
void UART_PrintfInit(void);
|
||||
void UART_SendByte(uint8_t ch);
|
||||
void UART_SendHalfWord(uint16_t ch);
|
||||
void UART_SendArray(uint8_t *array, uint16_t num);
|
||||
void UART_SendString(char *str);
|
||||
void UART_TxHex(uint8_t *hex, uint8_t len);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user