Skip to content

Commit

Permalink
Added instant boot on power on; Added SHA256 check from EEPROM before…
Browse files Browse the repository at this point in the history
… booting; faster startup; Faster DHCP; Added Status LED
  • Loading branch information
ClemensElflein committed Oct 24, 2024
1 parent 57a96e1 commit add6d7b
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 75 deletions.
3 changes: 2 additions & 1 deletion bootloader/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O3 -ggdb -fomit-frame-pointer -falign-functions=16
USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
endif

# C specific options here (added to USE_OPT).
Expand Down Expand Up @@ -127,6 +127,7 @@ CSRC = $(ALLCSRC) \
src/id_eeprom.c \
src/bootloader.c \
src/stm32hal.c \
src/status_led.c \
main.c

# C++ sources that can be compiled in ARM or THUMB mode depending on the global
Expand Down
8 changes: 6 additions & 2 deletions bootloader/boards/ST_NUCLEO144_H723ZG/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
#define GPIOC_PIN11 11U
#define GPIOC_PIN12 12U
#define GPIOC_BUTTON 13U
#define GPIOC_PREVENT_BOOT_BUTTON 13U
#define GPIOC_OSC32_IN 14U
#define GPIOC_OSC32_OUT 15U

Expand All @@ -144,6 +145,7 @@
#define GPIOE_PIN0 0U
#define GPIOE_LED2 1U
#define GPIOE_LED_YELLOW 1U
#define GPIOE_STATUS_LED 1U
#define GPIOE_PIN2 2U
#define GPIOE_PIN3 3U
#define GPIOE_PIN4 4U
Expand Down Expand Up @@ -289,6 +291,7 @@
#define LINE_RMII_RXD0 PAL_LINE(GPIOC, 4U)
#define LINE_RMII_RXD1 PAL_LINE(GPIOC, 5U)
#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
#define LINE_PREVENT_BOOT_BUTTON PAL_LINE(GPIOC, 13U)
#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
#define LINE_USART3_RX PAL_LINE(GPIOD, 8U)
Expand All @@ -298,6 +301,7 @@
#define LINE_USB_FS_PWR_EN PAL_LINE(GPIOD, 10U)
#define LINE_LED2 PAL_LINE(GPIOE, 1U)
#define LINE_LED_YELLOW PAL_LINE(GPIOE, 1U)
#define LINE_STATUS_LED PAL_LINE(GPIOE, 1U)
#define LINE_USB_FS_OVCR PAL_LINE(GPIOG, 7U)
#define LINE_RMII_TX_EN PAL_LINE(GPIOG, 11U)
#define LINE_RMII_TXD0 PAL_LINE(GPIOG, 13U)
Expand Down Expand Up @@ -592,7 +596,7 @@
* PC10 - PIN10 (input pullup).
* PC11 - PIN11 (input pullup).
* PC12 - PIN12 (input pullup).
* PC13 - BUTTON (input floating).
* PC13 - BUTTON PREVENT_BOOT_BUTTON(input floating).
* PC14 - OSC32_IN (input floating).
* PC15 - OSC32_OUT (input floating).
*/
Expand Down Expand Up @@ -814,7 +818,7 @@
* GPIOE setup:
*
* PE0 - PIN0 (input pullup).
* PE1 - LED2 LED_YELLOW (output pushpull maximum).
* PE1 - LED2 LED_YELLOW STATUS_LED(output pushpull maximum).
* PE2 - PIN2 (input pullup).
* PE3 - PIN3 (input pullup).
* PE4 - PIN4 (input pullup).
Expand Down
1 change: 1 addition & 0 deletions bootloader/boards/ST_NUCLEO144_H723ZG/board_ex.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define BOARD_NAME "Nucleo144-H723ZG"
#define BOARD_VERSION_MAJOR 1
#define BOARD_VERSION_MINOR 0
#define BOARD_VERSION_PATCH 0

// Define the fallback IP settings for this board (if DHCP fails)
// 10.0.0.254
Expand Down
4 changes: 2 additions & 2 deletions bootloader/boards/ST_NUCLEO144_H723ZG/cfg/board.chcfg
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@
Mode="Input"
Alternate="0" />
<pin13
ID="BUTTON"
ID="BUTTON PREVENT_BOOT_BUTTON"
Type="PushPull"
Level="High"
Speed="Minimum"
Expand Down Expand Up @@ -558,7 +558,7 @@
Mode="Input"
Alternate="0" />
<pin1
ID="LED2 LED_YELLOW"
ID="LED2 LED_YELLOW STATUS_LED"
Type="PushPull"
Level="Low"
Speed="Maximum"
Expand Down
4 changes: 2 additions & 2 deletions bootloader/boards/ST_NUCLEO144_H723ZG/cfg/board.fmpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
sourceRoot: ../../../../../../tools/ftl/processors/boards/stm32h7xx/templates
sourceRoot: ../../../ext/ChibiOS_21.11.3/tools/ftl/processors/boards/stm32h7xx/templates
outputRoot: ..
dataRoot: .

freemarkerLinks: {
lib: ../../../../../../tools/ftl/libs
lib: ../../../ext/ChibiOS_21.11.3/tools/ftl/libs
}

data : {
Expand Down
2 changes: 1 addition & 1 deletion bootloader/cfg/halconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#define HAL_USE_RTC TRUE
#endif

/**
Expand Down
8 changes: 6 additions & 2 deletions bootloader/cfg/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#ifndef __LWIPOPT_H__
#define __LWIPOPT_H__

// LWIP_LINK_POLL_INTERVAL is set low here in order to have quicker startup time.
#define LWIP_LINK_POLL_INTERVAL TIME_MS2I(1000)

/*
-----------------------------------------------
Expand Down Expand Up @@ -680,8 +682,10 @@
* DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address.
*/
#ifndef DHCP_DOES_ARP_CHECK
#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP))
#define DHCP_DOES_ARP_CHECK 0
#endif
// Same option, but for newer LWIP version
#define LWIP_DHCP_DOES_ACD_CHECK 0

/*
------------------------------------
Expand Down Expand Up @@ -1123,7 +1127,7 @@
* changes its up/down status (i.e., due to DHCP IP acquistion)
*/
#ifndef LWIP_NETIF_STATUS_CALLBACK
#define LWIP_NETIF_STATUS_CALLBACK 0
#define LWIP_NETIF_STATUS_CALLBACK 1
#endif

/**
Expand Down
125 changes: 104 additions & 21 deletions bootloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,60 @@
#include <id_eeprom.h>
#include <lwip/dhcp.h>
#include <service_discovery.h>
#include <sha256.h>
#include <status_led.h>
#include <string.h>

#include "lwipthread.h"

void link_up(struct netif *netif) {
if (netif->ip_addr.addr != 0) {
chEvtBroadcastFlags(&netif_events, NETIF_FLAG_BROADCAST);
}
}

bool jump_to_user_program(void) {
RTC->BKP0R = 0xB0043D;
#ifdef BOARD_HAS_EEPROM

// Check, if we have a valid image
struct bootloader_info info = {0};
if (!ID_EEPROM_GetBootloaderInfo(&info)) {
// If we don't have a valid image, stay in bootloader and allow bootloading
// again
return false;
}

// Check, if image size is valid
if (info.image_size > PROGRAM_FLASH_SIZE_BYTES) {
return false;
}

// If we have a valid info in our EEPROM, verify the hash before booting
SHA256_CTX sha256;
uint8_t validate_hash[32] = {0};
sha256_init(&sha256);
sha256_update(&sha256, (uint8_t *)TARGET_FLASH_ADDRESS, info.image_size);
sha256_final(&sha256, validate_hash);
if (memcmp(validate_hash, info.image_sha256, sizeof(validate_hash)) == 0) {
// Program OK, now we can boot to it.
RTC->BKP0R = 0xB0043D;
MODIFY_REG(SYSCFG->UR2, SYSCFG_UR2_BOOT_ADD0,
(BOOT_ADDRESS >> 16) << SYSCFG_UR2_BOOT_ADD0_Pos);
NVIC_SystemReset();
} else {
return false;
}

#else
// We don't have EEPROM, so we cannot verify the image, just jump to it.
RTC->BKP0R = 0xB0043D;
MODIFY_REG(SYSCFG->UR2, SYSCFG_UR2_BOOT_ADD0,
(BOOT_ADDRESS >> 16) << SYSCFG_UR2_BOOT_ADD0_Pos);
NVIC_SystemReset();
#endif
}

/*
* Application entry point.
*/
Expand All @@ -36,44 +87,76 @@ int main(void) {
*/
InitGlobals();
InitHeartbeat();
InitStatusLed();

// True, when the board was started via power up. If we have a valid image,
// directly jump to it without waiting.
bool is_started_from_power_up = RTC->BKP0R != 0xB0043D;

if (is_started_from_power_up) {
SetStatusLedMode(LED_MODE_BLINK_SLOW);
// No need to actually catch the return value here.
// If success, we won't return
// If fail, we bootload as usual.
jump_to_user_program();
}

SetStatusLedMode(LED_MODE_BLINK_FAST);

/*
* Setup LWIP stack using the MAC address provided by the EEPROM.
*/
uint8_t mac_address[6] = {0};
ID_EEPROM_GetMacAddress(mac_address, sizeof(mac_address));
lwipthread_opts_t lwipconf_opts = {0};
lwipconf_opts.addrMode = NET_ADDRESS_STATIC;
lwipconf_opts.address = PP_HTONL(FALLBACK_IP_ADDRESS);
lwipconf_opts.gateway = PP_HTONL(FALLBACK_GATEWAY);
lwipconf_opts.netmask = PP_HTONL(FALLBACK_NETMASK);
lwipconf_opts.addrMode = NET_ADDRESS_DHCP;
lwipconf_opts.address = 0;
lwipconf_opts.gateway = 0;
lwipconf_opts.netmask = 0;
lwipconf_opts.macaddress = mac_address;
lwipInit(&lwipconf_opts);
netif_set_status_callback(netif_default, link_up);

// Start the ServiceDiscovery Task.
InitServiceDiscovery();
// Wait for the interface to come up (DHCP)
event_listener_t event_listener;
chEvtRegister(&netif_events, &event_listener, 0);
// 10 second timeout
eventmask_t events =
chEvtWaitAnyTimeout(NETIF_EVENT_ADDRESS_VALID, TIME_S2I(10));
bool got_address = (events & NETIF_EVENT_ADDRESS_VALID) != 0;
if (got_address) {
// Start Service Discovery and Bootloader Thread
SetStatusLedMode(LED_MODE_BLINK_SLOW);

// Start the actual Bootloader Task
InitBootloaderThread();
// Start the ServiceDiscovery Task.
InitServiceDiscovery();

chThdSleep(TIME_INFINITE);
// Start the actual Bootloader Task
InitBootloaderThread();

uint32_t sleep_count = 1000 / 100;
while (sleep_count-- > 0) {
chThdSleep(TIME_MS2I(100));
if (palReadLine(LINE_BUTTON)) {
// sleep forever, don't boot into user software
chThdSleep(TIME_INFINITE);
// Timer before starting into user program
#ifndef LINE_PREVENT_BOOT_BUTTON
chThdSleep(TIME_S2I(5));
#else
// instead of just sleeping, we can poll a user button to keep device from
// entering user program
uint32_t sleep_count = 1000 / 100;
while (sleep_count-- > 0) {
chThdSleep(TIME_MS2I(100));
if (palReadLine(LINE_BUTTON)) {
// sleep forever, don't boot into user software
chThdSleep(TIME_INFINITE);
}
}
#endif
}

// prevent bootloader from bootloading
chMtxLock(&reboot_mutex);

MODIFY_REG(SYSCFG->UR2, SYSCFG_UR2_BOOT_ADD0,
(BOOT_ADDRESS >> 16) << SYSCFG_UR2_BOOT_ADD0_Pos);
NVIC_SystemReset();
jump_to_user_program();

while (1) {
chThdSleep(100);
}
// allow bootloader to work again, since jumping to user program didn't work
chMtxUnlock(&reboot_mutex);
chThdSleep(TIME_INFINITE);
}
Loading

0 comments on commit add6d7b

Please sign in to comment.