mirror of https://github.com/wolfSSL/wolfBoot.git
Added support for STM32F7 + DUALBANK_SWAP hw-assisted support
parent
d0719f3d2d
commit
34def41dd1
5
Makefile
5
Makefile
|
@ -24,6 +24,7 @@ WOLFBOOT_VERSION?=0
|
|||
V?=0
|
||||
SPMATH?=1
|
||||
RAM_CODE?=0
|
||||
DUALBANK_SWAP=0
|
||||
|
||||
|
||||
|
||||
|
@ -85,6 +86,10 @@ ifeq ($(RAM_CODE),1)
|
|||
CFLAGS+= -DRAM_CODE
|
||||
endif
|
||||
|
||||
ifeq ($(DUALBANK_SWAP),1)
|
||||
CFLAGS+= -DDUALBANK_SWAP
|
||||
endif
|
||||
|
||||
ifeq ($(SPI_FLASH),1)
|
||||
EXT_FLASH=1
|
||||
CFLAGS+= -DSPI_FLASH=1
|
||||
|
|
6
arch.mk
6
arch.mk
|
@ -30,6 +30,12 @@ ifeq ($(ARCH),ARM)
|
|||
CORTEX_M0=1
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),stm32f7)
|
||||
ARCH_FLASH_OFFSET=0x08000000
|
||||
else
|
||||
ARCH_FLASH_OFFSET=0x0
|
||||
endif
|
||||
|
||||
## Cortex-M CPU
|
||||
ifeq ($(CORTEX_M0),1)
|
||||
CFLAGS+=-mcpu=cortex-m0
|
||||
|
|
118
docs/Targets.md
118
docs/Targets.md
|
@ -26,7 +26,7 @@ This results in the following partition configuration:
|
|||
This configuration demonstrates one of the possible layouts, with the slots
|
||||
aligned to the beginning of the physical sector on the flash.
|
||||
|
||||
The entry point for all the runnable firmware images on this target will be `0x20100`,
|
||||
The entry point for all the runnable firmware images on this target will be `0x20100`,
|
||||
256 Bytes after the beginning of the first flash partition. This is due to the presence
|
||||
of the firmware image header at the beginning of the partition, as explained more in details
|
||||
in [Firmware image](firmware_image.md)
|
||||
|
@ -114,14 +114,14 @@ For testing wolfBoot here are the changes required:
|
|||
1. Makefile arguments:
|
||||
* ARCH=RISCV
|
||||
* TARGET=hifive1
|
||||
|
||||
|
||||
```
|
||||
make ARCH=RISCV TARGET=hifive1 RAM_CODE=1 clean
|
||||
make ARCH=RISCV TARGET=hifive1 RAM_CODE=1
|
||||
```
|
||||
|
||||
If using the `riscv64-unknown-elf-` cross compiler you can add `CROSS_COMPILE=riscv64-unknown-elf-` to your `make` or modify `arch.mk` as follows:
|
||||
|
||||
|
||||
```
|
||||
ifeq ($(ARCH),RISCV)
|
||||
- CROSS_COMPILE:=riscv32-unknown-elf-
|
||||
|
@ -172,3 +172,115 @@ riscv64-unknown-elf-gdb wolfboot.elf -ex "set remotetimeout 240" -ex "target ext
|
|||
add-symbol-file test-app/image.elf 0x20020100
|
||||
```
|
||||
|
||||
|
||||
## STM32-F769
|
||||
|
||||
The STM32-F76x and F77x offer dual-bank hardware-assisted swapping.
|
||||
The flash geometry must be defined beforehand, and wolfBoot can be compiled to use hardware
|
||||
assisted bank-swapping to perform updates.
|
||||
|
||||
|
||||
Example 2MB partitioning on STM32-F769:
|
||||
|
||||
- Dual-bank configuration
|
||||
|
||||
BANK A: 0x08000000 to 0x080FFFFFF (1MB)
|
||||
BANK B: 0x08100000 to 0x081FFFFFF (1MB)
|
||||
|
||||
- WolfBoot executes from BANK A after reboot (address: 0x08000000)
|
||||
- Boot partition @ BANK A + 0x20000 = 0x08020000
|
||||
- Update partition @ BANK B + 0x20000 = 0x08120000
|
||||
- Application entry point: 0x08020100
|
||||
|
||||
```C
|
||||
#define WOLFBOOT_SECTOR_SIZE 0x20000
|
||||
#define WOLFBOOT_PARTITION_SIZE 0x40000
|
||||
|
||||
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x08020000
|
||||
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x08120000
|
||||
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x0 /* Unused, swap is hw-assisted */
|
||||
```
|
||||
|
||||
### Build Options
|
||||
|
||||
To activate the dual-bank hardware-assisted swap feature on STM32F76x/77x, use the
|
||||
`DUALBANK_SWAP=1` compile time option. Some code requires to run in RAM during the swapping
|
||||
of the images, so the compile-time option `RAMCODE=1` is also required in this case.
|
||||
|
||||
Dual-bank STM32F7 build can be built using:
|
||||
|
||||
```
|
||||
make TARGET=stm32f7 DUALBANK_SWAP=1 RAM_CODE=1
|
||||
```
|
||||
|
||||
|
||||
### Loading the firmware
|
||||
|
||||
To switch between single-bank (1x2MB) and dual-bank (2 x 1MB) mode mapping, this [stm32f7-dualbank-tool](https://github.com/danielinux/stm32f7-dualbank-tool)
|
||||
can be used.
|
||||
Before starting openocd, switch the flash mode to dualbank (e.g. via `make dualbank` using the dualbank tool).
|
||||
|
||||
OpenOCD configuration for flashing/debugging, can be copied into `openocd.cfg` in your working directory:
|
||||
|
||||
```
|
||||
source [find interface/stlink.cfg]
|
||||
source [find board/stm32f7discovery.cfg]
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
mmw 0xe0042004 0x7 0x0
|
||||
}
|
||||
init
|
||||
reset
|
||||
halt
|
||||
```
|
||||
|
||||
OpenOCD can be either run in background (to allow remote GDB and monitor terminal connections), or
|
||||
directly from command line, to execute terminal scripts.
|
||||
|
||||
If OpenOCD is running, local TCP port 4444 can be used to access an interactive terminal prompt.
|
||||
|
||||
Using the following openocd commands, the initial images for wolfBoot and the test application
|
||||
are loaded to flash in bank 0:
|
||||
|
||||
```
|
||||
flash write_image unlock erase wolfboot.bin 0x08000000
|
||||
flash verify_bank 0 wolfboot.bin
|
||||
flash write_image unlock erase test-app/image_v1_signed.bin 0x08020000
|
||||
flash verify_bank 0 test-app/image_v1_signed.bin 0x20000
|
||||
reset
|
||||
resume 0x0000001
|
||||
```
|
||||
|
||||
To sign the same application image as new version (2), use the python script `sign.py` provided:
|
||||
|
||||
```
|
||||
tools/keytools/sign.py test-app/image.bin ed25519.der 2
|
||||
```
|
||||
|
||||
From OpenOCD, the updated image (version 2) can be flashed to the second bank:
|
||||
```
|
||||
flash write_image unlock erase test-app/image_v2_signed.bin 0x08120000
|
||||
flash verify_bank 0 test-app/image_v1_signed.bin 0x20000
|
||||
```
|
||||
|
||||
Upon reboot, wolfboot will elect the best candidate (version 2 in this case) and authenticate the image.
|
||||
If the accepted candidate image resides on BANK B (like in this case), wolfBoot will perform one bank swap before
|
||||
booting.
|
||||
|
||||
The bank-swap operation is immediate and a SWAP image is not required in this case. Fallback mechanism can rely on
|
||||
a second choice (older firmware) in the other bank.
|
||||
|
||||
|
||||
### Debugging
|
||||
|
||||
Debugging with OpenOCD:
|
||||
|
||||
Use the OpenOCD configuration from the previous section to run OpenOCD.
|
||||
|
||||
From another console, connect using gdb, e.g.:
|
||||
|
||||
```
|
||||
arm-none-eabi-gdb
|
||||
(gdb) target remote:3333
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -136,6 +136,19 @@ both `PART_UPDATE_EXT` and `PART_SWAP_EXT` are defined.
|
|||
When external memory is used, the HAL API must be extended to define methods to access the custom memory.
|
||||
Refer to the [HAL](HAL.md) page for the description of the `ext_flash_*` API.
|
||||
|
||||
### Executing flash access code from RAM
|
||||
|
||||
On some platform, flash access code requires to be executed from RAM, to avoid conflict e.g. when writing
|
||||
to the same device where wolfBoot is executing, or when changing the configuration of the flash itself.
|
||||
|
||||
To move all the code accessing the internal flash for writing, into a section in RAM, use the compile time option
|
||||
`RAM_CODE=1` (on some hardware configurations this is required for the bootloader to access the flash for writing).
|
||||
|
||||
### Enable Dual-bank hardware-assisted swapping
|
||||
|
||||
When supported by the target platform, hardware-assisted dual-bank swapping can be used to perform updates.
|
||||
To enable this functionality, use `DUALBANK_SWAP=1`. Currently, only STM32F76x and F77x support this feature.
|
||||
|
||||
### Using Mac OS/X
|
||||
|
||||
If you see 0xC3 0xBF (C3BF) repeated in your factory.bin then your OS is using Unicode characters.
|
||||
|
@ -155,3 +168,4 @@ LC_ALL=
|
|||
```
|
||||
|
||||
Then run the normal `make` steps.
|
||||
|
||||
|
|
|
@ -0,0 +1,510 @@
|
|||
/* stm32f7.c
|
||||
*
|
||||
* Copyright (C) 2019 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfBoot 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <image.h>
|
||||
#include "hal.h"
|
||||
/* STM32 F7 register configuration */
|
||||
|
||||
/* Assembly helpers */
|
||||
#define DMB() __asm__ volatile ("dmb")
|
||||
#define ISB() __asm__ volatile ("isb")
|
||||
|
||||
/*** RCC ***/
|
||||
|
||||
#define RCC_BASE (0x40023800)
|
||||
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00))
|
||||
#define RCC_PLLCFGR (*(volatile uint32_t *)(RCC_BASE + 0x04))
|
||||
#define RCC_CFGR (*(volatile uint32_t *)(RCC_BASE + 0x08))
|
||||
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00))
|
||||
|
||||
#define RCC_CR_PLLRDY (1 << 25)
|
||||
#define RCC_CR_PLLON (1 << 24)
|
||||
#define RCC_CR_HSERDY (1 << 17)
|
||||
#define RCC_CR_HSEON (1 << 16)
|
||||
#define RCC_CR_HSIRDY (1 << 1)
|
||||
#define RCC_CR_HSION (1 << 0)
|
||||
|
||||
#define RCC_CFGR_SW_HSI 0x0
|
||||
#define RCC_CFGR_SW_HSE 0x1
|
||||
#define RCC_CFGR_SW_PLL 0x2
|
||||
|
||||
|
||||
#define RCC_PLLCFGR_PLLSRC (1 << 22)
|
||||
|
||||
#define RCC_PRESCALER_DIV_NONE 0
|
||||
#define RCC_PRESCALER_DIV_2 8
|
||||
#define RCC_PRESCALER_DIV_4 9
|
||||
#define PLL_FULL_MASK (0x7F037FFF)
|
||||
|
||||
/*** FLASH ***/
|
||||
#define APB1_CLOCK_ER (*(volatile uint32_t *)(0x40023840))
|
||||
#define APB1_CLOCK_RST (*(volatile uint32_t *)(0x40023820))
|
||||
#define TIM2_APB1_CLOCK_ER_VAL (1 << 0)
|
||||
#define PWR_APB1_CLOCK_ER_VAL (1 << 28)
|
||||
|
||||
#define APB2_CLOCK_ER (*(volatile uint32_t *)(0x40023844))
|
||||
#define APB2_CLOCK_RST (*(volatile uint32_t *)(0x40023824))
|
||||
#define SYSCFG_APB2_CLOCK_ER (1 << 14)
|
||||
|
||||
#define FLASH_BASE (0x40023C00)
|
||||
#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
|
||||
#define FLASH_KEYR (*(volatile uint32_t *)(FLASH_BASE + 0x04))
|
||||
#define FLASH_OPTKEYR (*(volatile uint32_t *)(FLASH_BASE + 0x08))
|
||||
#define FLASH_SR (*(volatile uint32_t *)(FLASH_BASE + 0x0C))
|
||||
#define FLASH_CR (*(volatile uint32_t *)(FLASH_BASE + 0x10))
|
||||
#define FLASH_OPTCR (*(volatile uint32_t *)(FLASH_BASE + 0x14))
|
||||
|
||||
/* Register values */
|
||||
#define FLASH_ACR_ARTRST (1 << 11)
|
||||
#define FLASH_ACR_PRFEN (1 << 9)
|
||||
#define FLASH_ACR_ARTEN (1 << 8)
|
||||
|
||||
#define FLASH_SR_BSY (1 << 16)
|
||||
#define FLASH_SR_PGSERR (1 << 7)
|
||||
#define FLASH_SR_PGPERR (1 << 6)
|
||||
#define FLASH_SR_PGAERR (1 << 5)
|
||||
#define FLASH_SR_WRPERR (1 << 4)
|
||||
#define FLASH_SR_OPERR (1 << 1)
|
||||
#define FLASH_SR_EOP (1 << 0)
|
||||
|
||||
#define FLASH_CR_LOCK (1 << 31)
|
||||
#define FLASH_CR_ERRIE (1 << 25)
|
||||
#define FLASH_CR_EOPIE (1 << 24)
|
||||
#define FLASH_CR_STRT (1 << 16)
|
||||
#define FLASH_CR_MER2 (1 << 15)
|
||||
#define FLASH_CR_MER1 (1 << 2)
|
||||
#define FLASH_CR_SER (1 << 1)
|
||||
#define FLASH_CR_PG (1 << 0)
|
||||
|
||||
#define FLASH_CR_SNB_SHIFT 3
|
||||
#define FLASH_CR_SNB_MASK 0x1f
|
||||
|
||||
#define FLASH_CR_PROGRAM_X8 (0 << 8)
|
||||
#define FLASH_CR_PROGRAM_X16 (1 << 8)
|
||||
#define FLASH_CR_PROGRAM_X32 (2 << 8)
|
||||
#define FLASH_CR_PROGRAM_X64 (3 << 8)
|
||||
|
||||
#define FLASH_OPTCR_nDBOOT (1 << 28)
|
||||
#define FLASH_OPTCR_nDBANK (1 << 29)
|
||||
#define FLASH_OPTCR_STRT (1 << 1)
|
||||
|
||||
#define FLASH_KEY1 (0x45670123)
|
||||
#define FLASH_KEY2 (0xCDEF89AB)
|
||||
|
||||
#define FLASH_OPTKEY1 (0x08192A3B)
|
||||
#define FLASH_OPTKEY2 (0x4C5D6E7F)
|
||||
|
||||
|
||||
/* FLASH Geometry
|
||||
*
|
||||
* per ST AN4826, two configurations are possible on STM32F7:
|
||||
*
|
||||
* - Dual bank with swapping, 2 x 512KB banks, 8 sectors each
|
||||
* - Single bank, 1 x 1MB, 8 sectors in total
|
||||
*
|
||||
* The chosen configuration depends on the FLASH_OPTCR_DBANK value.
|
||||
*
|
||||
*
|
||||
* */
|
||||
|
||||
#define FLASH_SECTOR_UNUSED 0xFFFFFFFF
|
||||
/* This memory mapping is for 2MB flash (STM32F769). */
|
||||
|
||||
#ifdef DUALBANK_SWAP
|
||||
# define SYSCFG_MEMRMP (*(volatile uint32_t *)(0x40013800))
|
||||
# define MEMRMP_SWP_FB (1 << 8)
|
||||
# define FLASH_SECTORS 28
|
||||
|
||||
/* Block 0: 0x8000000 */
|
||||
# define FLASH_SECTOR_0 0x8000000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_1 0x8004000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_2 0x8008000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_3 0x800C000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_4 0x8010000 /* 64 Kb */
|
||||
# define FLASH_SECTOR_5 0x8020000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_6 0x8040000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_7 0x8060000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_8 0x8080000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_9 0x80A0000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_10 0x80C0000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_11 0x80E0000 /* 128 Kb */
|
||||
|
||||
/* Block 1: 0x8100000 */
|
||||
# define FLASH_SECTOR_16 0x8100000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_17 0x8104000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_18 0x8108000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_19 0x810C000 /* 16 Kb */
|
||||
# define FLASH_SECTOR_20 0x8110000 /* 64 Kb */
|
||||
# define FLASH_SECTOR_21 0x8120000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_22 0x8140000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_23 0x8160000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_24 0x8180000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_25 0x81A0000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_26 0x81C0000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_27 0x81E0000 /* 128 Kb */
|
||||
|
||||
void fork_bootloader(void);
|
||||
|
||||
#else
|
||||
# define FLASH_SECTORS 12
|
||||
# define FLASH_SECTOR_0 0x8000000 /* 32 Kb */
|
||||
# define FLASH_SECTOR_1 0x8008000 /* 32 Kb */
|
||||
# define FLASH_SECTOR_2 0x8010000 /* 32 Kb */
|
||||
# define FLASH_SECTOR_3 0x8018000 /* 32 Kb */
|
||||
# define FLASH_SECTOR_4 0x8020000 /* 128 Kb */
|
||||
# define FLASH_SECTOR_5 0x8040000 /* 256 Kb */
|
||||
# define FLASH_SECTOR_6 0x8080000 /* 256 Kb */
|
||||
# define FLASH_SECTOR_7 0x80C0000 /* 256 Kb */
|
||||
# define FLASH_SECTOR_8 0x8100000 /* 256 Kb */
|
||||
# define FLASH_SECTOR_9 0x8140000 /* 256 Kb */
|
||||
# define FLASH_SECTOR_10 0x8180000 /* 256 Kb */
|
||||
# define FLASH_SECTOR_11 0x818C000 /* 256 Kb */
|
||||
#endif
|
||||
# define FLASH_TOP 0x8200000
|
||||
|
||||
const uint32_t flash_sector[FLASH_SECTORS + 1] = {
|
||||
FLASH_SECTOR_0,
|
||||
FLASH_SECTOR_1,
|
||||
FLASH_SECTOR_2,
|
||||
FLASH_SECTOR_3,
|
||||
FLASH_SECTOR_4,
|
||||
FLASH_SECTOR_5,
|
||||
FLASH_SECTOR_6,
|
||||
FLASH_SECTOR_7,
|
||||
FLASH_SECTOR_8,
|
||||
FLASH_SECTOR_9,
|
||||
FLASH_SECTOR_10,
|
||||
FLASH_SECTOR_11,
|
||||
#ifdef DUALBANK_SWAP
|
||||
FLASH_SECTOR_UNUSED,
|
||||
FLASH_SECTOR_UNUSED,
|
||||
FLASH_SECTOR_UNUSED,
|
||||
FLASH_SECTOR_UNUSED,
|
||||
FLASH_SECTOR_16,
|
||||
FLASH_SECTOR_17,
|
||||
FLASH_SECTOR_18,
|
||||
FLASH_SECTOR_19,
|
||||
FLASH_SECTOR_20,
|
||||
FLASH_SECTOR_21,
|
||||
FLASH_SECTOR_22,
|
||||
FLASH_SECTOR_23,
|
||||
FLASH_SECTOR_24,
|
||||
FLASH_SECTOR_25,
|
||||
FLASH_SECTOR_26,
|
||||
FLASH_SECTOR_27,
|
||||
#endif
|
||||
FLASH_TOP
|
||||
};
|
||||
|
||||
static void RAMFUNCTION flash_set_waitstates(int waitstates)
|
||||
{
|
||||
FLASH_ACR |= waitstates | FLASH_ACR_PRFEN | FLASH_ACR_ARTEN;
|
||||
}
|
||||
|
||||
static RAMFUNCTION void flash_wait_complete(void)
|
||||
{
|
||||
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
|
||||
;
|
||||
}
|
||||
|
||||
static void RAMFUNCTION flash_erase_sector(uint32_t sec)
|
||||
{
|
||||
uint32_t reg = FLASH_CR & (~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT));
|
||||
FLASH_CR = reg | (sec & FLASH_CR_SNB_MASK) << FLASH_CR_SNB_SHIFT;
|
||||
FLASH_CR |= FLASH_CR_SER;
|
||||
FLASH_CR |= FLASH_CR_STRT;
|
||||
flash_wait_complete();
|
||||
FLASH_CR &= ~FLASH_CR_SER;
|
||||
FLASH_CR &= ~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT);
|
||||
}
|
||||
|
||||
static void RAMFUNCTION clear_errors(void)
|
||||
{
|
||||
FLASH_SR |= ( FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR | FLASH_SR_OPERR | FLASH_SR_EOP );
|
||||
}
|
||||
|
||||
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
||||
{
|
||||
int i;
|
||||
uint32_t val;
|
||||
flash_wait_complete();
|
||||
clear_errors();
|
||||
/* Set 8-bit write */
|
||||
FLASH_CR &= (~(0x03 << 8));
|
||||
for (i = 0; i < len; i++) {
|
||||
FLASH_CR |= FLASH_CR_PG;
|
||||
*((uint8_t *)(address + i)) = data[i];
|
||||
flash_wait_complete();
|
||||
FLASH_CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RAMFUNCTION hal_flash_unlock(void)
|
||||
{
|
||||
FLASH_CR |= FLASH_CR_LOCK;
|
||||
FLASH_KEYR = FLASH_KEY1;
|
||||
FLASH_KEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
void RAMFUNCTION hal_flash_lock(void)
|
||||
{
|
||||
FLASH_CR |= FLASH_CR_LOCK;
|
||||
}
|
||||
|
||||
|
||||
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
|
||||
{
|
||||
int start = -1, end = -1;
|
||||
uint32_t end_address;
|
||||
int i;
|
||||
int nxt;
|
||||
if (len == 0)
|
||||
return -1;
|
||||
end_address = address + len - 1;
|
||||
|
||||
if (address < flash_sector[0] || end_address > FLASH_TOP)
|
||||
return -1;
|
||||
for (i = 0; i < FLASH_SECTORS; i++)
|
||||
{
|
||||
if (flash_sector[i] == FLASH_SECTOR_UNUSED)
|
||||
continue;
|
||||
nxt = i + 1;
|
||||
while (nxt < FLASH_SECTORS) {
|
||||
if (flash_sector[nxt] == FLASH_SECTOR_UNUSED)
|
||||
nxt++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ((address >= flash_sector[i]) && (address < flash_sector[nxt])) {
|
||||
start = i;
|
||||
}
|
||||
if ((end_address >= flash_sector[i]) && (end_address < flash_sector[nxt])) {
|
||||
end = i;
|
||||
}
|
||||
if (start > 0 && end > 0)
|
||||
break;
|
||||
}
|
||||
if (start < 0 || end < 0)
|
||||
return -1;
|
||||
for (i = start; i <= end; i++)
|
||||
flash_erase_sector(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void RAMFUNCTION clock_pll_off(void)
|
||||
{
|
||||
uint32_t reg32;
|
||||
/* Enable internal high-speed oscillator. */
|
||||
RCC_CR |= RCC_CR_HSION;
|
||||
DMB();
|
||||
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 1) | (1 << 0));
|
||||
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI);
|
||||
DMB();
|
||||
|
||||
/* Turn off PLL */
|
||||
RCC_CR &= ~RCC_CR_PLLON;
|
||||
DMB();
|
||||
}
|
||||
|
||||
static void clock_pll_on(int powersave)
|
||||
{
|
||||
uint32_t reg32;
|
||||
uint32_t cpu_freq, plln, pllm, pllq, pllp, hpre, ppre1, ppre2, flash_waitstates;
|
||||
|
||||
/* Enable Power controller */
|
||||
APB1_CLOCK_ER |= PWR_APB1_CLOCK_ER_VAL;
|
||||
|
||||
/* Select clock parameters (CPU Speed = 168MHz) */
|
||||
pllm = 25;
|
||||
plln = 432;
|
||||
pllp = 2;
|
||||
pllq = 9;
|
||||
hpre = RCC_PRESCALER_DIV_NONE;
|
||||
ppre1 = RCC_PRESCALER_DIV_4;
|
||||
ppre2 = RCC_PRESCALER_DIV_2;
|
||||
flash_waitstates = 7;
|
||||
cpu_freq = 216000000;
|
||||
|
||||
flash_set_waitstates(flash_waitstates);
|
||||
|
||||
/* Enable internal high-speed oscillator. */
|
||||
RCC_CR |= RCC_CR_HSION;
|
||||
DMB();
|
||||
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
|
||||
|
||||
/* Select HSI as SYSCLK source. */
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 1) | (1 << 0));
|
||||
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI);
|
||||
DMB();
|
||||
|
||||
/* Enable external high-speed oscillator 8MHz. */
|
||||
RCC_CR |= RCC_CR_HSEON;
|
||||
DMB();
|
||||
while ((RCC_CR & RCC_CR_HSERDY) == 0) {};
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, ABP1, ABP2.
|
||||
*/
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~(0xF0);
|
||||
RCC_CFGR = (reg32 | (hpre << 4));
|
||||
DMB();
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~(0x1C00);
|
||||
RCC_CFGR = (reg32 | (ppre1 << 10));
|
||||
DMB();
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~(0x07 << 13);
|
||||
RCC_CFGR = (reg32 | (ppre2 << 13));
|
||||
DMB();
|
||||
|
||||
/* Set PLL config */
|
||||
reg32 = RCC_PLLCFGR;
|
||||
reg32 &= ~(PLL_FULL_MASK);
|
||||
RCC_PLLCFGR = reg32 | RCC_PLLCFGR_PLLSRC | pllm |
|
||||
(plln << 6) | (((pllp >> 1) - 1) << 16) |
|
||||
(pllq << 24);
|
||||
DMB();
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
RCC_CR |= RCC_CR_PLLON;
|
||||
DMB();
|
||||
while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
reg32 = RCC_CFGR;
|
||||
reg32 &= ~((1 << 1) | (1 << 0));
|
||||
RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
|
||||
DMB();
|
||||
|
||||
/* Wait for PLL clock to be selected. */
|
||||
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SW_PLL) {};
|
||||
|
||||
/* Disable internal high-speed oscillator. */
|
||||
RCC_CR &= ~RCC_CR_HSION;
|
||||
}
|
||||
|
||||
void hal_init(void)
|
||||
{
|
||||
// asm volatile ("BKPT #0");
|
||||
#if defined(DUALBANK_SWAP) && defined(__WOLFBOOT)
|
||||
if ((FLASH_OPTCR & FLASH_OPTCR_nDBANK) != 0)
|
||||
fork_bootloader();
|
||||
#endif
|
||||
clock_pll_on(0);
|
||||
}
|
||||
|
||||
void RAMFUNCTION hal_prepare_boot(void)
|
||||
{
|
||||
#ifdef SPI_FLASH
|
||||
spi_release();
|
||||
#endif
|
||||
|
||||
clock_pll_off();
|
||||
}
|
||||
|
||||
void RAMFUNCTION hal_erase_bank2(void)
|
||||
{
|
||||
FLASH_CR |= FLASH_CR_MER2;
|
||||
FLASH_CR |= FLASH_CR_STRT;
|
||||
flash_wait_complete();
|
||||
FLASH_CR &= ~FLASH_CR_MER2;
|
||||
}
|
||||
|
||||
#if defined(DUALBANK_SWAP) && defined(__WOLFBOOT)
|
||||
|
||||
#define WOLFBOOT_ORIG_BOOTLOADER (0x08000000) /* Start of FLASH */
|
||||
#define WOLFBOOT_COPY_BOOTLOADER (0x08100000) /* First sector of second bank */
|
||||
#define BOOTLOADER_SIZE (32 * 1024)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void mass_erase(void)
|
||||
{
|
||||
FLASH_CR |= FLASH_CR_MER1;
|
||||
FLASH_CR |= FLASH_CR_STRT;
|
||||
flash_wait_complete();
|
||||
FLASH_CR &= ~FLASH_CR_MER1;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t bootloader_copy_mem[BOOTLOADER_SIZE];
|
||||
|
||||
void RAMFUNCTION fork_bootloader(void)
|
||||
{
|
||||
uint8_t *data = (uint8_t *) WOLFBOOT_ORIG_BOOTLOADER;
|
||||
uint32_t dst = WOLFBOOT_COPY_BOOTLOADER;
|
||||
uint32_t r = 0, w = 0;
|
||||
int i;
|
||||
|
||||
/* Read the wolfBoot image in RAM */
|
||||
memcpy(bootloader_copy_mem, data, BOOTLOADER_SIZE);
|
||||
|
||||
/* Disable ART pre-fetcher */
|
||||
FLASH_ACR &= ~(FLASH_ACR_PRFEN | FLASH_ACR_ARTEN);
|
||||
|
||||
/* Reset ART cache */
|
||||
FLASH_ACR |= FLASH_ACR_ARTRST;
|
||||
DMB();
|
||||
ISB();
|
||||
|
||||
|
||||
/* Unlock OPTCR */
|
||||
FLASH_OPTKEYR = FLASH_OPTKEY1;
|
||||
FLASH_OPTKEYR = FLASH_OPTKEY2;
|
||||
|
||||
/* Switch to dual bank */
|
||||
FLASH_OPTCR &= (~FLASH_OPTCR_nDBANK);
|
||||
FLASH_OPTCR |= FLASH_OPTCR_STRT;
|
||||
flash_wait_complete();
|
||||
DMB();
|
||||
|
||||
/* Mass-erase */
|
||||
hal_flash_unlock();
|
||||
for (i = 0x00; i < 0x04; i++)
|
||||
flash_erase_sector(i);
|
||||
hal_flash_write(WOLFBOOT_ORIG_BOOTLOADER, bootloader_copy_mem, BOOTLOADER_SIZE);
|
||||
hal_flash_lock();
|
||||
arch_reboot();
|
||||
}
|
||||
|
||||
|
||||
void RAMFUNCTION hal_flash_dualbank_swap(void)
|
||||
{
|
||||
/* Disable ART pre-fetcher */
|
||||
FLASH_ACR &= ~(FLASH_ACR_PRFEN | FLASH_ACR_ARTEN);
|
||||
/* Reset ART cache */
|
||||
FLASH_ACR |= FLASH_ACR_ARTRST;
|
||||
DMB();
|
||||
ISB();
|
||||
SYSCFG_MEMRMP |= MEMRMP_SWP_FB;
|
||||
DMB();
|
||||
/* Re-enable pre-fetchers */
|
||||
FLASH_ACR |= FLASH_ACR_PRFEN | FLASH_ACR_ARTEN;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x001FFE0
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000 /* mapping TCM only */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_start_text = .;
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
_end_text = .;
|
||||
} > FLASH
|
||||
|
||||
_stored_data = .;
|
||||
.data : AT (_stored_data)
|
||||
{
|
||||
_start_data = .;
|
||||
KEEP(*(.data*))
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.ramcode))
|
||||
. = ALIGN(4);
|
||||
_end_data = .;
|
||||
} > RAM
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
_start_bss = .;
|
||||
__bss_start__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_end_bss = .;
|
||||
__bss_end__ = .;
|
||||
_end = .;
|
||||
} > RAM
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
END_STACK = ORIGIN(RAM) + LENGTH(RAM);
|
|
@ -40,6 +40,10 @@ void hal_flash_unlock(void);
|
|||
void hal_flash_lock(void);
|
||||
void hal_prepare_boot(void);
|
||||
|
||||
#ifdef DUALBANK_SWAP
|
||||
void hal_flash_dualbank_swap(void);
|
||||
#endif
|
||||
|
||||
#ifdef EXT_FLASH
|
||||
#ifndef SPI_FLASH
|
||||
/* user supplied external flash interfaces */
|
||||
|
|
|
@ -91,7 +91,7 @@ static void *app_entry;
|
|||
static uint32_t app_end_stack;
|
||||
|
||||
|
||||
void do_boot(const uint32_t *app_offset)
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
||||
{
|
||||
|
||||
#ifndef NO_VTOR
|
||||
|
|
90
src/loader.c
90
src/loader.c
|
@ -32,6 +32,8 @@ extern void (** const IV_RAM)(void);
|
|||
#endif
|
||||
|
||||
#define FLASHBUFFER_SIZE 256
|
||||
|
||||
#ifndef DUALBANK_SWAP
|
||||
static int wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_image *dst, uint32_t sector)
|
||||
{
|
||||
uint32_t pos = 0;
|
||||
|
@ -165,6 +167,90 @@ static int wolfBoot_update(int fallback_allowed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else /* DUALBANK_SWAP */
|
||||
|
||||
static inline void boot_panic(void)
|
||||
{
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
static void RAMFUNCTION wolfBoot_start(void)
|
||||
{
|
||||
int ret;
|
||||
struct wolfBoot_image fw_image, boot_image;
|
||||
uint8_t p_state;
|
||||
uint32_t boot_v, update_v;
|
||||
int candidate = PART_BOOT;
|
||||
int fallback_is_possible = 0;
|
||||
|
||||
/* Find the candidate */
|
||||
boot_v = wolfBoot_current_firmware_version();
|
||||
update_v = wolfBoot_update_firmware_version();
|
||||
|
||||
/* panic if no images available */
|
||||
if ((boot_v == 0) && (update_v == 0))
|
||||
boot_panic();
|
||||
|
||||
else if (boot_v == 0) /* No primary image */
|
||||
{
|
||||
candidate = PART_UPDATE;
|
||||
}
|
||||
else if ((boot_v > 0) && (update_v > 0)) {
|
||||
fallback_is_possible = 1;
|
||||
if (update_v > boot_v)
|
||||
candidate = PART_UPDATE;
|
||||
}
|
||||
|
||||
/* Check current status for failure (still in TESTING), and fall-back
|
||||
* if an alternative is available
|
||||
*/
|
||||
if (fallback_is_possible &&
|
||||
(wolfBoot_get_partition_state(candidate, &p_state) == 0) &&
|
||||
(p_state == IMG_STATE_TESTING))
|
||||
{
|
||||
candidate ^= 1; /* switch to other partition if available */
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if ((wolfBoot_open_image(&fw_image, candidate) < 0) ||
|
||||
(wolfBoot_verify_integrity(&fw_image) < 0) ||
|
||||
(wolfBoot_verify_authenticity(&fw_image) < 0)) {
|
||||
|
||||
/* panic if authentication fails and no backup */
|
||||
if (!fallback_is_possible)
|
||||
boot_panic();
|
||||
else {
|
||||
/* Invalidate failing image and switch to the
|
||||
* other partition
|
||||
*/
|
||||
fallback_is_possible = 0;
|
||||
wolfBoot_erase_partition(candidate);
|
||||
candidate ^= 1;
|
||||
}
|
||||
} else
|
||||
break; /* candidate successfully authenticated */
|
||||
}
|
||||
|
||||
/* First time we boot this update, set to TESTING to await
|
||||
* confirmation from the system
|
||||
*/
|
||||
if ((wolfBoot_get_partition_state(candidate, &p_state) == 0) &&
|
||||
(p_state == IMG_STATE_UPDATING))
|
||||
{
|
||||
hal_flash_unlock();
|
||||
wolfBoot_set_partition_state(candidate, IMG_STATE_TESTING);
|
||||
hal_flash_lock();
|
||||
}
|
||||
|
||||
/* Booting from update is possible via HW-assisted swap */
|
||||
if (candidate == PART_UPDATE)
|
||||
hal_flash_dualbank_swap();
|
||||
|
||||
hal_prepare_boot();
|
||||
do_boot((void *)WOLFBOOT_PARTITION_BOOT_ADDRESS + IMAGE_HEADER_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RAM_CODE
|
||||
|
||||
|
@ -176,6 +262,8 @@ static void RAMFUNCTION wolfBoot_erase_bootloader(void)
|
|||
|
||||
}
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void RAMFUNCTION wolfBoot_self_update(struct wolfBoot_image *src)
|
||||
{
|
||||
uint32_t pos = 0;
|
||||
|
@ -238,6 +326,7 @@ static void wolfBoot_check_self_update(void)
|
|||
}
|
||||
#endif /* RAM_CODE for self_update */
|
||||
|
||||
#ifndef DUALBANK_SWAP
|
||||
static void wolfBoot_start(void)
|
||||
{
|
||||
uint8_t st;
|
||||
|
@ -268,6 +357,7 @@ static void wolfBoot_start(void)
|
|||
hal_prepare_boot();
|
||||
do_boot((void *)boot.fw_base);
|
||||
}
|
||||
#endif /* ifndef DUALBANK_SWAP */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08020100, LENGTH = 0x001FF00
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_start_text = .;
|
||||
KEEP(*(.isr_vector))
|
||||
*(.init)
|
||||
*(.fini)
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
_end_text = .;
|
||||
} > FLASH
|
||||
|
||||
_stored_data = .;
|
||||
|
||||
.data : AT (_stored_data)
|
||||
{
|
||||
_start_data = .;
|
||||
KEEP(*(.data*))
|
||||
. = ALIGN(4);
|
||||
_end_data = .;
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
_start_bss = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_end_bss = .;
|
||||
_end = .;
|
||||
} > RAM
|
||||
}
|
||||
|
||||
PROVIDE(_start_heap = _end);
|
||||
PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM));
|
|
@ -20,6 +20,10 @@ ifeq ($(V),0)
|
|||
endif
|
||||
|
||||
LSCRIPT:=$(ARCH).ld
|
||||
ifeq ($(TARGET),stm32f7)
|
||||
LSCRIPT=ARM-stm32f7.ld
|
||||
CFLAGS+=-DDUALBANK_SWAP
|
||||
endif
|
||||
LDFLAGS:=$(CFLAGS) -T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map
|
||||
|
||||
ifeq ($(EXT_FLASH),1)
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
/* stm32f7.c
|
||||
*
|
||||
* Test bare-metal application with UART update
|
||||
*
|
||||
* Copyright (C) 2018 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfBoot.
|
||||
*
|
||||
* wolfBoot is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfBoot 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "system.h"
|
||||
#include "hal.h"
|
||||
|
||||
|
||||
/* UART module */
|
||||
#define UART1_PIN_AF 7
|
||||
#define UART1_RX_PIN 10
|
||||
#define UART1_TX_PIN 9
|
||||
#define UART1 (0x40011000)
|
||||
#define UART1_CR1 (*(volatile uint32_t *)(UART1 + 0x00))
|
||||
#define UART1_CR2 (*(volatile uint32_t *)(UART1 + 0x04))
|
||||
#define UART1_BRR (*(volatile uint32_t *)(UART1 + 0x0C))
|
||||
#define UART1_ISR (*(volatile uint32_t *)(UART1 + 0x1C))
|
||||
#define UART1_RDR (*(volatile uint32_t *)(UART1 + 0x24))
|
||||
#define UART1_TDR (*(volatile uint32_t *)(UART1 + 0x28))
|
||||
#define UART_CR1_UART_ENABLE (1 << 0)
|
||||
#define UART_CR1_TX_ENABLE (1 << 3)
|
||||
#define UART_CR1_RX_ENABLE (1 << 2)
|
||||
#define UART_CR1_SYMBOL_LEN (1 << 28)
|
||||
#define UART_CR1_PARITY_ENABLED (1 << 10)
|
||||
#define UART_CR1_PARITY_ODD (1 << 9)
|
||||
#define UART_ISR_TX_EMPTY (1 << 7)
|
||||
#define UART_ISR_RX_NOTEMPTY (1 << 5)
|
||||
|
||||
#define CLOCK_SPEED (216000000)
|
||||
|
||||
#define APB2_CLOCK_ER (*(volatile uint32_t *)(0x40023844))
|
||||
#define UART1_APB2_CLOCK_ER (1 << 4)
|
||||
#define AHB1_CLOCK_ER (*(volatile uint32_t *)(0x40023830))
|
||||
#define GPIOA_AHB1_CLOCK_ER (1 << 0)
|
||||
#define GPIOD_AHB1_CLOCK_ER (1 << 3)
|
||||
#define GPIOA_BASE 0x40020000
|
||||
#define GPIOD_BASE 0x40020c00
|
||||
#define GPIOA_MODE (*(volatile uint32_t *)(GPIOA_BASE + 0x00))
|
||||
#define GPIOA_AFL (*(volatile uint32_t *)(GPIOA_BASE + 0x20))
|
||||
#define GPIOA_AFH (*(volatile uint32_t *)(GPIOA_BASE + 0x24))
|
||||
#define GPIOA_BSRR (*(volatile uint32_t *)(GPIOA_BASE + 0x18))
|
||||
#define GPIOA_PUPD (*(volatile uint32_t *)(GPIOA_BASE + 0x0c))
|
||||
#define GPIOD_MODE (*(volatile uint32_t *)(GPIOD_BASE + 0x00))
|
||||
#define GPIOD_OTYPE (*(volatile uint32_t *)(GPIOD_BASE + 0x04))
|
||||
#define GPIOD_OSPD (*(volatile uint32_t *)(GPIOD_BASE + 0x08))
|
||||
#define GPIOD_PUPD (*(volatile uint32_t *)(GPIOD_BASE + 0x0c))
|
||||
#define GPIOD_ODR (*(volatile uint32_t *)(GPIOD_BASE + 0x14))
|
||||
#define GPIOD_BSRR (*(volatile uint32_t *)(GPIOD_BASE + 0x18))
|
||||
#define GPIOD_AFL (*(volatile uint32_t *)(GPIOD_BASE + 0x20))
|
||||
#define GPIOD_AFH (*(volatile uint32_t *)(GPIOD_BASE + 0x24))
|
||||
void hal_erase_bank2(void);
|
||||
|
||||
void uart_write(const char c)
|
||||
{
|
||||
uint32_t reg;
|
||||
do {
|
||||
reg = UART1_ISR;
|
||||
} while ((reg & UART_ISR_TX_EMPTY) == 0);
|
||||
UART1_TDR = c;
|
||||
}
|
||||
|
||||
void uart_print(const char *s)
|
||||
{
|
||||
int i = 0;
|
||||
while(s[i])
|
||||
uart_write(s[i++]);
|
||||
}
|
||||
|
||||
static void uart_pins_setup(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
AHB1_CLOCK_ER |= GPIOA_AHB1_CLOCK_ER;
|
||||
/* Set mode = AF */
|
||||
reg = GPIOA_MODE & ~ (0x03 << (UART1_RX_PIN * 2));
|
||||
GPIOA_MODE = reg | (2 << (UART1_RX_PIN * 2));
|
||||
reg = GPIOA_MODE & ~ (0x03 << (UART1_TX_PIN * 2));
|
||||
GPIOA_MODE = reg | (2 << (UART1_TX_PIN * 2));
|
||||
|
||||
/* Alternate function: use hi pins (9 and 10) */
|
||||
reg = GPIOA_AFH & ~(0xf << ((UART1_TX_PIN - 8) * 4));
|
||||
GPIOA_AFH = reg | (UART1_PIN_AF << ((UART1_TX_PIN - 8) * 4));
|
||||
reg = GPIOA_AFH & ~(0xf << ((UART1_RX_PIN - 8) * 4));
|
||||
GPIOA_AFH = reg | (UART1_PIN_AF << ((UART1_RX_PIN - 8) * 4));
|
||||
}
|
||||
|
||||
int uart_setup(uint32_t bitrate, uint8_t data, char parity, uint8_t stop)
|
||||
{
|
||||
uint32_t reg;
|
||||
/* Enable pins and configure for AF7 */
|
||||
uart_pins_setup();
|
||||
/* Turn on the device */
|
||||
APB2_CLOCK_ER |= UART1_APB2_CLOCK_ER;
|
||||
|
||||
/* Configure for TX + RX */
|
||||
UART1_CR1 |= (UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE);
|
||||
|
||||
/* Configure clock */
|
||||
UART1_BRR = CLOCK_SPEED / bitrate;
|
||||
|
||||
/* Configure data bits */
|
||||
if (data == 8)
|
||||
UART1_CR1 &= ~UART_CR1_SYMBOL_LEN;
|
||||
else
|
||||
UART1_CR1 |= UART_CR1_SYMBOL_LEN;
|
||||
|
||||
/* Configure parity */
|
||||
switch (parity) {
|
||||
case 'O':
|
||||
UART1_CR1 |= UART_CR1_PARITY_ODD;
|
||||
/* fall through to enable parity */
|
||||
case 'E':
|
||||
UART1_CR1 |= UART_CR1_PARITY_ENABLED;
|
||||
break;
|
||||
default:
|
||||
UART1_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD);
|
||||
}
|
||||
/* Set stop bits (not supported)*/
|
||||
(void)stop;
|
||||
|
||||
/* Turn on uart */
|
||||
UART1_CR1 |= UART_CR1_UART_ENABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char uart_read(void)
|
||||
{
|
||||
char c;
|
||||
volatile uint32_t reg;
|
||||
do {
|
||||
reg = UART1_ISR;
|
||||
} while ((reg & UART_ISR_RX_NOTEMPTY) == 0);
|
||||
c = (char)(UART1_RDR & 0xff);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define MSGSIZE 16
|
||||
#define PAGESIZE (256)
|
||||
static uint8_t page[PAGESIZE];
|
||||
static const char ERR='!';
|
||||
static const char START='*';
|
||||
static const char UPDATE='U';
|
||||
static const char ACK='#';
|
||||
static uint8_t msg[MSGSIZE];
|
||||
|
||||
static void ack(uint32_t _off)
|
||||
{
|
||||
uint8_t *off = (uint8_t *)(&_off);
|
||||
int i;
|
||||
uart_write(ACK);
|
||||
for (i = 0; i < 4; i++) {
|
||||
uart_write(off[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int check(uint8_t *pkt, int size)
|
||||
{
|
||||
int i;
|
||||
uint16_t c = 0;
|
||||
uint16_t c_rx = *((uint16_t *)(pkt + 2));
|
||||
uint16_t *p = (uint16_t *)(pkt + 4);
|
||||
for (i = 0; i < ((size - 4) >> 1); i++)
|
||||
c += p[i];
|
||||
if (c == c_rx)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void uart_update_mgr(void)
|
||||
{
|
||||
uint32_t tlen = 0;
|
||||
volatile uint32_t recv_seq;
|
||||
uint32_t r_total = 0;
|
||||
uint32_t tot_len = 0;
|
||||
uint32_t next_seq = 0;
|
||||
uint32_t version = 0;
|
||||
uint8_t *v_array = (uint8_t *)&version;
|
||||
int i;
|
||||
memset(page, 0xFF, PAGESIZE);
|
||||
hal_flash_unlock();
|
||||
// version = wolfBoot_current_firmware_version();
|
||||
// if ((version & 0x01) == 0)
|
||||
// wolfBoot_success();
|
||||
uart_write(START);
|
||||
for (i = 3; i >= 0; i--) {
|
||||
uart_write(v_array[i]);
|
||||
}
|
||||
while (1) {
|
||||
r_total = 0;
|
||||
do {
|
||||
while(r_total < 2) {
|
||||
msg[r_total++] = uart_read();
|
||||
if ((r_total == 2) && ((msg[0] != 0xA5) || msg[1] != 0x5A)) {
|
||||
r_total = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
msg[r_total++] = uart_read();
|
||||
if ((tot_len == 0) && r_total == 2 + sizeof(uint32_t))
|
||||
break;
|
||||
if ((r_total > 8) && (tot_len <= ((r_total - 8) + next_seq)))
|
||||
break;
|
||||
} while (r_total < MSGSIZE);
|
||||
if (tot_len == 0) {
|
||||
tlen = msg[2] + (msg[3] << 8) + (msg[4] << 16) + (msg[5] << 24);
|
||||
if (tlen > 2048 * 1024) {
|
||||
uart_write(ERR);
|
||||
uart_write(ERR);
|
||||
uart_write(ERR);
|
||||
uart_write(ERR);
|
||||
uart_write(START);
|
||||
recv_seq = 0;
|
||||
tot_len = 0;
|
||||
continue;
|
||||
}
|
||||
tot_len = tlen;
|
||||
hal_erase_bank2();
|
||||
ack(0);
|
||||
continue;
|
||||
}
|
||||
if (check(msg, r_total) < 0) {
|
||||
ack(next_seq);
|
||||
continue;
|
||||
}
|
||||
recv_seq = msg[4] + (msg[5] << 8) + (msg[6] << 16) + (msg[7] << 24);
|
||||
if (recv_seq == next_seq)
|
||||
{
|
||||
int psize = r_total - 8;
|
||||
int page_idx = recv_seq % PAGESIZE;
|
||||
memcpy(&page[recv_seq % PAGESIZE], msg + 8, psize);
|
||||
page_idx += psize;
|
||||
if ((page_idx == PAGESIZE) || (next_seq + psize >= tot_len)) {
|
||||
uint32_t dst = (0x08120000, recv_seq + psize) - page_idx;
|
||||
hal_flash_write(dst, page, PAGESIZE);
|
||||
memset(page, 0xFF, PAGESIZE);
|
||||
}
|
||||
next_seq += psize;
|
||||
}
|
||||
ack(next_seq);
|
||||
if (next_seq >= tot_len) {
|
||||
/* Update complete */
|
||||
//wolfBoot_update_trigger();
|
||||
hal_flash_lock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Wait for reboot */
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
|
||||
#define LED_BOOT_PIN (4)
|
||||
#define LED_USR_PIN (12)
|
||||
void boot_led_on(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t pin = LED_BOOT_PIN;
|
||||
AHB1_CLOCK_ER |= GPIOD_AHB1_CLOCK_ER;
|
||||
reg = GPIOD_MODE & ~(0x03 << (pin * 2));
|
||||
GPIOD_MODE = reg | (1 << (pin * 2));
|
||||
reg = GPIOD_PUPD & ~(0x03 << (pin * 2));
|
||||
GPIOD_PUPD = reg | (1 << (pin * 2));
|
||||
GPIOD_BSRR |= (1 << pin);
|
||||
}
|
||||
|
||||
void boot_led_off(void)
|
||||
{
|
||||
GPIOD_BSRR |= (1 << (LED_BOOT_PIN + 16));
|
||||
}
|
||||
|
||||
void usr_led_on(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t pin = LED_USR_PIN;
|
||||
AHB1_CLOCK_ER |= GPIOA_AHB1_CLOCK_ER;
|
||||
reg = GPIOA_MODE & ~(0x03 << (pin * 2));
|
||||
GPIOA_MODE = reg | (1 << (pin * 2));
|
||||
reg = GPIOA_PUPD & ~(0x03 << (pin * 2));
|
||||
GPIOA_PUPD = reg | (1 << (pin * 2));
|
||||
GPIOA_BSRR |= (1 << pin);
|
||||
}
|
||||
|
||||
void usr_led_off(void)
|
||||
{
|
||||
GPIOA_BSRR |= (1 << (LED_USR_PIN + 16));
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
hal_init();
|
||||
|
||||
boot_led_on();
|
||||
usr_led_on();
|
||||
boot_led_off();
|
||||
// usr_led_off();
|
||||
uart_setup(115200, 8, 'N', 1);
|
||||
uart_update_mgr();
|
||||
while(1)
|
||||
;
|
||||
}
|
|
@ -20,8 +20,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
#ifdef PLATFORM_stm32f4
|
||||
|
||||
#if defined(PLATFORM_stm32f4) || defined(PLATFORM_stm32f7)
|
||||
#include <stdint.h>
|
||||
#include "system.h"
|
||||
|
||||
|
@ -58,16 +57,29 @@
|
|||
#define RCC_PRESCALER_DIV_4 9
|
||||
|
||||
|
||||
/* STM32F4-Discovery, 168 MHz */
|
||||
#ifdef PLATFORM_stm32f4
|
||||
# define PLLM 8
|
||||
# define PLLN 336
|
||||
# define PLLP 2
|
||||
# define PLLQ 7
|
||||
# define PLLR 0
|
||||
# define TARGET_FLASH_WAITSTATES 5
|
||||
#endif
|
||||
|
||||
#define PLLM 8
|
||||
#define PLLN 336
|
||||
#define PLLP 2
|
||||
#define PLLQ 7
|
||||
#define PLLR 0
|
||||
/* STM32F7-Discovery, 216 MHz */
|
||||
#ifdef PLATFORM_stm32f7
|
||||
# define PLLM 25
|
||||
# define PLLN 432
|
||||
# define PLLP 2
|
||||
# define PLLQ 9
|
||||
# define PLLR 0
|
||||
# define TARGET_FLASH_WAITSTATES 7
|
||||
#endif
|
||||
|
||||
void flash_set_waitstates(void)
|
||||
{
|
||||
FLASH_ACR |= 5 | FLASH_ACR_ENABLE_DATA_CACHE | FLASH_ACR_ENABLE_INST_CACHE;
|
||||
FLASH_ACR |= TARGET_FLASH_WAITSTATES | FLASH_ACR_ENABLE_DATA_CACHE | FLASH_ACR_ENABLE_INST_CACHE;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue