Merge pull request #4 from tomoveu/add-stm32f4-example

Add new STM32F4 and measured boot example
pull/6/head
Daniele Lacamera 2021-02-02 15:17:39 +01:00 committed by GitHub
commit b09c5e1291
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1925 additions and 1 deletions

View File

@ -0,0 +1,4 @@
tar rem:3333
file wolfboot.elf
foc c

View File

@ -0,0 +1,153 @@
# Inherit our settings for wolfBoot, TARGET, ARCH, etc.
-include measured.wolfboot.config
# Make sure environment variables do not corrupt the binary output for MacOS users
LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
APPSRC:=./src
WOLFBOOT_ROOT:=../wolfBoot
WOLFSSL_ROOT:=../wolfBoot/lib/wolfssl
WOLFTPM_ROOT:=../wolfBoot/lib/wolfTPM
ECCKEY:=$(WOLFBOOT_ROOT)/ecc256.der
DEBUG?=1
include $(WOLFBOOT_ROOT)/tools/config.mk
export WOLFBOOT_ROOT
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/keygen)","")
KEYGEN_TOOL:=$(WOLFBOOT_ROOT)/tools/keytools/keygen
else
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/keygen.exe)","")
KEYGEN_TOOL:=$(WOLFBOOT_ROOT)/tools/keytools/keygen.exe
else
KEYGEN_TOOL:=python3 $(WOLFBOOT_ROOT)/tools/keytools/keygen.py
endif
endif
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/sign)","")
SIGN_TOOL:=$(WOLFBOOT_ROOT)/tools/keytools/sign
else
ifneq ("$(wildcard $(WOLFBOOT_ROOT)/tools/keytools/sign.exe)","")
SIGN_TOOL:=$(WOLFBOOT_ROOT)/tools/keytools/sign.exe
else
SIGN_TOOL:=python3 $(WOLFBOOT_ROOT)/tools/keytools/sign.py
endif
endif
CFLAGS:=-g -ggdb -Wall -Wstack-usage=1024 -ffreestanding -Wno-unused -DPLATFORM_$(TARGET) \
-I$(WOLFBOOT_ROOT)/include -I$(WOLFBOOT_ROOT) -I$(WOLFSSL_ROOT) -I$(WOLFTPM_ROOT) \
-DWOLFBOOT_MEASURED_PCR_A -nostartfiles
CFLAGS+=-DWOLFBOOT_HASH_SHA256
CFLAGS+=-DWOLFSSL_USER_SETTINGS
CFLAGS+=-DWOLFTPM_USER_SETTINGS
APP_OBJS:= \
$(APPSRC)/app_$(TARGET).o \
$(APPSRC)/led.o \
$(APPSRC)/system.o \
$(APPSRC)/timer.o \
$(WOLFBOOT_ROOT)/hal/$(TARGET).o \
$(WOLFBOOT_ROOT)/src/libwolfboot.o \
$(WOLFBOOT_ROOT)/hal/spi/spi_drv_stm32.o \
$(APPSRC)/startup_arm.o
# Add objects for wolfCrypt support required by wolfTPM
APP_OBJS+= \
$(WOLFSSL_ROOT)/wolfcrypt/src/hmac.o \
$(WOLFSSL_ROOT)/wolfcrypt/src/aes.o \
$(WOLFSSL_ROOT)/wolfcrypt/src/wc_port.o
# Add objects for wolfTPM support
APP_OBJS+= \
$(WOLFTPM_ROOT)/src/tpm2.o \
$(WOLFTPM_ROOT)/src/tpm2_packet.o \
$(WOLFTPM_ROOT)/src/tpm2_tis.o \
$(WOLFTPM_ROOT)/src/tpm2_wrap.o \
$(WOLFTPM_ROOT)/src/tpm2_param_enc.o
# Inherit cross-compiler and similar settings from wolfBoot
include ../wolfBoot/arch.mk
ifneq ($(DEBUG),0)
CFLAGS+=-O0 -ggdb3
else
CFLAGS+=-Os
endif
vpath %.c $(dir $(WOLFSSL_ROOT)/src)
vpath %.c $(dir $(WOLFSSL_ROOT)/wolfcrypt/src)
vpath %.c $(dir $(WOLFBOOT_ROOT))/lib/wolfTPM/wolftpm)
ENTRY_POINT=`cat .entry-point-address`
LSCRIPT:=$(APPSRC)/target-app.ld
LSCRIPT_TEMPLATE:=$(APPSRC)/$(ARCH).ld
LDFLAGS:=$(CFLAGS) -T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map
wolfboot-example: wolfboot_align.bin image.bin
$(SIGN_TOOL) --ecc256 image.bin $(ECCKEY) 1
cat wolfboot-align.bin image_v1_signed.bin >factory.bin
wolfboot-align.bin:LSCRIPT:=$(WOLFBOOT_ROOT)/target.ld
wolfboot_align.bin:CFLAGS+=-DWOLFBOOT_HASH_SHA256
wolfboot_align.bin: wolfboot_target
make -C $(WOLFBOOT_ROOT) align
cp $(WOLFBOOT_ROOT)/wolfboot-align.bin .
cp $(WOLFBOOT_ROOT)/wolfboot.elf .
image.bin: wolfboot_target image.elf
$(OBJCOPY) -O binary image.elf $@
$(SIZE) image.elf
image.elf: wolfboot_target $(APP_OBJS) $(LSCRIPT)
@echo "\t[LD] $@"
$(Q)$(LD) $(LDFLAGS) $(APP_OBJS) -o $@
wolfboot_target: FORCE
cp -f measured.wolfboot.config $(WOLFBOOT_ROOT)/.config
make -C $(WOLFBOOT_ROOT) include/target.h
%.o:%.c
@echo "\t[CC-$(ARCH)] $@"
$(Q)$(CC) $(CFLAGS) -c -o $@ $^
%.o:%.S
@echo "\t[AS-$(ARCH)] $@"
$(Q)$(CC) $(CFLAGS) -c -o $@ $^
clean:
make -C $(WOLFBOOT_ROOT) clean
@rm -f *.bin *.elf $(OBJS) wolfboot.map *.bin *.hex src/*.o tags *.map
$(LSCRIPT): $(LSCRIPT_TEMPLATE) FORCE
@printf "%d" $(WOLFBOOT_PARTITION_BOOT_ADDRESS) > .wolfboot-offset
@printf "%d" $(WOLFBOOT_PARTITION_SIZE) > .partition-size
@printf "%d" $(IMAGE_HEADER_SIZE) > .header-size
@expr `cat .wolfboot-offset` + `cat .header-size` > .entry-point
@printf "0x%X" `cat .entry-point` > .entry-point
@expr `cat .partition-size` - `cat .header-size` > .app-size
@printf "0x%X" `cat .app-size` > .app-size
@ cat $(LSCRIPT_TEMPLATE) | \
sed -e "s/##WOLFBOOT_TEST_APP_SIZE##/`cat .app-size`/g" | \
sed -e "s/##WOLFBOOT_TEST_APP_ADDRESS##/`cat .entry-point`/g" \
> $(@)
@rm -f .app-size .entry-point .wolfboot-offset .partition-size .header-size
flash: FORCE
st-flash write factory.bin 0x08000000
erase: FORCE
st-flash erase
FORCE:
.PHONY: FORCE clean

View File

@ -0,0 +1,196 @@
# STM32F407-Discovery-Measured-Boot
Measured Boot example running on STM32F407-Discovery board.
This project is meant to demonstrate Measured Boot using the [wolfBoot secure bootloader](https://github.com/wolfssl/wolfBoot), powered by wolfSSL.
The bootloader expects a Trusted Platform Module(TPM) to be available in hardware.
## Components
- Bootloader: [wolfBoot](https://github.com/wolfssl/wolfBoot) by wolfSSL
- Application: Test app printing the extended PCR value that wolfBoot created
- TPM2.0 stack: [wolfTPM](https://github.com/wolfssl/wolfTPM) by wolfSSL
## Motivation
Measured Boot provides the application with a trace of the boot process. This trace(log) is resistant to spoofing and tampering.
This is achieved by using a TPM which has unique Platform Configuration Registers(PCR) to store hash measurements.
The application(runtime) then can use this tamper-proof log to determine whether the system is in a good known state (trustworthy) or if the system is infected with malware.
After a measurement is stored into one of the TPM's PCRs, the user could perform local attestation using a TPM2.0 Quote and report the log to a remote sever for evaluation:
- The remote server can compare the log to golden value(s) and alert system owners in case of mismatch.
- The remote server can directly take action with the device.
The following diagram is a big picture overview of the different guarantee Secure and Measured Boot provide:
![Measured boot](measured_boot_diagram.png)
## Details
Secure Boot is a way for the system owner to guarantee that the device started with a geniune software. However, this information is not available to the system later on. Therefore, the application runtime must assume any and all software that was run before it is geniune. Measured Boot eliminates the guessing element and provides a way for the application to know the state of the system before it took control.
Measured Boot could evaluate a single component like firmware or application image, or can evaluate multiple components like system settings and user configuration. Additionally, the golden value could be stored within the system for the application to self-evaluate its state without the need of a remote server.
This example performs measured boot, stores the measurement of the firmware image into PCR16 and then boots into a test application. The test application prints the result of the measured boot(the value of the PCR).
This example could be extended to support multiple measurements.
## Prerequisites
- `STM32F4-Discovery` board (STM32F407)
with
- `LetsTrust TPM2.0` module or `Infineon SLB9670` module
Hardware connections must be made between the TPM2.0 module and the STM32F4 board. Here is a wiring table for the Infineon module:
| STM32F4 | Pin function | TPM2.0 module |
|----------|:-------------:|--------------:|
| PE0 | SPI CS | Pin 26 |
| PB3 | SPI CLK | Pin 23 |
| PB4 | SPI MISO | Pin 21 |
| PB5 | SPI MOSI | Pin 19 |
| 3V | +3V | Pin 1 |
| GND | Ground | Pin 6 |
UART1 on the STM32F4 is used by default. The default baud rate is 115200.
The UART Pinout can be found below:
| STM32F4 | Pin function |
|----------|:------------:|
| PB6 | UART TX |
| PB7 | UART RX |
| GND | Ground |
Note: The ST-Link USB UDC is UART 2 on PA3 (TX) / PA2 (RX). This can be changed in app_stm32f4.c using APP_UART.
Note: Make sure the Ground connection between your USB-UART converter is connected to the STM32F4 board, otherwise UART levels will float and communication will be corrupted.
## Compiling
Before compiling make sure the git submodules are initialized and updated correctly. Use the following commands to make sure:
`wolfboot-examples/$ git submodule --init --update`
`wolfboot-examples/$ cd wolfBoot`
`wolfboot-examples/wolfBoot$ git submodule --init --update`
Enter the project folder for this example:
`wolfboot-examples/wolfBoot$ cd ../test-app-STM32F4-measured-boot`
Makefile in the project folder takes care of compiling wolfTPM, wolfBoot, compiling the test application and signing the firmware:
`wolfboot-examples/wolfBoot$ make`
The following files will be available in the project folder after successful build:
- factory.bin - Test-app and wolfboot combined, ready for flashing
- wolfboot.elf - WolfBoot with Debug information, useful for gdb
- image.bin - Test-app without signature
- image.elf - Test-app with Debug information, useful for gdb
- image_v1_signed.bin - Test-app with signature
- image.map - Listing of the Test-app
## Usage
After successful compilation, the `flash` target can be used to flash the `factory.bin` image to the STM32F4-Discovery board using ST-Link2
`make flash`
Typical output:
```
test-app-STM32F4-measured-boot % make flash
st-flash write factory.bin 0x08000000
st-flash 1.6.1
2021-01-27T19:24:01 INFO common.c: F4xx: 192 KiB SRAM, 1024 KiB flash in at least 16 KiB pages.
file factory.bin md5 checksum: 7cc2a98a3e5366ecc54bbb79a646286, stlink checksum: 0x01c745fb
2021-01-27T19:24:01 INFO common.c: Attempting to write 143576 (0x230d8) bytes to stm32 address: 134217728 (0x8000000)
EraseFlash - Sector:0x0 Size:0x4000 2021-01-27T19:24:01 INFO common.c: Flash page at addr: 0x08000000 erased
EraseFlash - Sector:0x1 Size:0x4000 2021-01-27T19:24:02 INFO common.c: Flash page at addr: 0x08004000 erased
EraseFlash - Sector:0x2 Size:0x4000 2021-01-27T19:24:02 INFO common.c: Flash page at addr: 0x08008000 erased
EraseFlash - Sector:0x3 Size:0x4000 2021-01-27T19:24:02 INFO common.c: Flash page at addr: 0x0800c000 erased
EraseFlash - Sector:0x4 Size:0x10000 2021-01-27T19:24:03 INFO common.c: Flash page at addr: 0x08010000 erased
EraseFlash - Sector:0x5 Size:0x20000 2021-01-27T19:24:05 INFO common.c: Flash page at addr: 0x08020000 erased
2021-01-27T19:24:05 INFO common.c: Finished erasing 6 pages of 131072 (0x20000) bytes
2021-01-27T19:24:05 INFO common.c: Starting Flash write for F2/F4/L4
2021-01-27T19:24:05 INFO flash_loader.c: Successfully loaded flash loader in sram
enabling 32-bit flash writes
size: 32768
size: 32768
size: 32768
size: 32768
size: 12504
2021-01-27T19:24:07 INFO common.c: Starting verification of write complete
2021-01-27T19:24:08 INFO common.c: Flash written and verified! jolly good!
```
To debug start first start GDB server (see GDB Server section below).
1. Launch arm-none-eabi-gdb and perform the following steps for debugging
2. Load symbol file for test application. Wolfboot.elf is already loaded thanks to .gdbinit supplied with the project.
`add-symbol-file image.elf`
3. Set breakpoints at "main", two breakpoints should be created, one for main() in wolfBoot and one for main() in the test app.
`b main`
4. Set breakpoints at "measure_boot", "read_measured_boot"
`b measure_boot`
`b read_measured_boot`
5. Start execution by invoking "continue" to gdb
`c`
6. Expected output on the connected UART terminal (see UART pinout in `Prerequisites`)
```
App started
Measured Boot PCR is = 0x01020304050607080910
```
This value is the one created by wolfBoot during start of the device. This value is the result of PCR Extend operation and depends on the firmware image loaded. Using the same firmware image should produce the same PCR measurement. By using different firmware images a change in the PCR value can be obsereved, simulating tampering.
For more information about measured boot contact us at facts@wolfssl.com
## GDB Server
The supplied openocd.config is prepared for STM32F407-Discovery revision D that uses newer ST-LINK2 variant.
If you are using STM32F407-Discovery revision B, then modify the very first line in the config file:
`source [find interface/stlink-v2-1.cfg]`
with
`source [find interface/stlink-v2.cfg]`
Start new openocd session using
`openocd -f openocd.config`
Start new gdb session as described in `Usage`.
Note: You can also use the ST-Util for GDB server using: `st-util -p 3333`.
Please contact us at support@wolfssl.com for any questions about using this example.
## Copyright notice
This example is Copyright (c) 2020 wolfSSL Inc., and distributed under the term of GNU GPL2.
wolfBoot, wolfSSL (formerly known as CyaSSL) and wolfCrypt are Copyright (c) 2006-2018 wolfSSL Inc., and licensed for use under GPLv2.
wolfTPM is Copyright (c) 2018-2020 wolfSSL Inc., and licensed for use under GPLv2.
See the documentation within each component subdirectory for more information about using and distributing this software.

View File

@ -0,0 +1,26 @@
ARCH?=ARM
TARGET?=stm32f4
SIGN?=ECC256
HASH?=SHA256
DEBUG?=1
VTOR?=1
CORTEX_M0?=0
NO_ASM?=0
EXT_FLASH?=0
SPI_FLASH?=0
ALLOW_DOWNGRADE?=0
NVM_FLASH_WRITEONCE?=0
WOLFBOOT_VERSION?=0
V?=0
SPMATH?=1
RAM_CODE?=0
DUALBANK_SWAP?=0
IMAGE_HEADER_SIZE?=256
WOLFBOOT_PARTITION_SIZE?=0x20000
WOLFBOOT_SECTOR_SIZE?=0x20000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x40000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x60000
WOLFTPM?=1
MEASURED_BOOT?=1
MEASURED_PCR_A?=16

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -0,0 +1,8 @@
source [find interface/stlink-v2-1.cfg]
source [find target/stm32f4x.cfg]
$_TARGETNAME configure -event reset-init {
mmw 0xe0042004 0x7 0x0
}
init
reset
halt

View File

@ -0,0 +1,45 @@
MEMORY
{
FLASH (rx) : ORIGIN = ##WOLFBOOT_TEST_APP_ADDRESS##, LENGTH = ##WOLFBOOT_TEST_APP_SIZE##
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K /* Run in lowmem */
}
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);
KEEP(*(.ramcode))
. = 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));

View File

@ -0,0 +1,444 @@
/* app_stm32f4.c
*
* Test bare-metal application for reporting measured boot value over UART
*
* Copyright (C) 2021 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 <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "system.h"
#include "timer.h"
#include "led.h"
#include "hal.h"
#include "wolfboot/wolfboot.h"
#include "spi_flash.h"
#include "spi_drv.h"
#include "spi_tpm.h"
#include "wolftpm/tpm2.h"
#include "wolftpm/tpm2_wrap.h"
static WOLFTPM2_DEV wolftpm_dev;
#define UART1 (0x40011000)
#define UART2 (0x40014400)
#ifndef APP_UART
#define APP_UART UART1
#endif
#define UART_SR (*(volatile uint32_t *)(APP_UART))
#define UART_DR (*(volatile uint32_t *)(APP_UART + 0x04))
#define UART_BRR (*(volatile uint32_t *)(APP_UART + 0x08))
#define UART_CR1 (*(volatile uint32_t *)(APP_UART + 0x0c))
#define UART_CR2 (*(volatile uint32_t *)(APP_UART + 0x10))
#define UART_CR1_UART_ENABLE (1 << 13)
#define UART_CR1_SYMBOL_LEN (1 << 12)
#define UART_CR1_PARITY_ENABLED (1 << 10)
#define UART_CR1_PARITY_ODD (1 << 9)
#define UART_CR1_TX_ENABLE (1 << 3)
#define UART_CR1_RX_ENABLE (1 << 2)
#define UART_CR2_STOPBITS (3 << 12)
#define UART_SR_TX_EMPTY (1 << 7)
#define UART_SR_RX_NOTEMPTY (1 << 5)
#define CLOCK_SPEED (168000000)
#define APB2_CLOCK_ER (*(volatile uint32_t *)(0x40023844))
#define UART1_APB2_CLOCK_ER (1 << 4)
#define UART2_APB2_CLOCK_ER (1 << 17)
#define AHB1_CLOCK_ER (*(volatile uint32_t *)(0x40023830))
#define GPIOA_AHB1_CLOCK_ER (1 << 0)
#define GPIOB_AHB1_CLOCK_ER (1 << 1)
#ifndef GPIOA_BASE
#define GPIOA_BASE 0x48000000
#endif
#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))
#ifndef GPIOB_BASE
#define GPIOB_BASE 0x48000400
#endif
#define GPIOB_MODE (*(volatile uint32_t *)(GPIOB_BASE + 0x00))
#define GPIOB_AFL (*(volatile uint32_t *)(GPIOB_BASE + 0x20))
#define GPIOB_AFH (*(volatile uint32_t *)(GPIOB_BASE + 0x24))
#define UART_PIN_AF 7
#define UART1_RX_PIN 7 /* PB7 */
#define UART1_TX_PIN 6 /* PB6 */
#define UART2_RX_PIN 3 /* PA3 */
#define UART2_TX_PIN 2 /* PA2 */
#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 const char startString[]="App started";
static const char TPMfailString[]="tpm_init failed";
static const char TPMpcrString[]="Measured Boot PCR is = ";
static const char HEX [16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
volatile uint32_t time_elapsed = 0; /* Used for PWM on LED */
void uart_write(const char c)
{
uint32_t reg;
do {
reg = UART_SR;
} while ((reg & UART_SR_TX_EMPTY) == 0);
UART_DR = c;
}
void uart_write_hex(const char c)
{
uart_write(HEX[(c >> 4) & 0x0F]);
uart_write(HEX[c & 0x0F]);
}
static void uart_pins_setup(void)
{
uint32_t reg;
#if APP_UART == UART1
AHB1_CLOCK_ER |= GPIOB_AHB1_CLOCK_ER;
/* Set mode = AF */
reg = GPIOB_MODE & ~ (0x03 << (UART1_RX_PIN * 2));
GPIOB_MODE = reg | (2 << (UART1_RX_PIN * 2));
reg = GPIOB_MODE & ~ (0x03 << (UART1_TX_PIN * 2));
GPIOB_MODE = reg | (2 << (UART1_TX_PIN * 2));
/* Alternate function: use low pins (6 and 7) */
reg = GPIOB_AFL & ~(0xf << ((UART1_TX_PIN) * 4));
GPIOB_AFL = reg | (UART_PIN_AF << ((UART1_TX_PIN) * 4));
reg = GPIOB_AFL & ~(0xf << ((UART1_RX_PIN) * 4));
GPIOB_AFL = reg | (UART_PIN_AF << ((UART1_RX_PIN) * 4));
#elif APP_UART == UART2
AHB1_CLOCK_ER |= GPIOA_AHB1_CLOCK_ER;
/* Set mode = AF */
reg = GPIOA_MODE & ~ (0x03 << (UART2_RX_PIN * 2));
GPIOA_MODE = reg | (2 << (UART2_RX_PIN * 2));
reg = GPIOA_MODE & ~ (0x03 << (UART2_TX_PIN * 2));
GPIOA_MODE = reg | (2 << (UART2_TX_PIN * 2));
/* Alternate function: use low pins (6 and 7) */
reg = GPIOA_AFL & ~(0xf << ((UART2_TX_PIN) * 4));
GPIOA_AFL = reg | (UART_PIN_AF << ((UART2_TX_PIN) * 4));
reg = GPIOA_AFL & ~(0xf << ((UART2_RX_PIN) * 4));
GPIOA_AFL = reg | (UART_PIN_AF << ((UART2_RX_PIN) * 4));
#else
#error Please configure the UART pins
#endif
}
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 */
#if APP_UART == UART1
APB2_CLOCK_ER |= UART1_APB2_CLOCK_ER;
#elif APP_UART == UART2
APB2_CLOCK_ER |= UART2_APB2_CLOCK_ER;
#endif
/* Configure for TX + RX */
UART_CR1 |= (UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE);
/* Configure clock */
UART_BRR = CLOCK_SPEED / bitrate;
/* Configure data bits */
if (data == 8)
UART_CR1 &= ~UART_CR1_SYMBOL_LEN;
else
UART_CR1 |= UART_CR1_SYMBOL_LEN;
/* Configure parity */
switch (parity) {
case 'O':
UART_CR1 |= UART_CR1_PARITY_ODD;
/* fall through to enable parity */
case 'E':
UART_CR1 |= UART_CR1_PARITY_ENABLED;
break;
default:
UART_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD);
}
/* Set stop bits */
reg = UART_CR2 & ~UART_CR2_STOPBITS;
if (stop > 1)
UART_CR2 = reg & (2 << 12);
else
UART_CR2 = reg;
/* Turn on uart */
UART_CR1 |= UART_CR1_UART_ENABLE;
return 0;
}
char uart_read(void)
{
char c;
volatile uint32_t reg;
do {
reg = UART_SR;
} while ((reg & UART_SR_RX_NOTEMPTY) == 0);
c = (char)(UART_DR & 0xff);
return c;
}
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;
}
static int app_tpm2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
word16 xferSz, void* userCtx)
{
(void)userCtx;
(void)ctx;
word16 i;
spi_cs_on(SPI_CS_TPM);
XMEMSET(rxBuf, 0, xferSz);
for (i = 0; i < xferSz; i++)
{
spi_write(txBuf[i]);
rxBuf[i] = spi_read();
}
spi_cs_off(SPI_CS_TPM);
/*
printf("\r\nSPI TX: ");
printbin(txBuf, xferSz);
printf("SPI RX: ");
printbin(rxBuf, xferSz);
printf("\r\n");
*/
return 0;
}
static int app_tpm2_init(void)
{
int rc;
WOLFTPM2_CAPS caps;
spi_init(0,0);
/* Init the TPM2 device */
rc = wolfTPM2_Init(&wolftpm_dev, app_tpm2_IoCb, NULL);
if (rc != 0) {
return rc;
}
/* Get device capabilities + options */
rc = wolfTPM2_GetCapabilities(&wolftpm_dev, &caps);
if (rc != 0) {
return rc;
}
return 0;
}
/* Reads out the TPM measurement created by wolfBoot */
static int read_measured_boot(uint8_t* digest)
{
int rc;
PCR_Read_In pcrReadCmd;
PCR_Read_Out pcrReadResp;
XMEMSET(&pcrReadCmd, 0, sizeof(pcrReadCmd));
TPM2_SetupPCRSel(&pcrReadCmd.pcrSelectionIn, TPM_ALG_SHA256, WOLFBOOT_MEASURED_PCR_A);
rc = TPM2_PCR_Read(&pcrReadCmd, &pcrReadResp);
if (rc == TPM_RC_SUCCESS) {
XMEMCPY(digest, pcrReadResp.pcrValues.digests[0].buffer,
pcrReadResp.pcrValues.digests[0].size);
rc = 0;
}
return rc;
}
void main(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;
uint8_t boot_measurement[WOLFBOOT_SHA_DIGEST_SIZE];
int i;
memset(page, 0xFF, PAGESIZE);
boot_led_on();
flash_set_waitstates();
clock_config();
led_pwm_setup();
pwm_init(CPU_FREQ, 0);
/* Dim the led by altering the PWM duty-cicle
* in isr_tim2 (timer.c)
*
* Every 50ms, the duty cycle of the PWM connected
* to the blue led increases/decreases making a pulse
* effect.
*/
timer_init(CPU_FREQ, 1, 50);
uart_setup(115200, 8, 'N', 1);
memset(page, 0xFF, PAGESIZE);
asm volatile ("cpsie i");
while(time_elapsed == 0)
WFI();
hal_flash_unlock();
version = wolfBoot_current_firmware_version();
if ((version & 0x01) == 0)
wolfBoot_success();
#ifdef EXT_ENCRYPTED
wolfBoot_set_encrypt_key("0123456789abcdef0123456789abcdef", 32);
#endif
for(i=0; i < sizeof(startString); i++) {
uart_write(startString[i++]);
}
uart_write(START);
for (i = 3; i >= 0; i--) {
uart_write(v_array[i]);
}
if(app_tpm2_init() != 0) {
for(i=0; i < sizeof(TPMfailString); i++) {
uart_write(TPMfailString[i]);
}
}
if(read_measured_boot(boot_measurement) == 0) {
for(i = 0; i < sizeof(TPMpcrString); i++) {
uart_write(TPMpcrString[i]);
}
/* Print the digest of the measurement */
for(i=0; i < sizeof(boot_measurement); i++) {
uart_write_hex(boot_measurement[i]);
}
/* For better view on the UART terminal */
uart_write('\n');
uart_write('\r');
}
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 > WOLFBOOT_PARTITION_SIZE - 8) {
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;
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 = (WOLFBOOT_PARTITION_UPDATE_ADDRESS + recv_seq + psize) - page_idx;
if ((dst % WOLFBOOT_SECTOR_SIZE) == 0) {
hal_flash_erase(dst, WOLFBOOT_SECTOR_SIZE);
}
hal_flash_write(dst, page, PAGESIZE);
memset(page, 0xFF, PAGESIZE);
}
next_seq += psize;
}
ack(next_seq);
if (next_seq >= tot_len) {
/* Update complete */
spi_flash_probe();
wolfBoot_update_trigger();
spi_release();
hal_flash_lock();
break;
}
}
/* Wait for reboot */
while(1)
;
}

View File

@ -0,0 +1,180 @@
/* led.c
*
* Test bare-metal blinking led application
*
* Copyright (C) 2020 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 "wolfboot/wolfboot.h"
#ifdef PLATFORM_stm32f4
#define AHB1_CLOCK_ER (*(volatile uint32_t *)(0x40023830))
#define GPIOD_AHB1_CLOCK_ER (1 << 3)
#define GPIOD_BASE 0x40020c00
#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))
#define LED_PIN (15)
#define LED_BOOT_PIN (14)
#define GPIO_OSPEED_100MHZ (0x03)
void led_pwm_setup(void)
{
uint32_t reg;
AHB1_CLOCK_ER |= GPIOD_AHB1_CLOCK_ER;
reg = GPIOD_MODE & ~ (0x03 << (LED_PIN * 2));
GPIOD_MODE = reg | (2 << (LED_PIN * 2));
reg = GPIOD_OSPD & ~(0x03 << (LED_PIN * 2));
GPIOD_OSPD = reg | (0x03 << (LED_PIN * 2));
reg = GPIOD_PUPD & ~(0x03 << (LED_PIN * 2));
GPIOD_PUPD = reg | (0x02 << (LED_PIN * 2));
/* Alternate function: use high pin */
reg = GPIOD_AFH & ~(0xf << ((LED_PIN - 8) * 4));
GPIOD_AFH = reg | (0x2 << ((LED_PIN - 8) * 4));
}
void boot_led_on(void)
{
uint32_t reg;
uint32_t pin = LED_BOOT_PIN;// - 2 * (wolfBoot_current_firmware_version() & 0x01);
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);
}
#endif /* PLATFORM_stm32f4 */
#ifdef PLATFORM_stm32l0
#define LED_BOOT_PIN (5)
#define RCC_IOPENR (*(volatile uint32_t *)(0x4002102C))
#define IOPAEN (1 << 0)
#define GPIOA_BASE 0x50000000
#define GPIOA_MODE (*(volatile uint32_t *)(GPIOA_BASE + 0x00))
#define GPIOA_OTYPE (*(volatile uint32_t *)(GPIOA_BASE + 0x04))
#define GPIOA_OSPD (*(volatile uint32_t *)(GPIOA_BASE + 0x08))
#define GPIOA_PUPD (*(volatile uint32_t *)(GPIOA_BASE + 0x0c))
#define GPIOA_ODR (*(volatile uint32_t *)(GPIOA_BASE + 0x14))
#define GPIOA_BSRR (*(volatile uint32_t *)(GPIOA_BASE + 0x18))
#define GPIOA_AFL (*(volatile uint32_t *)(GPIOA_BASE + 0x20))
#define GPIOA_AFH (*(volatile uint32_t *)(GPIOA_BASE + 0x24))
void boot_led_on(void)
{
uint32_t reg;
uint32_t pin = LED_BOOT_PIN;
RCC_IOPENR |= IOPAEN;
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);
}
#endif /* PLATFORM_stm32l0 */
#ifdef PLATFORM_stm32g0
#include <stdint.h>
#include "wolfboot/wolfboot.h"
/*GPIOA5*/
#define RCC_IOPENR (*(volatile uint32_t *)(0x40021034)) // 40021034
#define RCC_IOPENR_GPIOAEN (1 << 0)
#define GPIOA_BASE 0x50000000
#define GPIOA_MODE (*(volatile uint32_t *)(GPIOA_BASE + 0x00))
#define GPIOA_OTYPE (*(volatile uint32_t *)(GPIOA_BASE + 0x04))
#define GPIOA_OSPD (*(volatile uint32_t *)(GPIOA_BASE + 0x08))
#define GPIOA_PUPD (*(volatile uint32_t *)(GPIOA_BASE + 0x0c))
#define GPIOA_ODR (*(volatile uint32_t *)(GPIOA_BASE + 0x14))
#define GPIOA_BSRR (*(volatile uint32_t *)(GPIOA_BASE + 0x18))
#define GPIOA_AFL (*(volatile uint32_t *)(GPIOA_BASE + 0x20))
#define GPIOA_AFH (*(volatile uint32_t *)(GPIOA_BASE + 0x24))
#define LED_PIN (5)
#define LED_BOOT_PIN (5)
#define GPIO_OSPEED_100MHZ (0x03)
void boot_led_on(void)
{
uint32_t reg;
uint32_t pin = LED_BOOT_PIN;
RCC_IOPENR |= RCC_IOPENR_GPIOAEN;
reg = GPIOA_MODE & ~(0x03 << (pin * 2));
GPIOA_MODE = reg | (1 << (pin * 2)); // general purpose output mode
reg = GPIOA_PUPD & ~(0x03 << (pin * 2));
GPIOA_PUPD = reg | (1 << (pin * 2)); // pull-up
GPIOA_BSRR |= (1 << pin); // set pin
}
#endif /** PLATFORM_stm32g0 **/
#ifdef PLATFORM_stm32wb
#define LED_BOOT_PIN (0)
#define RCC_AHB2_CLOCK_ER (*(volatile uint32_t *)(0x5800004C))
#define GPIOB_AHB2_CLOCK_ER (1 << 1)
#define GPIOB_BASE 0x48000400
#define GPIOB_MODE (*(volatile uint32_t *)(GPIOB_BASE + 0x00))
#define GPIOB_OTYPE (*(volatile uint32_t *)(GPIOB_BASE + 0x04))
#define GPIOB_OSPD (*(volatile uint32_t *)(GPIOB_BASE + 0x08))
#define GPIOB_PUPD (*(volatile uint32_t *)(GPIOB_BASE + 0x0c))
#define GPIOB_ODR (*(volatile uint32_t *)(GPIOB_BASE + 0x14))
#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))
void boot_led_on(void)
{
uint32_t reg;
uint32_t pin = LED_BOOT_PIN;
RCC_AHB2_CLOCK_ER |= GPIOB_AHB2_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);
}
void boot_led_off(void)
{
uint32_t reg;
uint32_t pin = LED_BOOT_PIN;
GPIOB_BSRR |= (1 << (pin + 16));
}
#endif /* PLATFORM_stm32wb */

View File

@ -0,0 +1,35 @@
/* led.h
*
* Test bare-metal blinking led application
*
* Copyright (C) 2020 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
*/
#ifndef GPIO_H_INCLUDED
#define GPIO_H_INCLUDED
int led_setup(void);
void led_on(void);
void led_off(void);
void led_toggle(void);
void led_pwm_setup(void);
void boot_led_on(void);
void boot_led_off(void);
#endif /* !GPIO_H_INCLUDED */

View File

@ -0,0 +1,36 @@
/* tpm_spi.h
*
* 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
*/
/** SPI settings for TPM2.0 module **/
#undef SPI_GPIO
#define SPI_GPIO GPIOB_BASE
#undef SPI_CS_GPIO
#define SPI_CS_GPIO GPIOE_BASE
#undef SPI_CS_TPM
#define SPI_CS_TPM 0 /* TPM CS connected to GPIOE0 */
#undef SPI1_CLOCK_PIN
#define SPI1_CLOCK_PIN 3 /* SPI_SCK: PB3 */
#undef SPI1_MISO_PIN
#define SPI1_MISO_PIN 4 /* SPI_MISO PB4 */
#undef SPI1_MOSI_PIN
#define SPI1_MOSI_PIN 5 /* SPI_MOSI PB5 */

View File

@ -0,0 +1,337 @@
/* startup_arm.c
*
* Test bare-metal blinking led application
*
* Copyright (C) 2020 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
*/
extern unsigned int _stored_data;
extern unsigned int _start_data;
extern unsigned int _end_data;
extern unsigned int _start_bss;
extern unsigned int _end_bss;
extern unsigned int _end_stack;
extern unsigned int _start_heap;
static int zeroed_variable_in_bss;
static int initialized_variable_in_data = 42;
extern void isr_tim2(void);
#define STACK_PAINTING
static volatile unsigned int avail_mem = 0;
static unsigned int sp;
extern void main(void);
void isr_reset(void) {
register unsigned int *src, *dst;
src = (unsigned int *) &_stored_data;
dst = (unsigned int *) &_start_data;
while (dst < (unsigned int *)&_end_data) {
*dst = *src;
dst++;
src++;
}
dst = &_start_bss;
while (dst < (unsigned int *)&_end_bss) {
*dst = 0U;
dst++;
}
avail_mem = &_end_stack - &_start_heap;
#ifdef STACK_PAINTING
{
asm volatile("mrs %0, msp" : "=r"(sp));
dst = ((unsigned int *)(&_end_stack)) - (8192 / sizeof(unsigned int)); ;
while ((unsigned int)dst < sp) {
*dst = 0xDEADC0DE;
dst++;
}
}
#endif
main();
}
void isr_fault(void)
{
/* Panic. */
while(1) ;;
}
void isr_memfault(void)
{
/* Panic. */
while(1) ;;
}
void isr_busfault(void)
{
/* Panic. */
while(1) ;;
}
void isr_usagefault(void)
{
/* Panic. */
while(1) ;;
}
void isr_empty(void)
{
}
__attribute__ ((section(".isr_vector")))
void (* const IV[])(void) =
{
(void (*)(void))(&_end_stack),
isr_reset, // Reset
isr_fault, // NMI
isr_fault, // HardFault
isr_memfault, // MemFault
isr_busfault, // BusFault
isr_usagefault, // UsageFault
0, // SecureFault
0, // reserved
0, // reserved
0, // reserved
isr_empty, // SVC
isr_empty, // DebugMonitor
0, // reserved
isr_empty, // PendSV
isr_empty, // SysTick
/* Device specific IRQs for LM3S */
#ifdef LM3S
isr_empty, // GPIO Port A
isr_empty, // GPIO Port B
isr_empty, // GPIO Port C
isr_empty, // GPIO Port D
isr_empty, // GPIO Port E
isr_empty, // UART0 Rx and Tx
isr_empty, // UART1 Rx and Tx
isr_empty, // SSI0 Rx and Tx
isr_empty, // I2C0 Master and Slave
isr_empty, // PWM Fault
isr_empty, // PWM Generator 0
isr_empty, // PWM Generator 1
isr_empty, // PWM Generator 2
isr_empty, // Quadrature Encoder 0
isr_empty, // ADC Sequence 0
isr_empty, // ADC Sequence 1
isr_empty, // ADC Sequence 2
isr_empty, // ADC Sequence 3
isr_empty, // Watchdog timer
isr_empty, // Timer 0 subtimer A
isr_empty, // Timer 0 subtimer B
isr_empty, // Timer 1 subtimer A
isr_empty, // Timer 1 subtimer B
isr_empty, // Timer 2 subtimer A
isr_empty, // Timer 3 subtimer B
isr_empty, // Analog Comparator 0
isr_empty, // Analog Comparator 1
isr_empty, // Analog Comparator 2
isr_empty, // System Control (PLL, OSC, BO)
isr_empty, // FLASH Control
isr_empty, // GPIO Port F
isr_empty, // GPIO Port G
isr_empty, // GPIO Port H
isr_empty, // UART2 Rx and Tx
isr_empty, // SSI1 Rx and Tx
isr_empty, // Timer 3 subtimer A
isr_empty, // Timer 3 subtimer B
isr_empty, // I2C1 Master and Slave
isr_empty, // Quadrature Encoder 1
isr_empty, // CAN0
isr_empty, // CAN1
isr_empty, // CAN2
isr_empty, // Ethernet
isr_empty, // Hibernate
#elif PLATFORM_stm32l5
isr_empty, // WWDG_IRQHandler
isr_empty, // PVD_PVM_IRQHandler
isr_empty, // RTC_IRQHandler
isr_empty, // RTC_S_IRQHandler
isr_empty, // TAMP_IRQHandler
isr_empty, // TAMP_S_IRQHandler
isr_empty, // FLASH_IRQHandler
isr_empty, // FLASH_S_IRQHandler
isr_empty, // GTZC_IRQHandler
isr_empty, // RCC_IRQHandler
isr_empty, // RCC_S_IRQHandler
isr_empty, // EXTI0_IRQHandler
isr_empty, // EXTI1_IRQHandler
isr_empty, // EXTI2_IRQHandler
isr_empty, // EXTI3_IRQHandler
isr_empty, // EXTI4_IRQHandler
isr_empty, // EXTI5_IRQHandler
isr_empty, // EXTI6_IRQHandler
isr_empty, // EXTI7_IRQHandler
isr_empty, // EXTI8_IRQHandler
isr_empty, // EXTI9_IRQHandler
isr_empty, // EXTI10_IRQHandler
isr_empty, // EXTI11_IRQHandler
isr_empty, // EXTI12_IRQHandler
isr_empty, // EXTI13_IRQHandler
isr_empty, // EXTI14_IRQHandler
isr_empty, // EXTI15_IRQHandler
isr_empty, // DMAMUX1_IRQHandler
isr_empty, // DMAMUX1_S_IRQHandler
isr_empty, // DMA1_Channel1_IRQHandler
isr_empty, // DMA1_Channel2_IRQHandler
isr_empty, // DMA1_Channel3_IRQHandler
isr_empty, // DMA1_Channel4_IRQHandler
isr_empty, // DMA1_Channel5_IRQHandler
isr_empty, // DMA1_Channel6_IRQHandler
isr_empty, // DMA1_Channel7_IRQHandler
isr_empty, // DMA1_Channel8_IRQHandler
isr_empty, // ADC1_2_IRQHandler
isr_empty, // DAC_IRQHandler
isr_empty, // FDCAN1_IT0_IRQHandler
isr_empty, // FDCAN1_IT1_IRQHandler
isr_empty, // TIM1_BRK_IRQHandler
isr_empty, // TIM1_UP_IRQHandler
isr_empty, // TIM1_TRG_COM_IRQHandler
isr_empty, // TIM1_CC_IRQHandler
isr_empty, // TIM2_IRQHandler
isr_empty, // TIM3_IRQHandler
isr_empty, // TIM4_IRQHandler
isr_empty, // TIM5_IRQHandler
isr_empty, // TIM6_IRQHandler
isr_empty, // TIM7_IRQHandler
isr_empty, // TIM8_BRK_IRQHandler
isr_empty, // TIM8_UP_IRQHandler
isr_empty, // TIM8_TRG_COM_IRQHandler
isr_empty, // TIM8_CC_IRQHandler
isr_empty, // I2C1_EV_IRQHandler
isr_empty, // I2C1_ER_IRQHandler
isr_empty, // I2C2_EV_IRQHandler
isr_empty, // I2C2_ER_IRQHandler
isr_empty, // SPI1_IRQHandler
isr_empty, // SPI2_IRQHandler
isr_empty, // USART1_IRQHandler
isr_empty, // USART2_IRQHandler
isr_empty, // USART3_IRQHandler
isr_empty, // UART4_IRQHandler
isr_empty, // UART5_IRQHandler
isr_empty, // LPUART1_IRQHandler
isr_empty, // LPTIM1_IRQHandler
isr_empty, // LPTIM2_IRQHandler
isr_empty, // TIM15_IRQHandler
isr_empty, // TIM16_IRQHandler
isr_empty, // TIM17_IRQHandler
isr_empty, // COMP_IRQHandler
isr_empty, // USB_FS_IRQHandler
isr_empty, // CRS_IRQHandler
isr_empty, // FMC_IRQHandler
isr_empty, // OCTOSPI1_IRQHandler
isr_empty, // 0
isr_empty, // SDMMC1_IRQHandler
isr_empty, // 0
isr_empty, // DMA2_Channel1_IRQHandler
isr_empty, // DMA2_Channel2_IRQHandler
isr_empty, // DMA2_Channel3_IRQHandler
isr_empty, // DMA2_Channel4_IRQHandler
isr_empty, // DMA2_Channel5_IRQHandler
isr_empty, // DMA2_Channel6_IRQHandler
isr_empty, // DMA2_Channel7_IRQHandler
isr_empty, // DMA2_Channel8_IRQHandler
isr_empty, // I2C3_EV_IRQHandler
isr_empty, // I2C3_ER_IRQHandler
isr_empty, // SAI1_IRQHandler
isr_empty, // SAI2_IRQHandler
isr_empty, // TSC_IRQHandler
isr_empty, // AES_IRQHandler
isr_empty, // RNG_IRQHandler
isr_empty, // FPU_IRQHandler
isr_empty, // HASH_IRQHandler
isr_empty, // PKA_IRQHandler
isr_empty, // LPTIM3_IRQHandler
isr_empty, // SPI3_IRQHandler
isr_empty, // I2C4_ER_IRQHandler
isr_empty, // I2C4_EV_IRQHandler
isr_empty, // DFSDM1_FLT0_IRQHandler
isr_empty, // DFSDM1_FLT1_IRQHandler
isr_empty, // DFSDM1_FLT2_IRQHandler
isr_empty, // DFSDM1_FLT3_IRQHandler
isr_empty, // UCPD1_IRQHandler
isr_empty, // ICACHE_IRQHandler
isr_empty, // OTFDEC1_IRQHandler
#else /* For STM32F4 */
isr_empty, // NVIC_WWDG_IRQ 0
isr_empty, // PVD_IRQ 1
isr_empty, // TAMP_STAMP_IRQ 2
isr_empty, // RTC_WKUP_IRQ 3
isr_empty, // FLASH_IRQ 4
isr_empty, // RCC_IRQ 5
isr_empty, // EXTI0_IRQ 6
isr_empty, // EXTI1_IRQ 7
isr_empty, // EXTI2_IRQ 8
isr_empty, // EXTI3_IRQ 9
isr_empty, // EXTI4_IRQ 10
isr_empty, // DMA1_STREAM0_IRQ 11
isr_empty, // DMA1_STREAM1_IRQ 12
isr_empty, // DMA1_STREAM2_IRQ 13
isr_empty, // DMA1_STREAM3_IRQ 14
isr_empty, // DMA1_STREAM4_IRQ 15
isr_empty, // DMA1_STREAM5_IRQ 16
isr_empty, // DMA1_STREAM6_IRQ 17
isr_empty, // ADC_IRQ 18
isr_empty, // CAN1_TX_IRQ 19
isr_empty, // CAN1_RX0_IRQ 20
isr_empty, // CAN1_RX1_IRQ 21
isr_empty, // CAN1_SCE_IRQ 22
isr_empty, // EXTI9_5_IRQ 23
isr_empty, // TIM1_BRK_TIM9_IRQ 24
isr_empty, // TIM1_UP_TIM10_IRQ 25
isr_empty, // TIM1_TRG_COM_TIM11_IRQ 26
isr_empty, // TIM1_CC_IRQ 27
isr_tim2, // TIM2_IRQ 28
isr_empty, // TIM3_IRQ 29
isr_empty, // TIM4_IRQ 30
isr_empty, // I2C1_EV_IRQ 31
isr_empty, // I2C1_ER_IRQ 32
isr_empty, // I2C2_EV_IRQ 33
isr_empty, // I2C2_ER_IRQ 34
isr_empty, // SPI1_IRQ 35
isr_empty, // SPI2_IRQ 36
isr_empty, // USART1_IRQ 37
isr_empty, // USART2_IRQ 38
isr_empty, // USART3_IRQ 39
isr_empty, // EXTI15_10_IRQ 40
isr_empty, // RTC_ALARM_IRQ 41
isr_empty, // USB_FS_WKUP_IRQ 42
isr_empty, // TIM8_BRK_TIM12_IRQ 43
isr_empty, // TIM8_UP_TIM13_IRQ 44
isr_empty, // TIM8_TRG_COM_TIM14_IRQ 45
isr_empty, // TIM8_CC_IRQ 46
isr_empty, // DMA1_STREAM7_IRQ 47
#endif
};

View File

@ -0,0 +1,147 @@
/* system.c
*
* Test bare-metal blinking led application
*
* Copyright (C) 2020 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
*/
#if defined(PLATFORM_stm32f4) || defined(PLATFORM_stm32f7)
#include <stdint.h>
#include "system.h"
/*** FLASH ***/
#define FLASH_BASE (0x40023C00)
#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
#define FLASH_ACR_ENABLE_DATA_CACHE (1 << 10)
#define FLASH_ACR_ENABLE_INST_CACHE (1 << 9)
/*** 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
/* 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
/* 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 |= TARGET_FLASH_WAITSTATES | FLASH_ACR_ENABLE_DATA_CACHE | FLASH_ACR_ENABLE_INST_CACHE;
}
void clock_config(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();
/* 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 | (RCC_PRESCALER_DIV_NONE << 4));
DMB();
reg32 = RCC_CFGR;
reg32 &= ~(0x1C00);
RCC_CFGR = (reg32 | (RCC_PRESCALER_DIV_2 << 10));
DMB();
reg32 = RCC_CFGR;
reg32 &= ~(0x07 << 13);
RCC_CFGR = (reg32 | (RCC_PRESCALER_DIV_4 << 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;
}
#endif /* PLATFORM_stm32f4 */

View File

@ -0,0 +1,67 @@
/* system.h
*
*
* Copyright (C) 2020 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
*/
#ifndef SYSTEM_H_INCLUDED
#define SYSTEM_H_INCLUDED
/* System specific: PLL with 8 MHz external oscillator, CPU at 168MHz */
#define CPU_FREQ (168000000)
#define PLL_FULL_MASK (0x7F037FFF)
/* Assembly helpers */
#define DMB() asm volatile ("dmb");
#define WFI() asm volatile ("wfi");
/* Master clock setting */
void clock_config(void);
void flash_set_waitstates(void);
/* NVIC */
/* NVIC ISER Base register (Cortex-M) */
#define NVIC_TIM2_IRQN (28)
#define NVIC_ISER_BASE (0xE000E100)
#define NVIC_ICER_BASE (0xE000E180)
#define NVIC_IPRI_BASE (0xE000E400)
static inline void nvic_irq_enable(uint8_t n)
{
int i = n / 32;
volatile uint32_t *nvic_iser = ((volatile uint32_t *)(NVIC_ISER_BASE + 4 * i));
*nvic_iser |= (1 << (n % 32));
}
static inline void nvic_irq_disable(uint8_t n)
{
int i = n / 32;
volatile uint32_t *nvic_icer = ((volatile uint32_t *)(NVIC_ICER_BASE + 4 * i));
*nvic_icer |= (1 << (n % 32));
}
static inline void nvic_irq_setprio(uint8_t n, uint8_t prio)
{
volatile uint8_t *nvic_ipri = ((volatile uint8_t *)(NVIC_IPRI_BASE + n));
*nvic_ipri = prio;
}
#endif /* !SYSTEM_H_INCLUDED */

View File

@ -0,0 +1,45 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x20100, LENGTH = 0x1FF00
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K /* Run in lowmem */
}
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);
KEEP(*(.ramcode))
. = 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));

View File

@ -0,0 +1,171 @@
/* timer.c
*
* Test bare-metal blinking led application
*
* Copyright (C) 2020 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
*/
#ifdef PLATFORM_stm32f4
#include <stdint.h>
#include "system.h"
#include "led.h"
/* STM32 specific defines */
#define APB1_CLOCK_ER (*(volatile uint32_t *)(0x40023840))
#define APB1_CLOCK_RST (*(volatile uint32_t *)(0x40023820))
#define TIM4_APB1_CLOCK_ER_VAL (1 << 2)
#define TIM2_APB1_CLOCK_ER_VAL (1 << 0)
#define TIM2_BASE (0x40000000)
#define TIM2_CR1 (*(volatile uint32_t *)(TIM2_BASE + 0x00))
#define TIM2_DIER (*(volatile uint32_t *)(TIM2_BASE + 0x0c))
#define TIM2_SR (*(volatile uint32_t *)(TIM2_BASE + 0x10))
#define TIM2_PSC (*(volatile uint32_t *)(TIM2_BASE + 0x28))
#define TIM2_ARR (*(volatile uint32_t *)(TIM2_BASE + 0x2c))
#define TIM4_BASE (0x40000800)
#define TIM4_CR1 (*(volatile uint32_t *)(TIM4_BASE + 0x00))
#define TIM4_DIER (*(volatile uint32_t *)(TIM4_BASE + 0x0c))
#define TIM4_SR (*(volatile uint32_t *)(TIM4_BASE + 0x10))
#define TIM4_CCMR1 (*(volatile uint32_t *)(TIM4_BASE + 0x18))
#define TIM4_CCMR2 (*(volatile uint32_t *)(TIM4_BASE + 0x1c))
#define TIM4_CCER (*(volatile uint32_t *)(TIM4_BASE + 0x20))
#define TIM4_PSC (*(volatile uint32_t *)(TIM4_BASE + 0x28))
#define TIM4_ARR (*(volatile uint32_t *)(TIM4_BASE + 0x2c))
#define TIM4_CCR4 (*(volatile uint32_t *)(TIM4_BASE + 0x40))
#define TIM_DIER_UIE (1 << 0)
#define TIM_SR_UIF (1 << 0)
#define TIM_CR1_CLOCK_ENABLE (1 << 0)
#define TIM_CR1_UPD_RS (1 << 2)
#define TIM_CR1_ARPE (1 << 7)
#define TIM_CCER_CC4_ENABLE (1 << 12)
#define TIM_CCMR1_OC1M_PWM1 (0x06 << 4)
#define TIM_CCMR2_OC4M_PWM1 (0x06 << 12)
#define AHB1_CLOCK_ER (*(volatile uint32_t *)(0x40023830))
#define GPIOD_AHB1_CLOCK_ER (1 << 3)
#define GPIOD_BASE 0x40020c00
#define GPIOD_MODE (*(volatile uint32_t *)(GPIOD_BASE + 0x00))
#define GPIOD_OTYPE (*(volatile uint32_t *)(GPIOD_BASE + 0x04))
#define GPIOD_PUPD (*(volatile uint32_t *)(GPIOD_BASE + 0x0c))
#define GPIOD_ODR (*(volatile uint32_t *)(GPIOD_BASE + 0x14))
static uint32_t master_clock = 0;
/** Use TIM4_CH4, which is linked to PD15 AF1 **/
int pwm_init(uint32_t clock, uint32_t threshold)
{
uint32_t val = (clock / 100000); /* Frequency is 100 KHz */
uint32_t lvl;
master_clock = clock;
if (threshold > 100)
return -1;
lvl = (val * threshold) / 100;
if (lvl != 0)
lvl--;
APB1_CLOCK_RST |= TIM4_APB1_CLOCK_ER_VAL;
asm volatile ("dmb");
APB1_CLOCK_RST &= ~TIM4_APB1_CLOCK_ER_VAL;
APB1_CLOCK_ER |= TIM4_APB1_CLOCK_ER_VAL;
/* disable CC */
TIM4_CCER &= ~TIM_CCER_CC4_ENABLE;
TIM4_CR1 = 0;
TIM4_PSC = 0;
TIM4_ARR = val - 1;
TIM4_CCR4 = lvl;
TIM4_CCMR1 &= ~(0x03 << 0);
TIM4_CCMR1 &= ~(0x07 << 4);
TIM4_CCMR1 |= TIM_CCMR1_OC1M_PWM1;
TIM4_CCMR2 &= ~(0x03 << 8);
TIM4_CCMR2 &= ~(0x07 << 12);
TIM4_CCMR2 |= TIM_CCMR2_OC4M_PWM1;
TIM4_CCER |= TIM_CCER_CC4_ENABLE;
TIM4_CR1 |= TIM_CR1_CLOCK_ENABLE | TIM_CR1_ARPE;
asm volatile ("dmb");
return 0;
}
int timer_init(uint32_t clock, uint32_t prescaler, uint32_t interval_ms)
{
uint32_t val = 0;
uint32_t psc = 1;
uint32_t err = 0;
clock = ((clock * prescaler) / 1000) * interval_ms;
while (psc < 65535) {
val = clock / psc;
err = clock % psc;
if ((val < 65535) && (err == 0)) {
val--;
break;
}
val = 0;
psc++;
}
if (val == 0)
return -1;
nvic_irq_enable(NVIC_TIM2_IRQN);
nvic_irq_setprio(NVIC_TIM2_IRQN, 0);
APB1_CLOCK_RST |= TIM2_APB1_CLOCK_ER_VAL;
asm volatile ("dmb");
APB1_CLOCK_RST &= ~TIM2_APB1_CLOCK_ER_VAL;
APB1_CLOCK_ER |= TIM2_APB1_CLOCK_ER_VAL;
TIM2_CR1 = 0;
asm volatile ("dmb");
TIM2_PSC = psc;
TIM2_ARR = val;
TIM2_CR1 |= TIM_CR1_CLOCK_ENABLE;
TIM2_DIER |= TIM_DIER_UIE;
asm volatile ("dmb");
return 0;
}
extern volatile uint32_t time_elapsed;
void isr_tim2(void)
{
static volatile uint32_t tim2_ticks = 0;
TIM2_SR &= ~TIM_SR_UIF;
/* Dim the led by altering the PWM duty-cicle */
if (++tim2_ticks > 15)
tim2_ticks = 0;
if (tim2_ticks > 8)
pwm_init(master_clock, 10 * (16 - tim2_ticks));
else
pwm_init(master_clock, 10 * tim2_ticks);
time_elapsed++;
}
#else
void isr_tim2(void)
{
}
#endif /* PLATFORM_stm32f4 */

View File

@ -0,0 +1,30 @@
/* timer.h
*
* Test bare-metal blinking led application
*
* Copyright (C) 2020 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
*/
#ifndef TIMER_H_INCLUDED
#define TIMER_H_INCLUDED
int pwm_init(uint32_t clock, uint32_t threshold);
int timer_init(uint32_t clock, uint32_t scaler, uint32_t interval);
#endif /* !TIMER_H_INCLUDED */

@ -1 +1 @@
Subproject commit 19f328cffdd1fe65b9ed764d4812adada3c819cf
Subproject commit 3516620f1a4df029e18734ef5cd9ee22813174e7