Select Git revision
-
Damien George authored
Blanket wide to all .c and .h files. Some files originating from ST are difficult to deal with (license wise) so it was left out of those. Also merged modpyb.h, modos.h, modstm.h and modtime.h in stmhal/.
Damien George authoredBlanket wide to all .c and .h files. Some files originating from ST are difficult to deal with (license wise) so it was left out of those. Also merged modpyb.h, modos.h, modstm.h and modtime.h in stmhal/.
main.c NaN GiB
#include "bootloader.h"
#include "card10-version.h"
#include "card10.h"
#include "led.h"
#include "pb.h"
#include "pmic.h"
#include "board.h"
#include "crc.h"
#include "crc16-ccitt.h"
#include "ff.h"
#include "flc.h"
#include "i2c.h"
#include "icc.h"
#include "mxc_config.h"
#include "mxc_delay.h"
#include "mxc_sys.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define GPIO_PORT_IN PORT_1
#define GPIO_PIN_IN PIN_6
#define PARTITION_START (0x10000000 + 64 * 1024)
#define PARTITION_END (0x10000000 + 1024 * 1024 - 1)
#define MSC_MAGIC 0x6E697807
/* TODO: Make this address part of the linker script */
void* API_CALL_MEM = (void*)0x20080000;
DIR dir;
FATFS FatFs;
int format(void)
{
BYTE work[FF_MAX_SS * 16];
/* Create FAT volume */
int res = f_mkfs("", FM_ANY | FM_SFD, 0, work, sizeof work);
if (res != FR_OK) {
printf("Failed to make new FS %d\n", res);
return -1;
}
f_setlabel("card10");
if (res != FR_OK) {
printf("Failed to set volume name %d\n", res);
return -1;
}
return 0;
}
int mount(void)
{
FRESULT res;
res = f_mount(&FatFs, "/", 0);
if (res != FR_OK) {
printf("f_mount error %d\n", res);
return -1;
}
res = f_opendir(&dir, "0:");
if (res != FR_OK) {
printf("f_opendir error %d\n", res);
return -1;
}
return 0;
}
int get_msc_flag(void)
{
// We use the API call memory to store a magic value there.
uint32_t* flag = (uint32_t*)API_CALL_MEM;
if (*flag == MSC_MAGIC) {
*flag = 0;
return 1;
} else {
return 0;
}
}
int check_integrity(void)
{
FIL file;
UINT readbytes;
char *filename = "card10.bin";
uint8_t data[512];
FRESULT res;
res = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
if (res != FR_OK) {
printf("f_open error %d\n", res);
return -ENOENT;
}
uint16_t crcval = 0;
do {
res = f_read(&file, data, sizeof(data), &readbytes);
if (res != FR_OK) {
printf("f_read error %d\n", res);
crcval = 1; // Make sure to fail the test
break;
}
crcval = crc16_ccitt(crcval, data, readbytes);
} while (readbytes == sizeof(data));
f_close(&file);
if (crcval != 0) {
printf("CRC check failed. Final CRC: %d\n", crcval);
return -EINVAL;
}
return 0;
}
bool is_update_needed(void)
{
FIL file;
UINT readbytes;
char *filename = "card10.bin";
uint8_t data[512];
FRESULT res;
res = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
if (res != FR_OK) {
printf("f_open error %d\n", res);
return false;
}
uint8_t *partition = (uint8_t *)(intptr_t)PARTITION_START;
bool different = false;
do {
res = f_read(&file, data, sizeof(data), &readbytes);
if (res != FR_OK) {
printf("f_read error %d\n", res);
break; /* Going to return false, don't want to use this file */
}
if (memcmp(partition, data, readbytes)) {
different = true;
break;
}
partition += readbytes;
} while (readbytes == sizeof(data));
f_close(&file);
return different;
}
void erase_partition(void)
{
int ret = FLC_MultiPageErase(PARTITION_START, PARTITION_END);
if (ret != E_NO_ERROR) {
printf("FLC_MultiPageErase failed with %d\n", ret);
while (1)
;
}
}
void flash_partition(void)
{
FIL file;
UINT readbytes;
char *filename = "card10.bin";
uint8_t data[512];
FRESULT res;
res = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
if (res != FR_OK) {
printf("f_open error %d\n", res);
while (1)
;
}
uint32_t partition = PARTITION_START;
ICC_Disable();
do {
res = f_read(&file, data, sizeof(data), &readbytes);
if (res != FR_OK) {
printf("f_read error %d\n", res);
break; /* Going to return false, don't want to use this file */
}
int ret = FLC_Write(
partition,
readbytes,
(uint32_t *
)
data); /* wild cast. not sure if this works */
if (ret != E_NO_ERROR) {
printf("FLC_Write failed with %d\n", ret);
bootloader_display_error(
"Firmware Write", "Firmware not", "updated."
);
while (1)
;
}
partition += readbytes;
} while (readbytes == sizeof(data));
ICC_Enable();
f_close(&file);
}
static inline void boot(const void *vtable)
{
SCB->VTOR = (uintptr_t)vtable;
// Reset stack pointer & branch to the new reset vector.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
__asm("mov r0, %0\n"
"ldr sp, [r0]\n"
"ldr r0, [r0, #4]\n"
"bx r0\n"
:
: "r"(vtable)
: "%sp", "r0");
#pragma GCC diagnostic pop
};
static void pmic_button(bool falling)
{
if (falling) {
card10_reset();
}
}
static void msc(void)
{
bootloader_display_header();
bootloader_display_line(3, "USB activated.", 0xffff);
bootloader_display_line(4, "Ready.", 0xffff);
run_usbmsc();
// If we return, don't try to boot. Maybe rather trigger a software reset.
// Reason: Not sure in which state the USB peripheral is and what kind
// of interrupts are active.
while (1)
;
}
/******************************************************************************/
int main(void)
{
printf("\n\nBootloader " CARD10_VERSION "\n");
card10_init();
/*
* Make the power/reset button restart card10.
*/
pmic_set_button_callback(pmic_button);
bootloader_display_init();
// If the button is pressed or a flag in memory is detected, we go into MSC mode.
if (PB_Get(3) || get_msc_flag()) {
msc();
}
if (mount() == 0) {
int res = check_integrity();
if (res == -ENOENT) {
printf("card10.bin not found!\n");
} else if (res == -EINVAL) {
printf("card10.bin CRC is invalid!\n");
bootloader_display_header();
bootloader_display_line(
3, "Integrity check failed", 0xffff
);
bootloader_display_line(4, "Trying to boot", 0xffff);
} else if (res == 0) {
printf("Found valid application image\n");
if (is_update_needed()) {
printf("Trying to update firmware from external flash\n");
bootloader_display_header();
bootloader_display_line(
4, "Updating ...", 0xffff
);
erase_partition();
flash_partition();
f_unlink("card10.bin");
bootloader_display_line(
4, "Trying to boot", 0xffff
);
} else {
printf("No update needed\n");
}
}
} else {
bootloader_display_header();
bootloader_display_line(3, "Creating new filesystem", 0xffff);
printf("Creating new filesystem\n");
if (format() == 0) {
/* Drop into MSC after a reboot */
card10_reset();
} else {
bootloader_display_line(
3, "Failed to create new filesystem", 0xffff
);
printf("Feiled to create new filesystem\n");
/* Prevent bootloops */
while (1) {
}
}
}
/* Get the intital SP of the firmware. If it is 0xFFFFFFFF, no image has been
* flashed yet. Drop into MSC for initial flashing. */
if (*((uint32_t *)PARTITION_START) == 0xFFFFFFFF) {
printf("No valid image in flash\n");
msc();
}
printf("Trying to boot\n");
boot((uintptr_t *)PARTITION_START);
while (1) {
// Should never be reached.
}
}
/******************************************************************************/
void SysTick_Handler(void)
{
mxc_delay_handler();
}