Skip to content

Commit 254882c

Browse files
danielinuxdgarske
authored andcommitted
Added support for STM32G0 (tested on STM32G070-Nucleo)
1 parent b558496 commit 254882c

7 files changed

Lines changed: 463 additions & 0 deletions

File tree

arch.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ ifeq ($(ARCH),ARM)
2525
ifeq ($(TARGET),stm32l0)
2626
CORTEX_M0=1
2727
endif
28+
29+
ifeq ($(TARGET),stm32g0)
30+
CORTEX_M0=1
31+
endif
2832

2933
## Cortex-M CPU
3034
ifeq ($(CORTEX_M0),1)

docs/Targets.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,41 @@ Possible workarounds:
6969
- Compile ed25519 with debug (optimizations are disabled) : `make TARGET=stm32l0 DEBUG=1`
7070
- Use ECDSA instead (which is much faster) : `make TARGET=stm32l0 SIGN=ECC256`
7171

72+
## STM32G0x0/STM32G0x1
73+
74+
Example 128KB partitioning on STM32-G070:
75+
76+
- Sector size: 2KB
77+
- Wolfboot partition size: 32KB
78+
- Application partition size: 45 KB
79+
80+
```C
81+
#define WOLFBOOT_SECTOR_SIZE 0x800 /* 2 KB */
82+
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x8000
83+
#define WOLFBOOT_PARTITION_SIZE 0xB000 /* 45 KB */
84+
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x13000
85+
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x1E000
86+
```
87+
88+
### Building
89+
90+
Use `make TARGET=stm32l0`. The option `CORTEX_M0` is automatically selected for this target.
91+
The option `NVM_FLASH_WRITEONCE=1` is mandatory on this target, since the IAP driver does not support
92+
multiple writes after each erase operation.
93+
94+
Compile with:
95+
96+
`make TARGET=stm32g0 NVM_FLASH_WRITEONCE=1`
97+
98+
#### Known issues
99+
100+
With Ed25519 (default SIGN algorithm) it's not possible at the moment to compile wolfboot
101+
with optimizations, due to a GCC linker error complaining about a missing symbol `__gnu_thumb1_case_uqi`.
102+
103+
Possible workarounds:
104+
- Compile ed25519 with debug (optimizations are disabled) : `make TARGET=stm32l0 DEBUG=1`
105+
- Use ECDSA instead (which is much faster) : `make TARGET=stm32l0 SIGN=ECC256`
106+
72107
## SiFive HiFive1 RISC-V
73108

74109
### Features
@@ -156,3 +191,6 @@ add-symbol-file test-app/image.elf 0x20020100
156191
```
157192
riscv64-unknown-elf-objdump -D test-app/image.elf
158193
```
194+
195+
196+

hal/stm32g0.c

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/* stm32g0.c
2+
*
3+
* Copyright (C) 2019 wolfSSL Inc.
4+
*
5+
* This file is part of wolfBoot.
6+
*
7+
* wolfBoot is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfBoot is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
#include <stdint.h>
23+
#include <image.h>
24+
25+
#ifndef NVM_FLASH_WRITEONCE
26+
# error "wolfBoot STM32G0 HAL: no WRITEONCE support detected. Please define NVM_FLASH_WRITEONCE"
27+
#endif
28+
29+
/* STM32 G0 register configuration */
30+
31+
/* Assembly helpers */
32+
#define DMB() __asm__ volatile ("dmb")
33+
34+
/*** RCC ***/
35+
36+
#define RCC_BASE (0x40021000)
37+
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00)) //RM0444 - 5.4.1
38+
#define RCC_PLLCFGR (*(volatile uint32_t *)(RCC_BASE + 0x0C)) //RM0444 - 5.4.4
39+
#define RCC_CFGR (*(volatile uint32_t *)(RCC_BASE + 0x08)) //RM0444 - 5.4.3
40+
#define APB1_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0x3C))
41+
#define APB2_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0x40))
42+
43+
44+
#define RCC_CR_PLLRDY (1 << 25)
45+
#define RCC_CR_PLLON (1 << 24)
46+
#define RCC_CR_HSIRDY (1 << 10)
47+
#define RCC_CR_HSION (1 << 8)
48+
49+
#define RCC_CFGR_SW_HSISYS 0x0
50+
#define RCC_CFGR_SW_PLL 0x2
51+
#define RCC_PLLCFGR_PLLR_EN (1 << 28) //RM0444 - 5.4.3
52+
53+
#define RCC_PLLCFGR_PLLSRC_HSI16 2
54+
55+
56+
/*** APB PRESCALER ***/
57+
#define RCC_PRESCALER_DIV_NONE 0
58+
59+
/*** FLASH ***/
60+
#define PWR_APB1_CLOCK_ER_VAL (1 << 28)
61+
#define SYSCFG_APB2_CLOCK_ER_VAL (1 << 0) //RM0444 - 5.4.15 - RCC_APBENR2 - SYSCFGEN
62+
63+
#define FLASH_BASE (0x40022000) /*FLASH_R_BASE = 0x40000000UL + 0x00020000UL + 0x00002000UL */
64+
#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00)) //RM0444 - 3.7.1 - FLASH_ACR
65+
#define FLASH_KEY (*(volatile uint32_t *)(FLASH_BASE + 0x08)) //RM0444 - 3.7.2 - FLASH_KEYR
66+
#define FLASH_SR (*(volatile uint32_t *)(FLASH_BASE + 0x10)) //RM0444 - 3.7.4 - FLASH_SR
67+
#define FLASH_CR (*(volatile uint32_t *)(FLASH_BASE + 0x14)) //RM0444 - 3.7.5 - FLASH_CR
68+
69+
#define FLASHMEM_ADDRESS_SPACE (0x08000000)
70+
#define FLASH_PAGE_SIZE (0x800) /* 2KB */
71+
72+
/* Register values */
73+
#define FLASH_SR_BSY1 (1 << 16) //RM0444 - 3.7.4 - FLASH_SR
74+
#define FLASH_SR_SIZERR (1 << 6) //RM0444 - 3.7.4 - FLASH_SR
75+
#define FLASH_SR_PGAERR (1 << 5) //RM0444 - 3.7.4 - FLASH_SR
76+
#define FLASH_SR_WRPERR (1 << 4) //RM0444 - 3.7.4 - FLASH_SR
77+
#define FLASH_SR_PROGERR (1 << 3)
78+
#define FLASH_SR_EOP (1 << 0) //RM0444 - 3.7.4 - FLASH_SR
79+
80+
#define FLASH_CR_LOCK (1 << 31) //RM0444 - 3.7.5 - FLASH_CR
81+
#define FLASH_CR_STRT (1 << 16) //RM0444 - 3.7.5 - FLASH_CR
82+
83+
#define FLASH_CR_PER (1 << 1) //RM0444 - 3.7.5 - FLASH_CR
84+
#define FLASH_CR_PG (1 << 0) //RM0444 - 3.7.5 - FLASH_CR
85+
86+
#define FLASH_CR_PNB_SHIFT 3 //RM0444 - 3.7.5 - FLASH_CR - PNB bits 8:3
87+
#define FLASH_CR_PNB_MASK 0x3f //RM0444 - 3.7.5 - FLASH_CR - PNB bits 8:3 - 6 bits
88+
89+
#define FLASH_KEY1 (0x45670123)
90+
#define FLASH_KEY2 (0xCDEF89AB)
91+
92+
93+
static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates)
94+
{
95+
uint32_t reg = FLASH_ACR;
96+
if ((reg & 0x03) != waitstates)
97+
FLASH_ACR = (reg & ~0x03) | waitstates ;
98+
}
99+
100+
static RAMFUNCTION void flash_wait_complete(void)
101+
{
102+
while ((FLASH_SR & FLASH_SR_BSY1) == FLASH_SR_BSY1)
103+
;
104+
}
105+
106+
static void RAMFUNCTION flash_clear_errors(void)
107+
{
108+
FLASH_SR |= ( FLASH_SR_SIZERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR | FLASH_SR_PROGERR);
109+
}
110+
111+
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
112+
{
113+
int i = 0;
114+
uint32_t *src, *dst;
115+
flash_clear_errors();
116+
FLASH_CR |= FLASH_CR_PG;
117+
118+
while (i < len) {
119+
flash_clear_errors();
120+
if ((len - i > 3) && ((((address + i) & 0x07) == 0) && ((((uint32_t)data) + i) & 0x07) == 0)) {
121+
src = (uint32_t *)data;
122+
dst = (uint32_t *)(address + FLASHMEM_ADDRESS_SPACE);
123+
flash_wait_complete();
124+
dst[i >> 2] = src[i >> 2];
125+
dst[(i >> 2) + 1] = src[(i >> 2) + 1];
126+
flash_wait_complete();
127+
i+=8;
128+
} else {
129+
uint32_t val[2];
130+
uint8_t *vbytes = (uint8_t *)(val);
131+
int off = (address + i) - (((address + i) >> 3) << 3);
132+
uint32_t base_addr = address & (~0x07); /* aligned to 64 bit */
133+
int u32_idx = (i >> 2);
134+
dst = (uint32_t *)(base_addr);
135+
val[0] = dst[u32_idx];
136+
val[1] = dst[u32_idx + 1];
137+
while ((off < 8) && (i < len))
138+
vbytes[off++] = data[i++];
139+
dst[u32_idx] = val[0];
140+
dst[u32_idx + 1] = val[1];
141+
flash_wait_complete();
142+
}
143+
}
144+
if ((FLASH_SR & FLASH_SR_EOP) == FLASH_SR_EOP);
145+
FLASH_SR |= FLASH_SR_EOP;
146+
FLASH_CR &= ~FLASH_CR_PG;
147+
return 0;
148+
}
149+
150+
void RAMFUNCTION hal_flash_unlock(void)
151+
{
152+
flash_wait_complete();
153+
if ((FLASH_CR & FLASH_CR_LOCK) != 0) {
154+
FLASH_KEY = FLASH_KEY1;
155+
DMB();
156+
FLASH_KEY = FLASH_KEY2;
157+
DMB();
158+
while ((FLASH_CR & FLASH_CR_LOCK) != 0)
159+
;
160+
}
161+
}
162+
163+
void RAMFUNCTION hal_flash_lock(void)
164+
{
165+
flash_wait_complete();
166+
if ((FLASH_CR & FLASH_CR_LOCK) == 0)
167+
FLASH_CR |= FLASH_CR_LOCK;
168+
}
169+
170+
171+
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
172+
{
173+
int start = -1, end = -1;
174+
uint32_t end_address;
175+
uint32_t p;
176+
if (len == 0)
177+
return -1;
178+
end_address = address + len - 1;
179+
for (p = address; p < end_address; p += FLASH_PAGE_SIZE) {
180+
uint32_t reg = FLASH_CR & (~(FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT));
181+
FLASH_CR = reg | ((p >> 11) << FLASH_CR_PNB_SHIFT) | FLASH_CR_PER;
182+
DMB();
183+
FLASH_CR |= FLASH_CR_STRT;
184+
flash_wait_complete();
185+
FLASH_CR &= ~FLASH_CR_PER;
186+
}
187+
return 0;
188+
}
189+
190+
static void clock_pll_off(void)
191+
{
192+
uint32_t reg32;
193+
194+
/* Select HSISYS as SYSCLK source. */
195+
reg32 = RCC_CFGR;
196+
reg32 &= ~((1 << 1) | (1 << 0));
197+
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSISYS);
198+
DMB();
199+
/* Turn off PLL */
200+
RCC_CR &= ~RCC_CR_PLLON;
201+
DMB();
202+
}
203+
204+
/*This implementation will setup HSI RC 16 MHz as PLL Source Mux, PLLCLK as System Clock Source*/
205+
static void clock_pll_on(int powersave)
206+
{
207+
uint32_t reg32;
208+
uint32_t cpu_freq, plln, pllm, pllq, pllp, pllr, hpre, ppre, flash_waitstates;
209+
210+
/* Enable Power controller */
211+
APB1_CLOCK_ER |= PWR_APB1_CLOCK_ER_VAL;
212+
213+
/* Select clock parameters (CPU Speed = 64MHz) */
214+
cpu_freq = 64000000;
215+
pllm = 4;
216+
plln = 80;
217+
pllp = 10;
218+
pllq = 5;
219+
pllr = 5;
220+
hpre = RCC_PRESCALER_DIV_NONE;
221+
ppre = RCC_PRESCALER_DIV_NONE;
222+
flash_waitstates = 2;
223+
224+
flash_set_waitstates(flash_waitstates);
225+
226+
/* Enable internal high-speed oscillator. */
227+
RCC_CR |= RCC_CR_HSION;
228+
DMB();
229+
while ((RCC_CR & RCC_CR_HSIRDY) == 0) {};
230+
231+
/* Select HSISYS as SYSCLK source. */
232+
reg32 = RCC_CFGR;
233+
reg32 &= ~((1 << 1) | (1 << 0));
234+
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSISYS);
235+
DMB();
236+
237+
/* Disable PLL */
238+
RCC_CR &= ~RCC_CR_PLLON;
239+
240+
/*
241+
* Set prescalers for AHB, ADC, ABP1, ABP2.
242+
*/
243+
reg32 = RCC_CFGR;
244+
reg32 &= ~(0xF0); //don't change bits [0-3] that were previously set
245+
RCC_CFGR = (reg32 | (hpre << 8)); //RM0444 - 5.4.3 - RCC_CFGR
246+
DMB();
247+
reg32 = RCC_CFGR;
248+
reg32 &= ~(0x1C00); //don't change bits [0-14]
249+
RCC_CFGR = (reg32 | (ppre << 12)); //RM0444 - 5.4.3 - RCC_CFGR
250+
DMB();
251+
252+
/* Set PLL config */
253+
reg32 = RCC_PLLCFGR;
254+
reg32 |= RCC_PLLCFGR_PLLSRC_HSI16;
255+
reg32 |= ((pllm - 1) << 4);
256+
reg32 |= plln << 8;
257+
reg32 |= ((pllp - 1) << 17);
258+
// reg32 |= ((pllq - 1) << 25); /* ? - Not in in RM0464 for STM32G0x0 */
259+
reg32 |= ((pllr - 1) << 29);
260+
RCC_PLLCFGR = reg32;
261+
262+
DMB();
263+
/* Enable PLL oscillator and wait for it to stabilize. */
264+
RCC_PLLCFGR |= RCC_PLLCFGR_PLLR_EN;
265+
RCC_CR |= RCC_CR_PLLON;
266+
DMB();
267+
while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
268+
269+
/* Select PLL as SYSCLK source. */
270+
reg32 = RCC_CFGR;
271+
reg32 &= ~((1 << 1) | (1 << 0));
272+
RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
273+
DMB();
274+
275+
/* Wait for PLL clock to be selected. */
276+
while ((RCC_CFGR & ((1 << 1) | (1 << 0))) != RCC_CFGR_SW_PLL) {};
277+
278+
/* SYSCFG, COMP and VREFBUF clock enable */
279+
APB2_CLOCK_ER |= SYSCFG_APB2_CLOCK_ER_VAL;
280+
}
281+
282+
void hal_init(void)
283+
{
284+
clock_pll_on(0);
285+
}
286+
287+
void hal_prepare_boot(void)
288+
{
289+
#ifdef SPI_FLASH
290+
spi_release();
291+
#endif
292+
clock_pll_off();
293+
}
294+

0 commit comments

Comments
 (0)