aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld20
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/cmsis_nvic.c3
-rw-r--r--libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c9
-rw-r--r--projects/cli-test/cli-test.c3
-rw-r--r--projects/cli-test/mgmt-dfu.c222
-rw-r--r--projects/cli-test/mgmt-dfu.h2
6 files changed, 193 insertions, 66 deletions
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
index cb19009..c78e619 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
@@ -1,19 +1,18 @@
/* Linker script to configure memory regions. */
MEMORY
-{
+{
/* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048k */
BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 128K
- FIRMWARE (rx) : ORIGIN = 0x08100000, LENGTH = 2048K - 128K
+ FIRMWARE (rx) : ORIGIN = 0x08000000 + 128K, LENGTH = 2048K - 128K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
- CCM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
- RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K - 4
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
- *
+ *
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
@@ -152,6 +151,17 @@ SECTIONS
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
+ /* The DFU code needs to know where the firmware lives */
+ CRYPTECH_BOOTLOADER_START = ORIGIN(BOOTLOADER);
+ CRYPTECH_BOOTLOADER_END = ORIGIN(BOOTLOADER) + LENGTH(BOOTLOADER) - 1;
+ CRYPTECH_FIRMWARE_START = ORIGIN(FIRMWARE);
+ CRYPTECH_FIRMWARE_END = ORIGIN(FIRMWARE) + LENGTH(FIRMWARE) - 1;
+ /* The last 4 bytes of RAM is used to control the DFU reset+jumping.
+ * Have to be reserved in here to not get overwritten by the Reset_Handler
+ * that zeros memory. Maybe there is a better way?
+ */
+ CRYPTECH_DFU_CONTROL = ORIGIN(RAM) + LENGTH(RAM);
+
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/cmsis_nvic.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/cmsis_nvic.c
index ac2c92a..2da63fc 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/cmsis_nvic.c
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/cmsis_nvic.c
@@ -38,8 +38,7 @@ void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
uint32_t i;
// Copy and switch to dynamic vectors if the first time called
- if (SCB->VTOR == NVIC_FLASH_VECTOR_ADDRESS ||
- SCB->VTOR == 0x08100000) {
+ if (SCB->VTOR == NVIC_FLASH_VECTOR_ADDRESS) {
uint32_t *old_vectors = vectors;
vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS;
for (i=0; i<NVIC_NUM_VECTORS; i++) {
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c
index c2816d0..cc527ae 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c
@@ -75,6 +75,8 @@
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
+extern uint32_t CRYPTECH_FIRMWARE_START; /* defined in the linker script (STM32F429BI.ld) */
+
/**
* @}
*/
@@ -197,11 +199,14 @@ void SystemInit(void)
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location add offset address ------------------*/
+ /* cryptech: Don't change VTOR if it is already set up by the bootloader */
+ if (SCB->VTOR != CRYPTECH_FIRMWARE_START) {
#ifdef VECT_TAB_SRAM
- SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+ SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
- SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
+ SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
+ }
/* Configure the Cube driver */
SystemCoreClock = 16000000; // At this stage the HSI is used as system clock
diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c
index 30623a4..1a8c6b7 100644
--- a/projects/cli-test/cli-test.c
+++ b/projects/cli-test/cli-test.c
@@ -410,6 +410,9 @@ main()
{
static struct cli_def cli;
+ /* This is simulating the bootloader from the cli-test. */
+ check_early_dfu_jump();
+
stm_init();
led_on(LED_RED);
diff --git a/projects/cli-test/mgmt-dfu.c b/projects/cli-test/mgmt-dfu.c
index 1f8aa0a..1c7e052 100644
--- a/projects/cli-test/mgmt-dfu.c
+++ b/projects/cli-test/mgmt-dfu.c
@@ -39,46 +39,136 @@
#include <string.h>
+extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
+
+/* symbols defined in the linker script (STM32F429BI.ld) */
+extern uint32_t CRYPTECH_FIRMWARE_START;
+extern uint32_t CRYPTECH_FIRMWARE_END;
+extern uint32_t CRYPTECH_DFU_CONTROL;
+
+#define DFU_FIRMWARE_ADDR ((uint32_t ) &CRYPTECH_FIRMWARE_START)
+#define DFU_FIRMWARE_PTR ((__IO uint32_t *) (CRYPTECH_FIRMWARE_START))
+#define DFU_FIRMWARE_END_ADDR CRYPTECH_FIRMWARE_END
+#define HARDWARE_EARLY_DFU_JUMP 0xBADABADA
+#define DFU_UPLOAD_CHUNK_SIZE 256
+
+__IO uint32_t *dfu_control = &CRYPTECH_DFU_CONTROL;
+__IO uint32_t *dfu_new_msp = &CRYPTECH_FIRMWARE_START;
+__IO uint32_t *dfu_firmware = &CRYPTECH_FIRMWARE_START + 4;
+
+/* Flash sector offsets from RM0090, Table 6. Flash module - 2 Mbyte dual bank organization */
+#define FLASH_NUM_SECTORS 24 + 1
+uint32_t flash_sector_offsets[FLASH_NUM_SECTORS] = {
+ /* Bank 1 */
+ 0x08000000, /* #0, 16 KBytes */
+ 0x08004000, /* #1, 16 Kbytes */
+ 0x08008000, /* #2, 16 Kbytes */
+ 0x0800C000, /* #3, 16 Kbytes */
+ 0x08010000, /* #4, 64 Kbytes */
+ 0x08020000, /* #5, 128 Kbytes */
+ 0x08040000, /* #6, 128 Kbytes */
+ 0x08060000, /* #7, 128 Kbytes */
+ 0x08080000, /* #8, 128 Kbytes */
+ 0x080A0000, /* #9, 128 Kbytes */
+ 0x080C0000, /* #10, 128 Kbytes */
+ 0x080E0000, /* #11, 128 Kbytes */
+ /* Bank 2 */
+ 0x08100000, /* #12, 16 Kbytes */
+ 0x08104000, /* #13, 16 Kbytes */
+ 0x08108000, /* #14, 16 Kbytes */
+ 0x0810C000, /* #15, 16 Kbytes */
+ 0x08110000, /* #16, 64 Kbytes */
+ 0x08120000, /* #17, 128 Kbytes */
+ 0x08140000, /* #18, 128 Kbytes */
+ 0x08160000, /* #19, 128 Kbytes */
+ 0x08180000, /* #20, 128 Kbytes */
+ 0x081A0000, /* #21, 128 Kbytes */
+ 0x081C0000, /* #22, 128 Kbytes */
+ 0x081E0000, /* #23, 128 Kbytes */
+ 0x08200000 /* first address *after* flash */
+};
+
+
+typedef void (*pFunction)(void);
+
+
+/* This is it's own function to make it more convenient to set a breakpoint at it in gdb */
+void do_early_dfu_jump(void)
+{
+ //pFunction loaded_app = (pFunction) *(DFU_FIRMWARE_PTR + 1);
+ pFunction loaded_app = (pFunction) *dfu_firmware;
+ *dfu_control = 0;
+ __set_MSP(*dfu_new_msp);
+ /* Set the Vector Table Offset Register */
+ SCB->VTOR = DFU_FIRMWARE_ADDR;
+ loaded_app();
+ while (1);
+}
-#define DFU_BASE_ADDRESS 0x08100000
-#define DFU_BASE_PTR (__IO uint32_t *) DFU_BASE_ADDRESS
+/* This function is called from main() before any peripherals are initialized */
+void check_early_dfu_jump(void)
+{
+ if (*dfu_control == HARDWARE_EARLY_DFU_JUMP) {
+ do_early_dfu_jump();
+ }
+}
+inline int _flash_sector_num(uint32_t offset)
+{
+ int i = FLASH_NUM_SECTORS - 1;
+ while (i-- >= 0) {
+ if (offset >= flash_sector_offsets[i] &&
+ offset < flash_sector_offsets[i + 1]) {
+ return i;
+ }
+ }
+ return -1;
+}
-extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
+int _write_to_flash(uint32_t offset, const uint32_t *buf, uint32_t elements)
+{
+ uint32_t sector = _flash_sector_num(offset);
+ uint32_t SectorError = 0, i, j;
+
+ if (offset == flash_sector_offsets[sector]) {
+ /* Request to write to beginning of a flash sector, erase it first. */
+ FLASH_EraseInitTypeDef FLASH_EraseInitStruct;
+
+ FLASH_EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
+ FLASH_EraseInitStruct.Sector = sector;
+ FLASH_EraseInitStruct.NbSectors = 1;
+ FLASH_EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3;
+
+ if (HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError) != HAL_OK) {
+ return -1;
+ }
+ }
+ for (i = 0; i < elements; i++) {
+ if ((j = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, offset, buf[i])) != HAL_OK) {
+ return -2;
+ }
+ offset += 4;
+ }
-/* The chunk size have to be a multiple of the SPI flash page size (256 bytes),
- and it has to match the chunk size in the program sending the bitstream over the UART.
-*/
-#define DFU_UPLOAD_CHUNK_SIZE 256
+ return 1;
+}
int cmd_dfu_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
{
- uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0, i, j;
- uint32_t offset = 0, n = DFU_UPLOAD_CHUNK_SIZE;
+ uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0;
+ uint32_t offset = DFU_FIRMWARE_ADDR, n = DFU_UPLOAD_CHUNK_SIZE;
uint32_t buf[DFU_UPLOAD_CHUNK_SIZE / 4];
- FLASH_EraseInitTypeDef FLASH_EraseInitStruct;
- uint32_t SectorError = 0;
cli_print(cli, "OK, write DFU application file size (4 bytes), data in %i byte chunks, CRC-32 (4 bytes)",
DFU_UPLOAD_CHUNK_SIZE);
/* Read file size (4 bytes) */
uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000);
- cli_print(cli, "File size %li", filesize);
+ cli_print(cli, "File size %li, will write it to 0x%lx", filesize, offset);
HAL_FLASH_Unlock();
- FLASH_EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
- FLASH_EraseInitStruct.Sector = 12; /* the sector for DFU_BASE_ADDRESS (0x08100000) */
- FLASH_EraseInitStruct.NbSectors = 1;
- FLASH_EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3;
-
- if (HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError) != HAL_OK) {
- cli_print(cli, "Failed erasing flash sector");
- return CLI_ERROR;
- }
-
while (filesize) {
/* By initializing buf to the same value that erased flash has (0xff), we don't
* have to try and be smart when writing the last page of data to the memory.
@@ -99,14 +189,8 @@ int cmd_dfu_upload(struct cli_def *cli, const char *command, char *argv[], int a
* calculate CRC and write it to flash.
*/
my_crc = update_crc(my_crc, (uint8_t *) buf, n);
-
- for (i = 0; i < DFU_UPLOAD_CHUNK_SIZE / 4; i++) {
- if ((j = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, DFU_BASE_ADDRESS + offset, buf[i])) != HAL_OK) {
- cli_print(cli, "Failed writing data at offset %li: %li", offset, j);
- return CLI_ERROR;
- }
- offset += 4;
- }
+ _write_to_flash(offset, buf, sizeof(buf) / 4);
+ offset += DFU_UPLOAD_CHUNK_SIZE;
/* ACK this chunk by sending the current chunk counter (4 bytes) */
counter++;
@@ -130,48 +214,71 @@ int cmd_dfu_upload(struct cli_def *cli, const char *command, char *argv[], int a
int cmd_dfu_dump(struct cli_def *cli, const char *command, char *argv[], int argc)
{
- cli_print(cli, "First 256 bytes from DFU application address %p:\r\n", DFU_BASE_PTR);
+ cli_print(cli, "First 256 bytes from DFU application address %p:\r\n", DFU_FIRMWARE_PTR);
- uart_send_hexdump(STM_UART_MGMT, (uint8_t *) DFU_BASE_PTR, 0, 0xff);
+ uart_send_hexdump(STM_UART_MGMT, (uint8_t *) DFU_FIRMWARE_ADDR, 0, 0xff);
uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n");
return CLI_OK;
}
-typedef int (*pFunction)(void);
+int cmd_dfu_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ uint32_t start_sector = _flash_sector_num(DFU_FIRMWARE_ADDR);
+ uint32_t end_sector = _flash_sector_num(DFU_FIRMWARE_END_ADDR);
+ uint32_t sector;
+
+ cli_print(cli, "Erasing flash sectors %li to %li (address %p to %p)",
+ start_sector, end_sector,
+ (uint32_t *) DFU_FIRMWARE_ADDR,
+ (uint32_t *) DFU_FIRMWARE_END_ADDR);
+
+ if (start_sector > end_sector) {
+ cli_print(cli, "ERROR: Bad sectors");
+ return CLI_ERROR;
+ }
+
+ HAL_FLASH_Unlock();
+
+ for (sector = start_sector; sector <= end_sector; sector++) {
+ uint32_t SectorError = 0;
+ FLASH_EraseInitTypeDef FLASH_EraseInitStruct;
+
+ FLASH_EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
+ FLASH_EraseInitStruct.Sector = sector;
+ FLASH_EraseInitStruct.NbSectors = 1;
+ FLASH_EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3;
+
+ if (HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError) != HAL_OK) {
+ cli_print(cli, "ERROR: Failed erasing sector %li", sector);
+ }
+ }
+ HAL_FLASH_Lock();
+
+ return CLI_OK;
+}
int cmd_dfu_jump(struct cli_def *cli, const char *command, char *argv[], int argc)
{
- uint32_t new_msp, i;
- /* Load first byte from the DFU_BASE_PTR to verify it contains an IVT before
+ uint32_t i;
+ /* Load first byte from the DFU_FIRMWARE_PTR to verify it contains an IVT before
* jumping there.
*/
- new_msp = *DFU_BASE_PTR;
- i = new_msp & 0xFF000000;
- /* 'i' is supposed to be a pointer to the new applications stack, it should
+ cli_print(cli, "Checking for application at %p", DFU_FIRMWARE_PTR);
+
+ //new_msp = (uint32_t) DFU_FIRMWARE_PTR;
+ i = *dfu_new_msp & 0xFF000000;
+ /* 'new_msp' is supposed to be a pointer to the new applications stack, it should
* point either at RAM (0x20000000) or at the CCM memory (0x10000000).
*/
if (i == 0x20000000 || i == 0x10000000) {
- uint32_t jmp_to = *(DFU_BASE_PTR + 1);
- pFunction loaded_app = (pFunction) jmp_to;
-
- __disable_irq();
- HAL_NVIC_DisableIRQ(SysTick_IRQn);
-
- HAL_DeInit();
-
- /* Relocate interrupt vector table */
- //NVIC_SetVectorTable(DFU_BASE_ADDRESS);
- SCB->VTOR == DFU_BASE_ADDRESS;
- NVIC_SetVector(WWDG_IRQn, *DFU_BASE_PTR + 1);
-
- /* Re-initialize stack pointer */
- __set_MSP(new_msp);
- /* Jump to the DFU loaded application */
- loaded_app();
- Error_Handler();
+ *dfu_control = HARDWARE_EARLY_DFU_JUMP;
+ cli_print(cli, "Making the leap");
+ HAL_NVIC_SystemReset();
+ while (1) { ; }
} else {
- cli_print(cli, "No loaded application found at %p", DFU_BASE_PTR);
+ cli_print(cli, "No loaded application found at %p (read 0x%x)",
+ DFU_FIRMWARE_PTR, (unsigned int) *dfu_new_msp);
}
return CLI_OK;
@@ -184,4 +291,5 @@ void configure_cli_dfu(struct cli_def *cli)
cli_command_node(dfu, dump, "Show the first 256 bytes of the loaded application");
cli_command_node(dfu, jump, "Jump to the loaded application");
cli_command_node(dfu, upload, "Load a new application");
+ cli_command_node(dfu, erase, "Erase the application memory");
}
diff --git a/projects/cli-test/mgmt-dfu.h b/projects/cli-test/mgmt-dfu.h
index c38a63e..e1e3932 100644
--- a/projects/cli-test/mgmt-dfu.h
+++ b/projects/cli-test/mgmt-dfu.h
@@ -38,7 +38,9 @@
#include "stm-init.h"
#include <libcli.h>
+#define DFU_UPLOAD_CHUNK_SIZE 256
extern void configure_cli_dfu(struct cli_def *cli);
+extern void check_early_dfu_jump(void);
#endif /* __STM32_CLI_MGMT_DFU_H */