bootloader: flash page erase is on-demand, now fits in 2K
Flash pages are only erased as needed during the flash routine, which makes flashing faster as well as making the transfer consistent. Later datasheets have the flash clock set to 2MHz. I've set it to 2MHz here. I may undo this change later depending on how slow loading a 14K firmware feels. Was able to save enough space to reduce bootloader size from almost 2.5K to 2K exactly. Adjusted flash offsets to start from 0x800. GPIO values are now mostly reset to power-on defaults. Fixed some formatting. Removed dead code.
This commit is contained in:
@@ -15,8 +15,9 @@
|
||||
|
||||
#define FLASH_SIZE 16384 // size of overall flash available on MCU
|
||||
#define FLASH_ERASE_PAGE_SIZE ((uint16_t)0x80) // erase page size
|
||||
#define FLASH_ERASE_PAGE_MASK 0x7f // bitmask of page size
|
||||
|
||||
#define USER_APP_START_ADDR ((uint32_t)FLASH_BASE + 0xa00) // 2560 bytes (20 pages) rsvd for bootloader
|
||||
#define USER_APP_START_ADDR ((uint32_t)FLASH_BASE + 0x800) // 2048 bytes (16 pages) rsvd for bootloader
|
||||
#define USER_APP_END_ADDR ((uint32_t)FLASH_BASE + FLASH_SIZE)
|
||||
|
||||
|
||||
@@ -32,7 +33,7 @@ typedef enum {
|
||||
|
||||
|
||||
|
||||
BL_flash_status flash_erase_user_app();
|
||||
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();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define CODE_INC_USART_H_
|
||||
|
||||
|
||||
#define COMM_TIMEOUT 512000;
|
||||
#define COMM_TIMEOUT 0xffff;
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ typedef enum {
|
||||
|
||||
void comm_init();
|
||||
BL_comm_status comm_rx(uint8_t *data, uint16_t length);
|
||||
BL_comm_status comm_tx_str(uint8_t *data);
|
||||
BL_comm_status comm_tx_str(char *data);
|
||||
BL_comm_status comm_tx_byte(uint8_t data);
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
void user_io_init();
|
||||
void user_led_init();
|
||||
void user_led_set(uint8_t lit);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,9 @@ typedef enum {
|
||||
X_ERROR = 0xFFu /**< Generic error. */
|
||||
} BL_xmodem_status;
|
||||
|
||||
void xmodem_receive(void);
|
||||
|
||||
|
||||
BL_xmodem_status xmodem_receive(void);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,49 +11,22 @@
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function erases the user application area, from start to end of flash.
|
||||
* @brief This function erases a single flash page.
|
||||
* @return status: Report about the success of the erasing.
|
||||
*/
|
||||
__attribute__ ((long_call, section(".ramfunc"))) BL_flash_status flash_erase_user_app()
|
||||
__attribute__ ((long_call, section(".ramfunc"))) BL_flash_status flash_erase_page(uint32_t addr)
|
||||
{
|
||||
// uint32_t timeout;
|
||||
uint32_t page;
|
||||
BL_flash_status status = FLASH_ERROR;
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
for (page = USER_APP_START_ADDR; page < USER_APP_END_ADDR; page += FLASH_ERASE_PAGE_SIZE) {
|
||||
if (FLASH_ErasePage(page) != FLASH_COMPLETE) {
|
||||
FLASH_Lock();
|
||||
return FLASH_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
// clear end of operation bit
|
||||
FLASH->SR &= ~FLASH_FLAG_EOP;
|
||||
|
||||
// start erasing page
|
||||
FLASH->CR |= FLASH_CR_PER;
|
||||
FLASH->AR = page;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
// wait wait for operation to complete
|
||||
timeout = FLASH_ER_PRG_TIMEOUT;
|
||||
while ((FLASH->SR & FLASH_FLAG_BSY)) {
|
||||
timeout--;
|
||||
if (!timeout) {
|
||||
FLASH_Lock();
|
||||
return FLASH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// disable page erase bit
|
||||
FLASH->CR &= ~FLASH_CR_PER;
|
||||
*/
|
||||
if (FLASH_ErasePage(addr) == FLASH_COMPLETE) {
|
||||
status = FLASH_OK;
|
||||
}
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
return FLASH_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,23 +44,23 @@ __attribute__ ((long_call, section(".ramfunc"))) BL_flash_status flash_write(uin
|
||||
|
||||
/* Loop through the data. */
|
||||
for (uint32_t i = 0u; (i < length) && (status == FLASH_OK); i++) {
|
||||
if (addr >= USER_APP_END_ADDR) {
|
||||
status = FLASH_ERROR_SIZE;
|
||||
break;
|
||||
} else {
|
||||
/* The actual flashing. If there is an error, then report it. */
|
||||
if (FLASH_ProgramByte(addr, data[i]) != FLASH_COMPLETE) {
|
||||
status |= FLASH_ERROR_WRITE;
|
||||
}
|
||||
if (addr >= USER_APP_END_ADDR) {
|
||||
status = FLASH_ERROR_SIZE;
|
||||
break;
|
||||
} else {
|
||||
/* The actual flashing. If there is an error, then report it. */
|
||||
if (FLASH_ProgramByte(addr, data[i]) != FLASH_COMPLETE) {
|
||||
status |= FLASH_ERROR_WRITE;
|
||||
}
|
||||
|
||||
/* Read back the content of the memory. If it is wrong, then report an error. */
|
||||
if (data[i] != (*(volatile uint8_t *)addr)) {
|
||||
status |= FLASH_ERROR_VERIFY;
|
||||
}
|
||||
/* Read back the content of the memory. If it is wrong, then report an error. */
|
||||
if (data[i] != (*(volatile uint8_t *)addr)) {
|
||||
status |= FLASH_ERROR_VERIFY;
|
||||
}
|
||||
|
||||
/* Shift the address by a word. */
|
||||
addr++;
|
||||
}
|
||||
/* Shift the address by a word. */
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
FLASH_Lock();
|
||||
@@ -109,6 +82,12 @@ void jump_to_user_app()
|
||||
USART1->CR1 = 0;
|
||||
USART1->BRR = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
// disable configured interrupts
|
||||
// NVIC->ICER[0] = 0;
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t btn;
|
||||
//volatile uint16_t timeout = 0xffff;
|
||||
uint32_t i;
|
||||
uint32_t btn;
|
||||
|
||||
// ensure the bootloader is write protected
|
||||
// TODO
|
||||
@@ -31,9 +31,6 @@ int main(void)
|
||||
// configure button and LED
|
||||
user_io_init();
|
||||
|
||||
// need a small delay to ensure the button pullup/down will charge/discharge pin capacitance
|
||||
//while (--timeout);
|
||||
|
||||
// get button state
|
||||
btn = BTN_PORT->IDR & (1 << BTN_PIN);
|
||||
#if BTN_ACT_DIR == 0
|
||||
@@ -41,34 +38,45 @@ int main(void)
|
||||
#endif
|
||||
|
||||
// bootloader activation methods
|
||||
if (btn // button pushed
|
||||
|| (*(volatile uint32_t *)USER_APP_START_ADDR) == 0x00000000 // flash empty
|
||||
|| (*(volatile uint32_t *)USER_APP_START_ADDR) == 0xFFFFFFFF) { // flash empty
|
||||
|
||||
// bootloader is activated, show it
|
||||
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?
|
||||
comm_init();
|
||||
|
||||
const uint8_t *banner_bar = (uint8_t *)"\r\n================================================\r\n";
|
||||
comm_tx_str((uint8_t *)banner_bar);
|
||||
comm_tx_str((uint8_t *)"trueControl HK32F XMODEM Flash Bootloader v0.0.1");
|
||||
comm_tx_str((uint8_t *)banner_bar);
|
||||
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('=');
|
||||
}
|
||||
|
||||
// wait for firmware load or reset
|
||||
while(1) {
|
||||
comm_tx_str((uint8_t*)"\r\nsend binary file using XMODEM to update firmware");
|
||||
comm_tx_str((uint8_t*)"\r\nthe first data block will take time. it's normal\r\n\r\n");
|
||||
xmodem_receive();
|
||||
// announce bootloader start
|
||||
comm_tx_str("\r\n\r\nsend firmware 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");
|
||||
break;
|
||||
}
|
||||
|
||||
// if xmodem exits, there was a failure. repeat the process.
|
||||
comm_tx_str((uint8_t*)"\r\nfailed to update. try again.\r\n");
|
||||
comm_tx_str("\r\nfailed to update; try again.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
// bootloader is not activated; jump to user code
|
||||
// bootloader is either done not activated; jump to user code
|
||||
jump_to_user_app();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,16 +41,14 @@ uint16_t rxlen = 0;
|
||||
*/
|
||||
void comm_init()
|
||||
{
|
||||
// USART_InitTypeDef usart;
|
||||
// NVIC_InitTypeDef nvic;
|
||||
|
||||
// enable GPIO clock
|
||||
RCC_AHBPeriphClockCmd(USART_TX_GPIO_CLK | USART_RX_GPIO_CLK, ENABLE);
|
||||
// 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);
|
||||
|
||||
/* these have been configured in user_io.c to save space
|
||||
USART_RX_PORT->MODER &= ~(GPIO_MODER_MODER0 << 2 * USART_RX_PIN);
|
||||
USART_RX_PORT->MODER |= (GPIO_Mode_AF << 2 * USART_RX_PIN); // alt function
|
||||
|
||||
@@ -58,46 +56,25 @@ void comm_init()
|
||||
USART_TX_PORT->OTYPER &= ~(GPIO_OTYPER_OT_0 << USART_TX_PIN); // push pull
|
||||
USART_TX_PORT->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEEDR0 << 2 * USART_TX_PIN); // slow
|
||||
USART_TX_PORT->MODER |= (GPIO_Mode_AF << 2 * USART_TX_PIN); // alt function
|
||||
|
||||
// configure NVIC
|
||||
/*
|
||||
nvic.NVIC_IRQChannel = USART1_IRQn;
|
||||
nvic.NVIC_IRQChannelPriority = 1;
|
||||
nvic.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&nvic);
|
||||
*/
|
||||
|
||||
// enable USART clock
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
|
||||
|
||||
/*
|
||||
// configure USART peripheral
|
||||
usart.USART_BaudRate = BAUDRATE;
|
||||
usart.USART_WordLength = USART_WordLength_8b;
|
||||
usart.USART_StopBits = USART_StopBits_1;
|
||||
usart.USART_Parity = USART_Parity_No;
|
||||
usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_Init(USART1, &usart);
|
||||
*/
|
||||
|
||||
// configure USART peripheral manually
|
||||
// we do this as the library uses division which bloats flash space
|
||||
// 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->BRR = 0x45; // 115200 baud rate @8MHz (per datasheet)
|
||||
|
||||
// enable USART interrupts
|
||||
// USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
|
||||
|
||||
// enable USART
|
||||
USART1->CR1 |= USART_CR1_UE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data from USART.
|
||||
* @brief Receives data from USART in a polling manner.
|
||||
* @param *data: Array to save the received data.
|
||||
* @param length: Size of the data.
|
||||
* @return status: Report about the success of the receiving.
|
||||
@@ -107,24 +84,8 @@ BL_comm_status comm_rx(uint8_t *data, uint16_t length)
|
||||
uint16_t i;
|
||||
uint16_t timeout;
|
||||
|
||||
/*
|
||||
// wait for more data to arrive
|
||||
timeout = COMM_TIMEOUT;
|
||||
while (rxlen < length) {
|
||||
timeout--;
|
||||
if (!timeout) return COMM_RX_TIMEOUT;
|
||||
}
|
||||
|
||||
// copy data to final buffer
|
||||
for (i = 0; i < length; i++) {
|
||||
data[i] = rxbuf[rxptr++];
|
||||
if (rxptr >= RX_BUF_LEN) rxptr = 0;
|
||||
rxlen--;
|
||||
}
|
||||
*/
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
timeout = 0xffff;
|
||||
timeout = COMM_TIMEOUT;
|
||||
while (!(USART1->ISR & USART_ISR_RXNE_Msk) && timeout) {
|
||||
timeout--;
|
||||
}
|
||||
@@ -160,40 +121,19 @@ BL_comm_status comm_tx_byte(uint8_t data)
|
||||
* @param *data: String array.
|
||||
* @return status: Report about the success of the transmission.
|
||||
*/
|
||||
BL_comm_status comm_tx_str(uint8_t *data)
|
||||
BL_comm_status comm_tx_str(char *data)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t len = 0;
|
||||
|
||||
len = strlen((const char *)data);
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
comm_tx_byte(data[i]);
|
||||
}
|
||||
|
||||
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
|
||||
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
|
||||
|
||||
return COMM_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
void USART1_IRQHandler()
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
if (USART1->ISR & USART_ISR_RXNE_Msk) {
|
||||
// read data
|
||||
data = USART1->RDR;
|
||||
|
||||
// only add data if there is room
|
||||
if (rxlen >= RX_BUF_LEN) return;
|
||||
rxlen++;
|
||||
|
||||
// next position
|
||||
if (++rxptr >= RX_BUF_LEN) rxptr = 0;
|
||||
|
||||
// save data
|
||||
rxbuf[rxptr] = data;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
void user_io_init()
|
||||
{
|
||||
// enable gpio clocks
|
||||
RCC_AHBPeriphClockCmd(BTN_CLK | LED_CLK, ENABLE);
|
||||
RCC_AHBPeriphClockCmd(BTN_CLK | LED_CLK | RCC_AHBPeriph_GPIOB, ENABLE);
|
||||
|
||||
/* --original method, not space efficient
|
||||
// configure led
|
||||
#if LED_ACT_DIR == 0
|
||||
LED_PORT->BSRR = (1 << LED_PIN); // idle high
|
||||
@@ -25,16 +26,44 @@ void user_io_init()
|
||||
LED_PORT->OTYPER &= ~(GPIO_OTYPER_OT_0 << LED_PIN); // push pull
|
||||
LED_PORT->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEEDR0 << 2 * LED_PIN); // slow
|
||||
LED_PORT->MODER &= ~(GPIO_MODER_MODER0 << 2 * LED_PIN);
|
||||
LED_PORT->MODER |= (GPIO_Mode_OUT << 2 * LED_PIN); // output
|
||||
LED_PORT->MODER = (GPIO_Mode_OUT << 2 * LED_PIN); // output
|
||||
|
||||
// configure button
|
||||
BTN_PORT->MODER &= ~(GPIO_MODER_MODER0 << 2 * BTN_PIN); // input
|
||||
BTN_PORT->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << 2 * BTN_PIN);
|
||||
#if BTN_ACT_DIR == 0
|
||||
BTN_PORT->PUPDR |= (GPIO_PuPd_UP << 2 * BTN_PIN); // pulled high
|
||||
//BTN_PORT->PUPDR |= (GPIO_PuPd_UP << 2 * BTN_PIN); // pulled high
|
||||
BTN_PORT->PUPDR = (GPIO_PuPd_UP << 2 * BTN_PIN); // pulled high
|
||||
#else
|
||||
BTN_PORT->PUPDR |= (GPIO_PuPd_DOWN << 2 * BTN_PIN); // pulled low
|
||||
//BTN_PORT->PUPDR |= (GPIO_PuPd_DOWN << 2 * BTN_PIN); // pulled low
|
||||
BTN_PORT->PUPDR = (GPIO_PuPd_DOWN << 2 * BTN_PIN); // pulled low
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* new method, configure USART pins at the same time as LED and btn
|
||||
* at they are on the same ports
|
||||
*/
|
||||
|
||||
// default MODER for GPIOB and GPIOD are 0xFBFF
|
||||
// pin 5 _must_ be configured as AF, otherwise you'll kill debugging!
|
||||
|
||||
// configure button as input
|
||||
BTN_PORT->MODER = 0x0;
|
||||
#if BTN_ACT_DIR == 0
|
||||
//BTN_PORT->PUPDR |= (GPIO_PuPd_UP << 2 * BTN_PIN); // pulled high
|
||||
BTN_PORT->PUPDR = (GPIO_PuPd_UP << 2 * BTN_PIN); // pulled high
|
||||
#else
|
||||
//BTN_PORT->PUPDR |= (GPIO_PuPd_DOWN << 2 * BTN_PIN); // pulled low
|
||||
BTN_PORT->PUPDR = (GPIO_PuPd_DOWN << 2 * BTN_PIN); // pulled low
|
||||
#endif
|
||||
|
||||
// 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));
|
||||
|
||||
// configure USART RX as AF
|
||||
GPIOB->MODER = 0x800 | (GPIO_Mode_AF << (2 * 4));
|
||||
}
|
||||
|
||||
void user_led_init()
|
||||
@@ -43,14 +72,3 @@ void user_led_init()
|
||||
SysTick_Config(8000000 / 20);
|
||||
}
|
||||
|
||||
void user_led_set(uint8_t lit)
|
||||
{
|
||||
#if LED_ACT_DIR == 0
|
||||
if (lit) LED_PORT->BRR = (1 << LED_PIN);
|
||||
else LED_PORT->BSRR = (1 << LED_PIN);
|
||||
#else
|
||||
if (lit) LED_PORT->BSRR = (1 << LED_PIN);
|
||||
else LED_PORT->BRR = (1 << LED_PIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ static BL_xmodem_status xmodem_error_handler(uint8_t *error_number, uint8_t max_
|
||||
* @param void
|
||||
* @return void
|
||||
*/
|
||||
void xmodem_receive(void)
|
||||
BL_xmodem_status xmodem_receive(void)
|
||||
{
|
||||
volatile BL_xmodem_status status = X_OK;
|
||||
uint8_t error_number = 0u;
|
||||
@@ -51,7 +51,7 @@ void xmodem_receive(void)
|
||||
BL_comm_status status_c = comm_rx(&header, 1);
|
||||
|
||||
/* 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 == false)) {
|
||||
if ((status_c != COMM_OK) && (x_first_packet_rcvd == 0)) {
|
||||
comm_tx_byte(X_C);
|
||||
}
|
||||
|
||||
@@ -96,9 +96,7 @@ void xmodem_receive(void)
|
||||
case X_EOT: {
|
||||
/* ACK, feedback to user (as a text), then jump to user application. */
|
||||
comm_tx_byte(X_ACK);
|
||||
comm_tx_str((uint8_t*)"\r\nfirmware updated.\r\nstarting firmware.\r\n\r\n");
|
||||
jump_to_user_app();
|
||||
break;
|
||||
return X_OK;
|
||||
}
|
||||
|
||||
/* Abort from host. */
|
||||
@@ -116,6 +114,8 @@ void xmodem_receive(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,22 +127,19 @@ void xmodem_receive(void)
|
||||
static uint16_t xmodem_calc_crc(uint8_t *data, uint16_t length)
|
||||
{
|
||||
uint16_t crc = 0u;
|
||||
while (length)
|
||||
{
|
||||
|
||||
while (length) {
|
||||
length--;
|
||||
crc = crc ^ ((uint16_t)*data++ << 8u);
|
||||
for (uint8_t i = 0u; i < 8u; i++)
|
||||
{
|
||||
if (crc & 0x8000u)
|
||||
{
|
||||
for (uint8_t i = 0u; i < 8u; i++) {
|
||||
if (crc & 0x8000u) {
|
||||
crc = (crc << 1u) ^ 0x1021u;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
crc = crc << 1u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
@@ -154,7 +151,8 @@ static uint16_t xmodem_calc_crc(uint8_t *data, uint16_t length)
|
||||
static BL_xmodem_status xmodem_handle_packet(uint8_t header)
|
||||
{
|
||||
BL_xmodem_status status = X_OK;
|
||||
uint16_t size = 0u;
|
||||
uint16_t size = 0;
|
||||
uint32_t i;
|
||||
|
||||
/* 2 bytes for packet number, 1024 for data, 2 for CRC*/
|
||||
uint8_t rcvd_packet_number[X_PACKET_NUMBER_SIZE];
|
||||
@@ -190,13 +188,9 @@ static BL_xmodem_status xmodem_handle_packet(uint8_t header)
|
||||
status |= X_ERROR_UART;
|
||||
}
|
||||
|
||||
/* If it is the first packet, then erase the memory. */
|
||||
if ((status == X_OK) && (x_first_packet_rcvd == false)) {
|
||||
if (flash_erase_user_app() == FLASH_OK) {
|
||||
x_first_packet_rcvd = true;
|
||||
} else {
|
||||
status |= X_ERROR_FLASH;
|
||||
}
|
||||
/* If it is the first packet, then mark it. If you want to erase all flash, do it here. */
|
||||
if ((status == X_OK)) { // && (x_first_packet_rcvd == 0)) {
|
||||
x_first_packet_rcvd = 1;
|
||||
}
|
||||
|
||||
/* Error handling and flashing. */
|
||||
@@ -219,11 +213,22 @@ static BL_xmodem_status xmodem_handle_packet(uint8_t header)
|
||||
}
|
||||
|
||||
/* Do the actual flashing if there weren't any errors. */
|
||||
if ((status == X_OK) &&
|
||||
(flash_write(xmodem_flash_w_addr, rcvd_packet_data, size)) != FLASH_OK) {
|
||||
if (status == X_OK) {
|
||||
/* first, erase pages depending on size */
|
||||
for (i = 0; i < size; i += FLASH_ERASE_PAGE_SIZE) {
|
||||
if (flash_erase_page(xmodem_flash_w_addr + i) != FLASH_OK) {
|
||||
/* Flashing error. */
|
||||
status |= X_ERROR_FLASH;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flashing error. */
|
||||
status |= X_ERROR_FLASH;
|
||||
/* then write data to these cleared pages */
|
||||
if (status == X_OK) {
|
||||
if (flash_write(xmodem_flash_w_addr, rcvd_packet_data, size) != FLASH_OK) {
|
||||
/* Flashing error. */
|
||||
status |= X_ERROR_FLASH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Raise the packet number and the address counters (if there weren't any errors). */
|
||||
|
||||
Reference in New Issue
Block a user