Skip to content

Commit e016722

Browse files
danielinuxdgarske
authored andcommitted
Added support for STM32L0X3
(firmware update successfully tested on STM32L073)
1 parent 63eb744 commit e016722

7 files changed

Lines changed: 403 additions & 9 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ RAM_CODE?=0
3030
## Initializers
3131
CFLAGS:=-D__WOLFBOOT -DWOLFBOOT_VERSION=$(WOLFBOOT_VERSION)UL
3232
LSCRIPT:=hal/$(TARGET).ld
33-
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles
33+
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles
3434
OBJS:= \
3535
./hal/$(TARGET).o \
3636
./src/loader.o \

arch.mk

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ ifeq ($(ARCH),ARM)
1717
LDFLAGS+=-mthumb -mlittle-endian -mthumb-interwork
1818
OBJS+=src/boot_arm.o
1919

20+
## Target specific configuration
21+
ifeq ($(TARGET),samr21)
22+
CORTEX_M0=1
23+
endif
24+
25+
ifeq ($(TARGET),stm32l0)
26+
CORTEX_M0=1
27+
endif
28+
2029
## Cortex-M CPU
2130
ifeq ($(CORTEX_M0),1)
2231
CFLAGS+=-mcpu=cortex-m0
@@ -67,10 +76,6 @@ OBJCOPY:=$(CROSS_COMPILE)objcopy
6776
SIZE:=$(CROSS_COMPILE)size
6877
BOOT_IMG?=test-app/image.bin
6978

70-
## Target specific configuration
71-
ifeq ($(TARGET),samr21)
72-
CORTEX_M0=1
73-
endif
7479

7580
ifeq ($(TARGET),kinetis)
7681
CFLAGS+= -I$(KINETIS_DRIVERS)/drivers -I$(KINETIS_DRIVERS) -DCPU_$(KINETIS_CPU) -I$(KINETIS_CMSIS)/Include -DDEBUG_CONSOLE_ASSERT_DISABLE=1

hal/stm32l0.c

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/* stm32l0.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+
/* STM32 L0 register configuration */
25+
26+
/* Assembly helpers */
27+
#define DMB() __asm__ volatile ("dmb")
28+
29+
/*** RCC ***/
30+
31+
#define RCC_BASE (0x40021000)
32+
#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00))
33+
#define RCC_CFGR (*(volatile uint32_t *)(RCC_BASE + 0x0C))
34+
#define RCC_CR_PLLRDY (1 << 25)
35+
#define RCC_CR_PLLON (1 << 24)
36+
#define RCC_CR_MSIRDY (1 << 9)
37+
#define RCC_CR_MSION (1 << 8)
38+
#define RCC_CR_HSI16RDY (1 << 2)
39+
#define RCC_CR_HSI16ON (1 << 0)
40+
#define RCC_CFGR_SW_MSI 0x0
41+
#define RCC_CFGR_SW_HSI16 0x1
42+
#define RCC_CFGR_SW_PLL 0x3
43+
#define RCC_CFGR_PLLDIV2 (0x01 << 22)
44+
#define RCC_CFGR_PLLMUL4 (0x01 << 18)
45+
#define RCC_PRESCALER_DIV_NONE 0
46+
47+
/*** FLASH ***/
48+
#define APB1_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0x38))
49+
#define PWR_APB1_CLOCK_ER_VAL (1 << 28)
50+
#define FLASH_BASE (0x40022000)
51+
#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
52+
#define FLASH_PECR (*(volatile uint32_t *)(FLASH_BASE + 0x04))
53+
#define FLASH_PEKEY (*(volatile uint32_t *)(FLASH_BASE + 0x0c))
54+
#define FLASH_PRGKEY (*(volatile uint32_t *)(FLASH_BASE + 0x10))
55+
#define FLASH_SR (*(volatile uint32_t *)(FLASH_BASE + 0x18))
56+
#define FLASHMEM_ADDRESS_SPACE (0x08000000)
57+
#define FLASH_PAGE_SIZE (128)
58+
59+
/* Register values */
60+
#define FLASH_ACR_ENABLE_PRFT (1 << 1)
61+
#define FLASH_SR_BSY (1 << 0)
62+
#define FLASH_SR_SIZERR (1 << 10)
63+
#define FLASH_SR_PGAERR (1 << 9)
64+
#define FLASH_SR_WRPERR (1 << 8)
65+
#define FLASH_SR_EOP (1 << 0)
66+
#define FLASH_PEKEY1 (0x89ABCDEF)
67+
#define FLASH_PEKEY2 (0x02030405)
68+
#define FLASH_PRGKEY1 (0x8C9DAEBF)
69+
#define FLASH_PRGKEY2 (0x13141516)
70+
#define FLASH_PECR_PELOCK (1 << 0)
71+
#define FLASH_PECR_PRGLOCK (1 << 1)
72+
#define FLASH_PECR_PROG (1 << 3)
73+
#define FLASH_PECR_ERASE (1 << 9)
74+
75+
76+
static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates)
77+
{
78+
if (waitstates && ((FLASH_ACR & 1) == 0))
79+
FLASH_ACR |= 1;
80+
if (!waitstates && ((FLASH_ACR & 1) == 1))
81+
FLASH_ACR &= 1;
82+
while ((FLASH_ACR & 1) != waitstates)
83+
;
84+
}
85+
86+
static RAMFUNCTION void flash_wait_complete(void)
87+
{
88+
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
89+
;
90+
}
91+
92+
static void RAMFUNCTION clear_errors(void)
93+
{
94+
FLASH_SR |= ( FLASH_SR_SIZERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR | FLASH_SR_EOP );
95+
}
96+
97+
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
98+
{
99+
int i = 0;
100+
uint32_t *src, *dst;
101+
clear_errors();
102+
103+
while (i < len) {
104+
if ((len - i > 3) && ((((address + i) & 0x03) == 0) && ((((uint32_t)data) + i) & 0x03) == 0)) {
105+
src = (uint32_t *)data;
106+
dst = (uint32_t *)(address + FLASHMEM_ADDRESS_SPACE);
107+
flash_wait_complete();
108+
dst[i >> 2] = src[i >> 2];
109+
flash_wait_complete();
110+
i+=4;
111+
} else {
112+
uint32_t val;
113+
uint8_t *vbytes = (uint8_t *)(&val);
114+
int off = (address + i) - (((address + i) >> 2) << 2);
115+
dst = (uint32_t *)(address + FLASHMEM_ADDRESS_SPACE - off);
116+
val = dst[i >> 2];
117+
vbytes[off] = data[i];
118+
flash_wait_complete();
119+
dst[i >> 2] = val;
120+
flash_wait_complete();
121+
i++;
122+
}
123+
}
124+
return 0;
125+
}
126+
127+
void RAMFUNCTION hal_flash_unlock(void)
128+
{
129+
flash_wait_complete();
130+
if ((FLASH_PECR & FLASH_PECR_PELOCK) != 0) {
131+
FLASH_PEKEY = FLASH_PEKEY1;
132+
DMB();
133+
FLASH_PEKEY = FLASH_PEKEY2;
134+
DMB();
135+
while ((FLASH_PECR & FLASH_PECR_PELOCK) != 0)
136+
;
137+
}
138+
if ((FLASH_PECR & FLASH_PECR_PRGLOCK) != 0) {
139+
FLASH_PRGKEY = FLASH_PRGKEY1;
140+
DMB();
141+
FLASH_PRGKEY = FLASH_PRGKEY2;
142+
DMB();
143+
while ((FLASH_PECR & FLASH_PECR_PRGLOCK) != 0)
144+
;
145+
}
146+
}
147+
148+
void RAMFUNCTION hal_flash_lock(void)
149+
{
150+
flash_wait_complete();
151+
if ((FLASH_PECR & FLASH_PECR_PRGLOCK) == 0)
152+
FLASH_PECR |= FLASH_PECR_PRGLOCK;
153+
}
154+
155+
156+
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
157+
{
158+
int start = -1, end = -1;
159+
uint32_t end_address;
160+
uint32_t p;
161+
if (len == 0)
162+
return -1;
163+
end_address = address + len - 1;
164+
for (p = address; p < end_address; p += FLASH_PAGE_SIZE) {
165+
FLASH_PECR |= FLASH_PECR_PROG | FLASH_PECR_ERASE;
166+
*(volatile uint32_t *)(p + FLASHMEM_ADDRESS_SPACE) = 0xFFFFFFFF;
167+
FLASH_PECR &= ~(FLASH_PECR_PROG | FLASH_PECR_ERASE);
168+
flash_wait_complete();
169+
}
170+
return 0;
171+
}
172+
173+
static void clock_pll_off(void)
174+
{
175+
uint32_t reg32;
176+
/* Enable internal high-speed oscillator. */
177+
RCC_CR |= RCC_CR_MSION;
178+
DMB();
179+
while ((RCC_CR & RCC_CR_MSIRDY) == 0) {};
180+
/* Select MSI as SYSCLK source. */
181+
reg32 = RCC_CFGR;
182+
reg32 &= ~((1 << 1) | (1 << 0));
183+
DMB();
184+
/* Turn off PLL */
185+
RCC_CR &= ~RCC_CR_PLLON;
186+
DMB();
187+
}
188+
189+
static void clock_pll_on(int powersave)
190+
{
191+
uint32_t reg32;
192+
uint32_t cpu_freq, hsi_freq, hpre, ppre1, ppre2, flash_waitstates;
193+
194+
/* Enable Power controller */
195+
APB1_CLOCK_ER |= PWR_APB1_CLOCK_ER_VAL;
196+
197+
/* Select clock parameters (CPU Speed = 32MHz) */
198+
cpu_freq = 32000000;
199+
hsi_freq = 16000000;
200+
hpre = RCC_PRESCALER_DIV_NONE;
201+
ppre1 = RCC_PRESCALER_DIV_NONE;
202+
ppre2 = RCC_PRESCALER_DIV_NONE;
203+
flash_waitstates = 1;
204+
205+
flash_set_waitstates(flash_waitstates);
206+
207+
/* Enable internal high-speed oscillator. */
208+
RCC_CR |= RCC_CR_HSI16ON;
209+
DMB();
210+
while ((RCC_CR & RCC_CR_HSI16RDY) == 0) {};
211+
212+
/* Select HSI as SYSCLK source. */
213+
reg32 = RCC_CFGR;
214+
reg32 &= ~((1 << 1) | (1 << 0));
215+
RCC_CFGR = (reg32 | RCC_CFGR_SW_HSI16);
216+
DMB();
217+
218+
/*
219+
* Set prescalers for AHB, ADC, ABP1, ABP2.
220+
*/
221+
reg32 = RCC_CFGR;
222+
reg32 &= ~(0xF << 4);
223+
RCC_CFGR = (reg32 | (hpre << 4));
224+
DMB();
225+
reg32 = RCC_CFGR;
226+
reg32 &= ~(0x07 << 8);
227+
RCC_CFGR = (reg32 | (ppre1 << 8));
228+
DMB();
229+
reg32 &= ~(0x07 << 11);
230+
RCC_CFGR = (reg32 | (ppre2 << 11));
231+
DMB();
232+
reg32 &= ~(0x0F << 18);
233+
RCC_CFGR = (reg32 | RCC_CFGR_PLLMUL4);
234+
DMB();
235+
reg32 &= ~(0x03 << 22);
236+
RCC_CFGR = (reg32 | RCC_CFGR_PLLDIV2);
237+
DMB();
238+
/* Enable PLL oscillator and wait for it to stabilize. */
239+
RCC_CR |= RCC_CR_PLLON;
240+
DMB();
241+
while ((RCC_CR & RCC_CR_PLLRDY) == 0) {};
242+
243+
/* Select PLL as SYSCLK source. */
244+
reg32 = RCC_CFGR;
245+
reg32 &= ~((1 << 1) | (1 << 0));
246+
RCC_CFGR = (reg32 | RCC_CFGR_SW_PLL);
247+
DMB();
248+
249+
/* Wait for PLL clock to be selected. */
250+
while (((RCC_CFGR >> 2) & 0x03) != RCC_CFGR_SW_PLL)
251+
;
252+
}
253+
254+
void hal_init(void)
255+
{
256+
clock_pll_on(0);
257+
}
258+
259+
void hal_prepare_boot(void)
260+
{
261+
#ifdef SPI_FLASH
262+
spi_release();
263+
#endif
264+
hal_flash_lock();
265+
if ((FLASH_PECR & FLASH_PECR_PELOCK) == 0)
266+
FLASH_PECR |= FLASH_PECR_PELOCK;
267+
clock_pll_off();
268+
}
269+

hal/stm32l0.ld

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
MEMORY
2+
{
3+
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x8000
4+
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
5+
}
6+
7+
SECTIONS
8+
{
9+
.text :
10+
{
11+
_start_text = .;
12+
KEEP(*(.isr_vector))
13+
*(.text*)
14+
*(.rodata*)
15+
. = ALIGN(4);
16+
_end_text = .;
17+
} > FLASH
18+
.edidx :
19+
{
20+
. = ALIGN(4);
21+
*(.ARM.exidx*)
22+
} > FLASH
23+
_stored_data = .;
24+
.data : AT (_stored_data)
25+
{
26+
_start_data = .;
27+
KEEP(*(.data*))
28+
. = ALIGN(4);
29+
KEEP(*(.ramcode))
30+
. = ALIGN(4);
31+
_end_data = .;
32+
} > RAM
33+
34+
.bss (NOLOAD) :
35+
{
36+
_start_bss = .;
37+
__bss_start__ = .;
38+
*(.bss*)
39+
*(COMMON)
40+
. = ALIGN(4);
41+
_end_bss = .;
42+
__bss_end__ = .;
43+
_end = .;
44+
} > RAM
45+
. = ALIGN(4);
46+
}
47+
48+
END_STACK = ORIGIN(RAM) + LENGTH(RAM);

test-app/ARM.ld

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
MEMORY
22
{
3-
FLASH (rx) : ORIGIN = 0x0020100, LENGTH = 0x001FF00
4-
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000
3+
FLASH (rx) : ORIGIN = 0x0008100, LENGTH = 0x005FFF
4+
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K /* Run in lowmem */
55
}
66

77
SECTIONS

0 commit comments

Comments
 (0)