Skip to content

Commit 35d3a75

Browse files
committed
Add h563
1 parent 1820e65 commit 35d3a75

File tree

8 files changed

+864
-0
lines changed

8 files changed

+864
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion
2+
CFLAGS += -Wformat-truncation -fno-common -Wno-sign-conversion
3+
#CFLAGS += -Wconversion # For LFS
4+
CFLAGS += -Wno-error=shadow # For LFS
5+
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
6+
CFLAGS += -I. -Imongoose -Icmsis_core/CMSIS/Core/Include -Icmsis_h5/Include
7+
CFLAGS += -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard $(CFLAGS_EXTRA)
8+
9+
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
10+
11+
SOURCES = main.c syscalls.c
12+
SOURCES += retarget_lfs.c littlefs/lfs.c littlefs/lfs_util.c
13+
SOURCES += cmsis_h5/Source/Templates/gcc/startup_stm32h563xx.s
14+
15+
all build: firmware.bin
16+
17+
firmware.bin: firmware.elf
18+
arm-none-eabi-objcopy -O binary $< $@
19+
arm-none-eabi-size --format=berkeley $<
20+
21+
firmware.elf: cmsis_core cmsis_h5 littlefs $(SOURCES) $(wildcard *.h) link.ld Makefile
22+
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
23+
24+
flash: firmware.bin
25+
STM32_Programmer_CLI -c port=swd -e all -w $< 0x8000000 -hardRst
26+
27+
cmsis_core:
28+
git clone -q -c advice.detachedHead=false --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
29+
30+
cmsis_h5:
31+
git clone -q -c advice.detachedHead=false --depth 1 -b v1.2.0 https://github.com/STMicroelectronics/cmsis_device_h5 $@
32+
33+
littlefs/lfs.c: littlefs
34+
littlefs:
35+
git clone -q -c advice.detachedHead=false --depth 1 -b v2.6.1 https://github.com/littlefs-project/littlefs $@
36+
37+
clean:
38+
rm -rf firmware.* cmsis_* littlefs
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright (c) 2022-2025 Cesanta Software Limited
2+
// SPDX-License-Identifier: GPL-2.0-only or commercial
3+
#pragma once
4+
5+
#define FLASH_START_ADDR 0x8000000
6+
#define FLASH_TOTAL_SIZE (2 * 1024 * 1024) // Defined in the CMSIS header
7+
#define FLASH_BLOCK_SIZE 8192 // FLash block size in bytes
8+
#define FLASH_ALIGN_SIZE 16
9+
10+
#define MG_REG(x) ((volatile uint32_t *) (x))[0]
11+
#define MG_BIT(x) (((uint32_t) 1U) << (x))
12+
#define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK)
13+
14+
#ifndef MG_DEBUG
15+
#define MG_DEBUG(x) // printf x; putchar('\n')
16+
#define MG_ERROR(x) // printf x; putchar('\n')
17+
#endif
18+
19+
#if defined(__GNUC__)
20+
#define MG_ARM_DISABLE_IRQ() asm volatile("cpsid i" : : : "memory")
21+
#define MG_ARM_ENABLE_IRQ() asm volatile("cpsie i" : : : "memory")
22+
#elif defined(__CCRH__)
23+
#define MG_RH850_DISABLE_IRQ() __DI()
24+
#define MG_RH850_ENABLE_IRQ() __EI()
25+
#else
26+
#define MG_ARM_DISABLE_IRQ()
27+
#define MG_ARM_ENABLE_IRQ()
28+
#endif
29+
30+
#define MG_FLASH_CONTROLLER_ADDR 0x40022000 // Flash controller base address
31+
#define FLASH_KEYR (MG_FLASH_CONTROLLER_ADDR + 0x4) // See RM0481 7.11
32+
#define FLASH_OPTKEYR (MG_FLASH_CONTROLLER_ADDR + 0xc)
33+
#define FLASH_OPTCR (MG_FLASH_CONTROLLER_ADDR + 0x1c)
34+
#define FLASH_NSSR (MG_FLASH_CONTROLLER_ADDR + 0x20)
35+
#define FLASH_NSCR (MG_FLASH_CONTROLLER_ADDR + 0x28)
36+
#define FLASH_NSCCR (MG_FLASH_CONTROLLER_ADDR + 0x30)
37+
#define FLASH_OPTSR_CUR (MG_FLASH_CONTROLLER_ADDR + 0x50)
38+
#define FLASH_OPTSR_PRG (MG_FLASH_CONTROLLER_ADDR + 0x54)
39+
40+
static inline void flash_unlock(void) {
41+
if (MG_REG(FLASH_NSCR) & MG_BIT(0)) {
42+
MG_REG(FLASH_KEYR) = 0x45670123;
43+
MG_REG(FLASH_KEYR) = 0xcdef89ab;
44+
MG_REG(FLASH_OPTKEYR) = 0x08192a3b;
45+
MG_REG(FLASH_OPTKEYR) = 0x4c5d6e7f;
46+
}
47+
}
48+
49+
static inline int flash_page_start(volatile uint32_t *dst) {
50+
char *base = (char *) FLASH_START_ADDR, *end = base + FLASH_TOTAL_SIZE;
51+
volatile char *p = (char *) dst;
52+
return p >= base && p < end && ((p - base) % FLASH_BLOCK_SIZE) == 0;
53+
}
54+
55+
static inline bool flash_is_err(void) {
56+
return MG_REG(FLASH_NSSR) & ((MG_BIT(8) - 1) << 17); // RM0481 7.11.9
57+
}
58+
59+
static inline void flash_wait(void) {
60+
while ((MG_REG(FLASH_NSSR) & MG_BIT(0)) &&
61+
(MG_REG(FLASH_NSSR) & MG_BIT(16)) == 0) {
62+
(void) 0;
63+
}
64+
}
65+
66+
static inline void flash_clear_err(void) {
67+
flash_wait(); // Wait until ready
68+
MG_REG(FLASH_NSCCR) = ((MG_BIT(9) - 1) << 16U); // Clear all errors
69+
}
70+
71+
static inline bool flash_bank_is_swapped(void) {
72+
return MG_REG(FLASH_OPTCR) & MG_BIT(31); // RM0481 7.11.8
73+
}
74+
75+
static inline bool flash_erase_block(void *location) {
76+
bool ok = false;
77+
if (flash_page_start(location) == false) {
78+
MG_ERROR(("%p is not on a sector boundary", location));
79+
} else {
80+
uintptr_t diff = (char *) location - (char *) FLASH_START_ADDR;
81+
uint32_t sector = diff / FLASH_BLOCK_SIZE;
82+
flash_unlock();
83+
flash_clear_err();
84+
MG_REG(FLASH_NSCR) = 0;
85+
if ((sector < 128 && flash_bank_is_swapped()) ||
86+
(sector > 127 && !flash_bank_is_swapped())) {
87+
MG_REG(FLASH_NSCR) |= MG_BIT(31); // Set FLASH_CR_BKSEL
88+
}
89+
if (sector > 127) sector -= 128;
90+
MG_REG(FLASH_NSCR) |= MG_BIT(2) | (sector << 6); // Erase | sector_num
91+
MG_REG(FLASH_NSCR) |= MG_BIT(5); // Start erasing
92+
flash_wait();
93+
ok = !flash_is_err();
94+
MG_DEBUG(("Erase sector %lu @ %p: %s. CR %#lx SR %#lx", sector, location,
95+
ok ? "ok" : "fail", MG_REG(FLASH_NSCR), MG_REG(FLASH_NSSR)));
96+
// mg_hexdump(location, 32);
97+
MG_REG(FLASH_NSCR) = 0; // Restore saved CR
98+
}
99+
return ok;
100+
}
101+
102+
static inline bool flash_swap_bank(void) {
103+
uint32_t desired = flash_bank_is_swapped() ? 0 : MG_BIT(31);
104+
flash_unlock();
105+
flash_clear_err();
106+
// printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG);
107+
MG_SET_BITS(MG_REG(FLASH_OPTSR_PRG), MG_BIT(31), desired);
108+
// printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG);
109+
MG_REG(FLASH_OPTCR) |= MG_BIT(1); // OPTSTART
110+
while ((MG_REG(FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0;
111+
return true;
112+
}
113+
114+
static inline size_t flash_write_buf(void *addr, const void *buf, size_t len) {
115+
if ((len % FLASH_ALIGN_SIZE) != 0) {
116+
MG_ERROR(("%u is not aligned to %u", len, FLASH_ALIGN_SIZE));
117+
return 0;
118+
}
119+
uint32_t *dst = (uint32_t *) addr;
120+
uint32_t *src = (uint32_t *) buf;
121+
uint32_t *end = (uint32_t *) ((char *) buf + len);
122+
bool ok = true;
123+
MG_ARM_DISABLE_IRQ();
124+
flash_unlock();
125+
flash_clear_err();
126+
MG_REG(FLASH_NSCR) = MG_BIT(1); // Set programming flag
127+
while (ok && src < end) {
128+
#if 0
129+
if (flash_page_start(dst) && flash_erase_block(dst) == false) {
130+
ok = false;
131+
break;
132+
}
133+
#endif
134+
*(volatile uint32_t *) dst++ = *src++;
135+
flash_wait();
136+
if (flash_is_err()) {
137+
ok = false;
138+
break;
139+
}
140+
}
141+
MG_ARM_ENABLE_IRQ();
142+
MG_DEBUG(("Flash write %zu bytes @ %p: %s. CR %#lx SR %#lx", len, dst,
143+
flash_is_err() ? "fail" : "ok", MG_REG(FLASH_NSCR),
144+
MG_REG(FLASH_NSSR)));
145+
MG_REG(FLASH_NSCR) = 0; // Restore CR
146+
return (size_t) ((char *) src - (char *) buf);
147+
}

0 commit comments

Comments
 (0)