mirror of https://github.com/wolfSSL/wolfBoot.git
STM32H7 Test Program
This wolfBoot application has been specifically developed for and tested on NUCLEO-H753ZI. Toogle between application A and B to use the application code to test firmware update capability of wolfBoot and to distinguish the two application versions.pull/103/head
parent
3516620f1a
commit
cff0c54cc5
|
@ -21,6 +21,15 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/** ------------------------------------------------------------------------------------------------------------------------
|
||||
* WOLFBOOT APPLICATION FOR NUCLEO-H753ZI BOARD ONLY! |
|
||||
* |
|
||||
* The following application runs on the above mentioned board. |
|
||||
* It contains setup of LD1, LD2 and LD3. |
|
||||
* As well as setup of UART serial commmunication using USART2 on pins PD5 (TX) and PD6 (RX). |
|
||||
* ------------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -29,68 +38,370 @@
|
|||
#include "hal.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
|
||||
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
|
||||
#define READ_BIT(REG, BIT) ((REG) & (BIT))
|
||||
#define CLEAR_REG(REG) ((REG) = (0x00))
|
||||
#define WRITE_REG(REG, VAL) ((REG) = (VAL))
|
||||
#define READ_REG(REG) ((REG))
|
||||
#define UNUSED(x) ((void)(x))
|
||||
|
||||
#define AHB4_CLOCK_ER (*(volatile uint32_t *)(0x580244E0))
|
||||
#define GPIOB_AHB4_CLOCK_ER (1 << 1)
|
||||
#define GPIOE_AHB4_CLOCK_ER (1 << 4)
|
||||
// ASSEMBLY HELPERS
|
||||
// ======================================================================
|
||||
// It ensures that all explicit memory accesses are observed.
|
||||
#ifndef DMB
|
||||
#define DMB() __asm__ volatile("dmb") // DMB: Data Memory Barrier
|
||||
#endif
|
||||
|
||||
#ifndef ISB
|
||||
#define ISB() __asm__ volatile("isb") // ISB: Instruction Synchronization Barrier
|
||||
#endif
|
||||
|
||||
#ifndef DSB
|
||||
#define DSB() __asm__ volatile("dsb") // DSB: Data Synchronization Barrier
|
||||
#endif
|
||||
|
||||
// GENERAL DEFINITIONS
|
||||
// ======================================================================
|
||||
#define FIRMWARE_A 1
|
||||
#define FIRMWARE_B 0
|
||||
|
||||
#define LED_OFF 0
|
||||
#define LED_INIT 1
|
||||
#define LED_ON 2
|
||||
|
||||
// USER LED
|
||||
// ======================================================================
|
||||
// Defining LED pin numbers in the corresponding GPIO group
|
||||
#define LD1_PIN (0) // Nucleo LD1 - Green Led
|
||||
#define LD2_PIN (1) // Nucleo LD2 - Yellow Led
|
||||
#define LD3_PIN (14) // Nucleo LD3 - Red Led
|
||||
|
||||
// GPIO GROUP B
|
||||
#define GPIOB_BASE 0x58020400
|
||||
#define GPIOE_BASE 0x58021000
|
||||
#define GPIOB_MODE (*(volatile uint32_t *)(GPIOB_BASE + 0x00))
|
||||
#define GPIOB_PUPD (*(volatile uint32_t *)(GPIOB_BASE + 0x0c))
|
||||
#define GPIOB_BSRR (*(volatile uint32_t *)(GPIOB_BASE + 0x18))
|
||||
#define GPIOB_AFL (*(volatile uint32_t *)(GPIOB_BASE + 0x20))
|
||||
#define GPIOB_AFH (*(volatile uint32_t *)(GPIOB_BASE + 0x24))
|
||||
#define GPIOB_AHB4_CLOCK_ER (1 << 1)
|
||||
|
||||
// GPIO GROUP E
|
||||
#define GPIOE_BASE 0x58021000
|
||||
#define GPIOE_MODE (*(volatile uint32_t *)(GPIOE_BASE + 0x00))
|
||||
#define GPIOE_PUPD (*(volatile uint32_t *)(GPIOE_BASE + 0x0c))
|
||||
#define GPIOE_BSRR (*(volatile uint32_t *)(GPIOE_BASE + 0x18))
|
||||
#define GPIOE_AFL (*(volatile uint32_t *)(GPIOE_BASE + 0x20))
|
||||
#define GPIOE_AFH (*(volatile uint32_t *)(GPIOE_BASE + 0x24))
|
||||
#define GPIOE_AHB4_CLOCK_ER (1 << 4)
|
||||
|
||||
// UART SETUP
|
||||
// ======================================================================
|
||||
// USART2 Base address (chosen because of its pin layout on Nucleo board)
|
||||
#define UART_BASE (0x40004400)
|
||||
#define RCC_BASE (0x58024400)
|
||||
#define GPIOD_BASE (0x58020C00)
|
||||
|
||||
#define LED_BOOT_PIN (0) //PB0 - Nucleo LD1 - Green Led
|
||||
#define LED_USR_PIN (1) //PE1 - Nucleo LD2 - Yellow Led
|
||||
static void boot_led_on(void)
|
||||
#define UART_PIN_AF 7 // AF stands for Alternate Function. For PD5/PD6 AF7 equals USART2 RX/TX.
|
||||
#define UART_TX_PIN 5 // PD5, USART Transmit pin
|
||||
#define UART_RX_PIN 6 // PD6, USART Receive pin
|
||||
|
||||
// UART/USART: Defining register start addresses.
|
||||
#define UART_CR1 (*(volatile uint32_t *)(UART_BASE + 0x00))
|
||||
#define UART_CR2 (*(volatile uint32_t *)(UART_BASE + 0x04))
|
||||
#define UART_BRR (*(volatile uint32_t *)(UART_BASE + 0x0C))
|
||||
#define UART_ISR (*(volatile uint32_t *)(UART_BASE + 0x1C))
|
||||
#define UART_RDR (*(volatile uint32_t *)(UART_BASE + 0x24))
|
||||
#define UART_TDR (*(volatile uint32_t *)(UART_BASE + 0x28))
|
||||
#define UART_RQR (*(volatile uint32_t *)(UART_BASE + 0x18))
|
||||
|
||||
// RCC: Defining register start addresses.
|
||||
#define RCC_D2CCIP2R (*(volatile uint32_t *)(RCC_BASE + 0x54))
|
||||
#define RCC_AHB1ENR (*(volatile uint32_t *)(RCC_BASE + 0xD8))
|
||||
#define RCC_AHB4ENR (*(volatile uint32_t *)(RCC_BASE + 0xE0))
|
||||
#define RCC_APB1ENR (*(volatile uint32_t *)(RCC_BASE + 0xE8))
|
||||
#define RCC_APB2ENR (*(volatile uint32_t *)(RCC_BASE + 0xF0))
|
||||
|
||||
// GPIO: Defining register start addresses.
|
||||
#define GPIOD_MODE (*(volatile uint32_t *)(GPIOD_BASE + 0x00))
|
||||
#define GPIOD_BSRR (*(volatile uint32_t *)(GPIOD_BASE + 0x18))
|
||||
#define GPIOD_AFRL (*(volatile uint32_t *)(GPIOD_BASE + 0x20))
|
||||
#define GPIOD_AFRH (*(volatile uint32_t *)(GPIOD_BASE + 0x24))
|
||||
|
||||
// UART/USART: Defining register bit placement for CR1 and ISR register for readabilty.
|
||||
#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_FIFO_NOT_FULL (1 << 7)
|
||||
#define UART_ISR_RX_FIFO_NOT_EMPTY (1 << 5)
|
||||
#define UART_ISR_TRANSMISSION_COMPLETE (1 << 6)
|
||||
#define UART_ISR_TX_DATA_REGISTER_EMPTY (1 << 7)
|
||||
|
||||
// RCC: Defining register bit placement for APB1, APB2, AHB1 and AHB4 register for readabilty.
|
||||
#define RCC_APB1_USART2_EN (1 << 17)
|
||||
#define RCC_APB1_USART3_EN (1 << 18)
|
||||
#define RCC_APB1_UART4_EN (1 << 19)
|
||||
#define RCC_APB1_UART5_EN (1 << 20)
|
||||
#define RCC_APB1_UART7_EN (1 << 30)
|
||||
#define RCC_APB1_UART8_EN (1 << 31)
|
||||
#define RCC_APB2_USART1_EN (1 << 4)
|
||||
#define RCC_APB2_USART6_EN (1 << 5)
|
||||
#define RCC_AHB1_DMA1_EN (1 << 0)
|
||||
#define RCC_AHB1_DMA2_EN (1 << 1)
|
||||
#define RCC_AHB4_GPIOD_EN (1 << 3)
|
||||
|
||||
// HSI Clock speed
|
||||
#define CLOCK_SPEED 64000000
|
||||
|
||||
// Marking the update partition as ready to be swapped and executed.
|
||||
#define UPDATE_PARTITION_BASE (0x08060000)
|
||||
// The four character is expected to write: W O L F (0x57 0x4F 0x4C 0x46)
|
||||
// Character = W. Hex = 57. BIN = 0101 0111, DEC = 87
|
||||
#define UPDATE_CHARACTER_1 (*(volatile uint32_t *)(UPDATE_PARTITION_BASE + 0x00))
|
||||
// Character = O. Hex = 4F. BIN = 0100 1111
|
||||
#define UPDATE_CHARACTER_2 (*(volatile uint32_t *)(UPDATE_PARTITION_BASE + 0x01))
|
||||
// Character = L. Hex = 4C. BIN = 0100 1100
|
||||
#define UPDATE_CHARACTER_3 (*(volatile uint32_t *)(UPDATE_PARTITION_BASE + 0x02))
|
||||
// Character = F. Hex = 46. BIN = 0100 0110
|
||||
#define UPDATE_CHARACTER_4 (*(volatile uint32_t *)(UPDATE_PARTITION_BASE + 0x03))
|
||||
|
||||
// Marking the update partition as ready to be swapped and executed.
|
||||
#define UPDATE_PARTITION_MAGIC_BASE (0x0809FFFC)
|
||||
#define UPDATE_MAGIC_1 (*(volatile uint32_t *)(UPDATE_PARTITION_MAGIC_BASE + 0x00))
|
||||
#define UPDATE_MAGIC_2 (*(volatile uint32_t *)(UPDATE_PARTITION_MAGIC_BASE + 0x01))
|
||||
#define UPDATE_MAGIC_3 (*(volatile uint32_t *)(UPDATE_PARTITION_MAGIC_BASE + 0x02))
|
||||
#define UPDATE_MAGIC_4 (*(volatile uint32_t *)(UPDATE_PARTITION_MAGIC_BASE + 0x03))
|
||||
|
||||
static void ld1_write(uint8_t led_status)
|
||||
{
|
||||
if (led_status == 0)
|
||||
{
|
||||
SET_BIT(GPIOB_BSRR, (1 << (LD1_PIN + 16)));
|
||||
}
|
||||
else if (led_status == 2)
|
||||
{
|
||||
SET_BIT(GPIOB_BSRR, (1 << LD1_PIN));
|
||||
}
|
||||
else if (led_status == 1)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t pin = LED_BOOT_PIN;
|
||||
AHB4_CLOCK_ER |= GPIOB_AHB4_CLOCK_ER;
|
||||
uint32_t pin = LD1_PIN;
|
||||
SET_BIT(RCC_AHB4ENR, GPIOB_AHB4_CLOCK_ER);
|
||||
reg = GPIOB_MODE & ~(0x03 << (pin * 2));
|
||||
GPIOB_MODE = reg | (1 << (pin * 2));
|
||||
reg = GPIOB_PUPD & ~(0x03 << (pin * 2));
|
||||
GPIOB_PUPD = reg | (1 << (pin * 2));
|
||||
GPIOB_BSRR |= (1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void boot_led_off(void)
|
||||
{
|
||||
GPIOB_BSRR |= (1 << (LED_BOOT_PIN + 16));
|
||||
}
|
||||
|
||||
void usr_led_on(void)
|
||||
static void ld2_write(uint8_t led_status)
|
||||
{
|
||||
if (led_status == 0)
|
||||
{
|
||||
GPIOE_BSRR |= (1 << (LD2_PIN + 16));
|
||||
}
|
||||
else if (led_status == 2)
|
||||
{
|
||||
SET_BIT(GPIOE_BSRR, (1 << LD2_PIN));
|
||||
}
|
||||
else if (led_status == 1)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t pin = LED_USR_PIN;
|
||||
AHB4_CLOCK_ER |= GPIOE_AHB4_CLOCK_ER;
|
||||
uint32_t pin = LD2_PIN;
|
||||
RCC_AHB4ENR |= GPIOE_AHB4_CLOCK_ER;
|
||||
reg = GPIOE_MODE & ~(0x03 << (pin * 2));
|
||||
GPIOE_MODE = reg | (1 << (pin * 2));
|
||||
reg = GPIOE_PUPD & ~(0x03 << (pin * 2));
|
||||
GPIOE_PUPD = reg | (1 << (pin * 2));
|
||||
GPIOE_BSRR |= (1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
void usr_led_off(void)
|
||||
static void ld3_write(uint8_t led_status)
|
||||
{
|
||||
GPIOE_BSRR |= (1 << (LED_USR_PIN + 16));
|
||||
if (led_status == 0)
|
||||
{
|
||||
GPIOB_BSRR |= (1 << (LD3_PIN + 16));
|
||||
}
|
||||
else if (led_status == 2)
|
||||
{
|
||||
SET_BIT(GPIOB_BSRR, (1 << LD3_PIN));
|
||||
}
|
||||
else if (led_status == 1)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t pin = LD3_PIN;
|
||||
RCC_AHB4ENR |= GPIOB_AHB4_CLOCK_ER;
|
||||
reg = GPIOB_MODE & ~(0x03 << (pin * 2));
|
||||
GPIOB_MODE = reg | (1 << (pin * 2));
|
||||
reg = GPIOB_PUPD & ~(0x03 << (pin * 2));
|
||||
GPIOB_PUPD = reg | (1 << (pin * 2));
|
||||
GPIOB_BSRR |= (1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
int uart_setup(uint32_t bitrate)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
if ((bitrate != 9600) && (bitrate != 115200))
|
||||
return -1; // Bitrate not accepted
|
||||
|
||||
// Enable UART pins
|
||||
SET_BIT(RCC_AHB4ENR, RCC_AHB4_GPIOD_EN);
|
||||
|
||||
// Set mode = AF. The PORT D I/O pin is first reset and then set to AF (bit config 10:Alternate function mode)
|
||||
reg = GPIOD_MODE & ~(0x03 << (UART_TX_PIN * 2));
|
||||
GPIOD_MODE = reg | (2 << (UART_TX_PIN * 2));
|
||||
reg = GPIOD_MODE & ~(0x03 << (UART_RX_PIN * 2));
|
||||
GPIOD_MODE = reg | (2 << (UART_RX_PIN * 2));
|
||||
|
||||
// Alternate function. Use AFLR for pins 0-7 and AFHR for pins 8-15
|
||||
reg = GPIOD_AFRL & ~(0xf << ((UART_TX_PIN)*4));
|
||||
GPIOD_AFRL = reg | (UART_PIN_AF << ((UART_TX_PIN)*4));
|
||||
reg = GPIOD_AFRL & ~(0xf << ((UART_RX_PIN)*4));
|
||||
GPIOD_AFRL = reg | (UART_PIN_AF << ((UART_RX_PIN)*4));
|
||||
|
||||
// Disable UART to enable settings to be written into the registers.
|
||||
if (READ_BIT(UART_CR1, UART_CR1_UART_ENABLE) == 1)
|
||||
{
|
||||
CLEAR_BIT(UART_CR1, UART_CR1_UART_ENABLE);
|
||||
}
|
||||
|
||||
// Set general UART clock source (all uarts but nr 1 and 6). 011 = HSI Clock Source
|
||||
SET_BIT(RCC_D2CCIP2R, (1 << 0));
|
||||
SET_BIT(RCC_D2CCIP2R, (1 << 1));
|
||||
CLEAR_BIT(RCC_D2CCIP2R, (1 << 2));
|
||||
|
||||
// Enable clock for USART_2
|
||||
SET_BIT(RCC_APB1ENR, RCC_APB1_USART2_EN);
|
||||
|
||||
// Enable FIFO mode
|
||||
SET_BIT(UART_CR1, (1 << 29));
|
||||
|
||||
// Configure the M bits (word length)
|
||||
CLEAR_BIT(UART_CR1, (1 << 28)); // Word length is 8 bits by default
|
||||
CLEAR_BIT(UART_CR1, (1 << 12)); // Word length is 8 bits by default
|
||||
|
||||
// Configure clock (speed/bitrate). Requires UE = 0.
|
||||
WRITE_REG(UART_BRR, (CLOCK_SPEED / bitrate));
|
||||
|
||||
// Configure stop bits (00: 1 stop bit / 10: 2 stop bits.)
|
||||
CLEAR_BIT(UART_CR2, (1 << 12));
|
||||
CLEAR_BIT(UART_CR2, (1 << 13));
|
||||
|
||||
// Set the TE bit in USART_CR1 to send an idle frame as first transmission.
|
||||
SET_BIT(UART_CR1, UART_CR1_TX_ENABLE);
|
||||
SET_BIT(UART_CR1, UART_CR1_RX_ENABLE);
|
||||
|
||||
// Configure parity bits, disabled
|
||||
CLEAR_BIT(UART_CR1, UART_CR1_PARITY_ENABLED);
|
||||
CLEAR_BIT(UART_CR1, UART_CR1_PARITY_ODD);
|
||||
|
||||
ISB();
|
||||
DSB();
|
||||
|
||||
// Turn on UART. USART_CR1 Register, Bit 0.
|
||||
SET_BIT(UART_CR1, UART_CR1_UART_ENABLE);
|
||||
|
||||
if (READ_BIT(UART_CR1, UART_CR1_UART_ENABLE) == 1)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uart_write(const char c)
|
||||
{
|
||||
// USART transmit data register(TDR), bit 0-8 contains the data character to be transmitted.
|
||||
// The register mus be written only when TXE/TXFNF = 1;
|
||||
// TXE : Set by hardware when the content of the USART_TDR register has been transferred
|
||||
// into the shift register.
|
||||
// TXFNF : Set by hardware when TXFIFO is not full meaning that data can be written
|
||||
// in the USART_TDR.
|
||||
while (READ_BIT(UART_CR1, UART_CR1_TX_ENABLE) == 0)
|
||||
;
|
||||
while (READ_BIT(UART_ISR, UART_ISR_TX_FIFO_NOT_FULL) == 0)
|
||||
;
|
||||
|
||||
UART_TDR = c;
|
||||
}
|
||||
|
||||
void uart_print(const char *s)
|
||||
{
|
||||
int i = 0;
|
||||
while (s[i])
|
||||
{
|
||||
uart_write(s[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
uint8_t firmware_version = 0;
|
||||
|
||||
hal_init();
|
||||
|
||||
boot_led_on();
|
||||
usr_led_on();
|
||||
boot_led_off();
|
||||
// LED Indicator of Firmware Type A/B. A = ON, B = OFF
|
||||
if (FIRMWARE_A)
|
||||
ld3_write(LED_INIT);
|
||||
|
||||
// LED Indicator of successful UART initialization. SUCCESS = ON, FAIL = OFF
|
||||
if (uart_setup(9600) < 0)
|
||||
ld2_write(LED_OFF);
|
||||
else
|
||||
ld2_write(LED_INIT);
|
||||
|
||||
firmware_version = wolfBoot_current_firmware_version(); // The same as: wolfBoot_get_image_version(PART_BOOT);
|
||||
|
||||
// LED Indicator of version number lower than 1.
|
||||
if (firmware_version <= 0)
|
||||
ld1_write(LED_OFF);
|
||||
else
|
||||
ld1_write(LED_INIT);
|
||||
|
||||
uart_print(" \n\r");
|
||||
uart_print("| ------------------------------------------------------------------- |\n\r");
|
||||
uart_print("| STM32H753 User Application in BOOT partition started by wolfBoot |\n\r");
|
||||
uart_print("| ------------------------------------------------------------------- |\n\n\r");
|
||||
|
||||
if (FIRMWARE_A)
|
||||
uart_print("\tUSER APPLICATION: A\n\n\r");
|
||||
if (FIRMWARE_B)
|
||||
uart_print("\tUSER APPLICATION: B\n\n\r");
|
||||
|
||||
uart_print("\tFIRMWARE VERSION: ");
|
||||
if (firmware_version <= 9)
|
||||
{
|
||||
uart_write(firmware_version + '0');
|
||||
uart_print(" \n\n\r");
|
||||
}
|
||||
else
|
||||
uart_print("Version higher than 9, extend print method!\n\n\r");
|
||||
|
||||
if ((firmware_version > 1) && FIRMWARE_B)
|
||||
{
|
||||
uart_print("[INFO] Executing API function call wolfBoot_success()\n\r");
|
||||
wolfBoot_success();
|
||||
uart_print("[INFO] BOOT partition marked with: IMG_STATE_SUCCESS\n\r");
|
||||
}
|
||||
|
||||
char char_temp = READ_REG(UPDATE_CHARACTER_1);
|
||||
uart_print("[DATA] Content of 0x08060000 (1 byte): ");
|
||||
uart_write(char_temp);
|
||||
uart_print("\n\r");
|
||||
|
||||
if ((char_temp == 'W') && FIRMWARE_A)
|
||||
{
|
||||
uart_print("[INFO] Executing API function call wolfBoot_update_trigger()\n\r");
|
||||
wolfBoot_update_trigger();
|
||||
while(1)
|
||||
}
|
||||
else if (FIRMWARE_B)
|
||||
uart_print("[INFO] User application B is running and update cannot be triggered\n\r");
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
Loading…
Reference in New Issue