start application if valid at boot
if the application is not valid, check and start the bootloader Change-Id: I323f2b3a1828d3e40a02c7fc755d07009fb43a85
This commit is contained in:
parent
b0a7dde6a6
commit
388dac3f87
112
usb_dfu_main.c
112
usb_dfu_main.c
|
@ -1,45 +1,95 @@
|
|||
/**
|
||||
* \file
|
||||
* \brief USB DFU bootloader implementation (DFU mode)
|
||||
*
|
||||
* \brief Application implement
|
||||
* Copyright (c) 2018-2019 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||
*
|
||||
* Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
* Copyright (c) 2018 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* \asf_license_start
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip
|
||||
* software and any derivatives exclusively with Microchip products.
|
||||
* It is your responsibility to comply with third party license terms applicable
|
||||
* to your use of third party software (including open source software) that
|
||||
* may accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
|
||||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
|
||||
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
|
||||
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
|
||||
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
|
||||
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
||||
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
|
||||
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
|
||||
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "atmel_start.h"
|
||||
#include "atmel_start_pins.h"
|
||||
|
||||
/** Start address of the application in flash
|
||||
* \remark must be initialized by check_bootloader
|
||||
*/
|
||||
static uint32_t* application_start_address;
|
||||
|
||||
/** Check if the bootloader is valid
|
||||
* \return true if the bootloader is valid and can be run
|
||||
* \remark initializes application_start_address
|
||||
*/
|
||||
static bool check_bootloader(void)
|
||||
{
|
||||
if (hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw) > 15) { // ensure BOOTPROT setting is valid
|
||||
return false;
|
||||
}
|
||||
application_start_address = (uint32_t*)((15 - hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw)) * 8192); // calculate bootloader size to know start address of the application (e.g. after the bootloader)
|
||||
if (0 == application_start_address) { // no space has been reserved for the bootloader
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Check if starting the bootloader is forced
|
||||
* \return true of the DFU bootloader should be started
|
||||
*/
|
||||
static bool check_force_dfu(void)
|
||||
{
|
||||
}
|
||||
|
||||
/** Check if the application is valid
|
||||
* \return true if the application is valid and can be started
|
||||
* \warning application_start_address must be initialized
|
||||
*/
|
||||
static bool check_application(void)
|
||||
{
|
||||
/* the application starts with the vector table
|
||||
* the first entry in the vector table is the initial stack pointer (SP) address
|
||||
* the stack will be placed in RAM which begins at 0x2000 0000, and there is up to 256 KB of RAM (0x40000).
|
||||
* if the SP is not in this range (e.g. flash has been erased) there is no valid application
|
||||
* the second entry in the vector table is the reset address, corresponding to the application start
|
||||
*/
|
||||
return (0x20000000 == ((*application_start_address) & 0xFFF80000));
|
||||
}
|
||||
|
||||
/** Start the application
|
||||
* \warning application_start_address must be initialized
|
||||
*/
|
||||
static void start_application(void)
|
||||
{
|
||||
__set_MSP(*application_start_address); // re-base the Stack Pointer
|
||||
SCB->VTOR = ((uint32_t) application_start_address & SCB_VTOR_TBLOFF_Msk); // re-base the vector table base address
|
||||
asm("bx %0"::"r"(*(application_start_address + 1))); // jump to application Reset Handler in the application */
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
atmel_start_init();
|
||||
usb_dfu();
|
||||
atmel_start_init(); // initialise system
|
||||
if (!check_bootloader()) { // check bootloader
|
||||
// blink the LED to tell the user we don't know where the application starts
|
||||
while (true) {
|
||||
gpio_set_pin_level(LED_SYSTEM, false);
|
||||
delay_ms(500);
|
||||
gpio_set_pin_level(LED_SYSTEM, true);
|
||||
delay_ms(500);
|
||||
}
|
||||
}
|
||||
if (check_application()) { // application is valid
|
||||
start_application(); // start application
|
||||
} else {
|
||||
usb_dfu(); // start DFU bootloader
|
||||
}
|
||||
}
|
||||
|
|
15
usb_start.c
15
usb_start.c
|
@ -82,23 +82,16 @@ void usb_dfu(void)
|
|||
while (!dfudf_is_enabled()); // wait for DFU to be installed
|
||||
gpio_set_pin_level(LED_SYSTEM, false); // switch LED on to indicate USB DFU stack is ready
|
||||
|
||||
uint32_t application_start = hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw); // read BOOTPROT setting to get the bootloader size
|
||||
ASSERT(application_start <= 15);
|
||||
application_start = (15 - application_start) * 8192; // calculate bootloader size to know where we should write the application firmware
|
||||
while (0 == application_start) { // no space has been reserved for the bootloader
|
||||
// blink the LED to tell the user we don't know where the application starts
|
||||
gpio_set_pin_level(LED_SYSTEM, false);
|
||||
delay_ms(500);
|
||||
gpio_set_pin_level(LED_SYSTEM, true);
|
||||
delay_ms(500);
|
||||
}
|
||||
ASSERT(hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw) <= 15);
|
||||
uint32_t application_start_address = (15 - hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw)) * 8192; // calculate bootloader size to know where we should write the application firmware
|
||||
ASSERT(application_start_address > 0);
|
||||
|
||||
while (true) { // main DFU infinite loop
|
||||
// run the second part of the USB DFU state machine handling non-USB aspects
|
||||
if (USB_DFU_STATE_DFU_DNLOAD_SYNC == dfu_state || USB_DFU_STATE_DFU_DNBUSY == dfu_state) { // there is some data to be flashed
|
||||
gpio_set_pin_level(LED_SYSTEM, true); // switch LED off to indicate we are flashing
|
||||
if (dfu_download_length > 0) { // there is some data to be flashed
|
||||
int32_t rc = flash_write(&FLASH_0, application_start + dfu_download_offset, dfu_download_data, dfu_download_length); // write downloaded data chunk to flash
|
||||
int32_t rc = flash_write(&FLASH_0, application_start_address + dfu_download_offset, dfu_download_data, dfu_download_length); // write downloaded data chunk to flash
|
||||
if (ERR_NONE == rc) {
|
||||
dfu_state = USB_DFU_STATE_DFU_DNLOAD_IDLE; // indicate flashing this block has been completed
|
||||
} else { // there has been a programming error
|
||||
|
|
Loading…
Reference in New Issue