Commit 1748ee63 authored by Henrique Silva's avatar Henrique Silva

Implement simple bootloader

This bootloader verifies the last byte of the upgrade flash region,
which holds the new received firmware, and if it's not blank
(0xFFFFFFFF), copies it to the user flash area (0x2000) and runs the
code from there
parent c2fbae7e
......@@ -85,22 +85,27 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "")
set(PROJ_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/afcipm.c)
add_subdirectory(FreeRTOS)
add_subdirectory(port)
add_subdirectory(boot)
add_subdirectory(modules)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(trace)
#add_subdirectory(trace)
endif()
# Libraries path
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
## Create executable
add_executable(${CMAKE_PROJECT_NAME}.axf ${PROJ_SRCS})
add_executable(${CMAKE_PROJECT_NAME} ${LPC17_SRCS} ${PROJ_SRCS})
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${MODULES_FLAGS})
add_executable(bootloader ${BOOT_SRCS} ${LPC17_SRCS})
# Headers path
target_include_directories(${CMAKE_PROJECT_NAME}.axf PUBLIC ${PROJ_HDRS})
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${PROJ_HDRS})
target_include_directories(bootloader PUBLIC ${PROJ_HDRS})
# Link libraries
target_link_libraries(${CMAKE_PROJECT_NAME}.axf gcc c m)
target_link_libraries(${CMAKE_PROJECT_NAME}.axf FreeRTOS)
target_link_libraries(${CMAKE_PROJECT_NAME}.axf lpcopen)
target_link_libraries(${CMAKE_PROJECT_NAME} gcc c m FreeRTOS lpcopen)
target_link_libraries(bootloader gcc c m lpcopen)
##Program command
set(LPCXPRESSO_PATH /usr/local/lpcxpresso_7.8.0_426/lpcxpresso/)
......
set(BOOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
set(BOOT_SRCS ${BOOT_SRCS} ${BOOT_PATH}/boot.c )
set(BOOT_SRCS ${BOOT_SRCS} PARENT_SCOPE)
set(PROJ_HDRS ${PROJ_HDRS} ${BOOT_PATH} PARENT_SCOPE)
#include "chip.h"
#include "boot.h"
#include "iap.h"
int main (void)
{
SystemCoreClockUpdate();
Bool upgrade = FALSE;
uint32_t upgr_fw_id, user_fw_id;
Chip_GPIO_Init(LPC_GPIO);
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 1, 9);
user_fw_id = *(uint32_t*)USER_FLASH_ID_ADDR;
upgr_fw_id = *(uint32_t*)UPGRADE_FLASH_ID_ADDR;
//if(user_fw_id == 0xFFFFFFFF || ((upgr_fw_id != 0xFFFFFFFF) && (user_fw_id < upgr_fw_id))) {
if(upgr_fw_id != 0xFFFFFFFF) {
upgrade = TRUE;
Chip_GPIO_SetPinState(LPC_GPIO, 1, 9, 0 );
}
if (upgrade) {
update_firmware();
}
execute_user_code();
while (1);
}
void program_page( uint32_t address, uint32_t * data, uint32_t size )
{
uint32_t sector_start = (address & 0xFF000) >> 12;
uint32_t sector_end = ((address+size) & 0xFF000) >> 12;
if (size % 256) {
/* Data should be a 256 byte boundary */
return;
}
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
return;
}
Chip_IAP_CopyRamToFlash( address, data, size );
}
void erase_sector( uint32_t sector_start, uint32_t sector_end )
{
if (Chip_IAP_PreSectorForReadWrite( sector_start, sector_end ) != IAP_CMD_SUCCESS) {
return;
}
Chip_IAP_EraseSector( sector_start, sector_end );
}
void execute_user_code( void )
{
USER_ENTRY_PFN user_entry;
user_entry = (USER_ENTRY_PFN)*((uint32_t*)(USER_FLASH_START_ADDR +4));
if (user_entry) {
(user_entry)();
}
}
void update_firmware( void )
{
uint32_t dst = USER_FLASH_START_ADDR;
uint32_t *src = (uint32_t *)UPGRADE_FLASH_START_ADDR;
uint32_t page[64];
for(uint8_t j=0; j<(sizeof(page)/sizeof(uint32_t)); j++) {
page[j] = 0xFFFFFFFF;
}
uint32_t fw_size = USER_FLASH_END_ADDR - USER_FLASH_START_ADDR;
uint32_t offset;
erase_sector( USER_FLASH_START_SECTOR , USER_FLASH_END_SECTOR );
for ( offset = 0; offset < fw_size; dst += sizeof(page)) {
/* Populate a page from source address */
for (uint8_t i = 0; i<sizeof(page)/4; i++, src++, offset+=4 ) {
page[i] = *src;
}
/* Program it into dst */
program_page( dst, page, sizeof(page) );
/* Reset the data in local storage */
for(uint8_t j=0; j<(sizeof(page)/sizeof(uint32_t)); j++) {
page[j] = 0xFFFFFFFF;
}
}
//erase_sector( UPGRADE_FLASH_START_SECTOR , UPGRADE_FLASH_END_SECTOR );
}
#define USER_FLASH_START_ADDR (0x2000)
#define USER_FLASH_START_SECTOR (0x2)
#define USER_FLASH_END_ADDR (0x10000)
#define USER_FLASH_END_SECTOR (0xF)
/* Last 4 bytes are reserved for Firmware Version ID */
#define USER_FLASH_ID_ADDR (0xFFFC)
#define UPGRADE_FLASH_START_ADDR (0x10000)
#define UPGRADE_FLASH_START_SECTOR (0x10)
#define UPGRADE_FLASH_END_ADDR (0x1E000)
#define UPGRADE_FLASH_END_SECTOR (0x11)
/* Last 4 bytes are reserved for Firmware Version ID */
#define UPGRADE_FLASH_ID_ADDR (0x1DFFC)
typedef void (*USER_ENTRY_PFN)();
void erase_sector( uint32_t sector_start, uint32_t sector_end );
void execute_user_code( void );
void update_firmware( void );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment