Skip to content

Commit bf29966

Browse files
authored
fix #96 - can now flash via bbf on attached USB (#103)
1 parent 3d19b35 commit bf29966

10 files changed

+248
-62
lines changed

hw/arm/prusa/stm32_chips/stm32f407xx.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static const stm32_soc_cfg_t stm32f407xx_cfg =
110110
),
111111
PER_LNIV(eth, "stm32f4xx-ethernet", P_UNDEFINED, 0x40028000, F4xx_ETH_IRQ, F4xx_ETH_WKUP_IRQ),
112112
PER_LNI(rcc, TYPE_STM32F2xx_RCC, P_RCC, 0x40023800, F4xx_RCC_IRQ),
113-
PER_LNI(flash_if, TYPE_STM32F2XX_FINT, P_FSMC, 0x40023C00, F4xx_FLASH_IRQ),
113+
PER_LNI(flash_if, TYPE_STM32F4xx_FINT, P_FINT, 0x40023C00, F4xx_FLASH_IRQ),
114114
PER_LN(iwdg, TYPE_STM32F4XX_IWDG, P_IWDG, 0x40003000),
115115
PER_LN(crc, TYPE_STM32F2XX_CRC, P_CRC, 0x40023000),
116116
PER_LN(rtc, TYPE_STM32F2XX_RTC, P_RTC, 0x40002800),

hw/arm/prusa/stm32_common/stm32_shared.h

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ enum {
9191
STM32_P_EXTI,
9292
STM32_P_SDIO,
9393
STM32_P_FSMC,
94+
STM32_P_FINT,
9495
STM32_P_RTC,
9596
STM32_P_CRC,
9697
STM32_P_DMAMUX,

hw/arm/prusa/stm32_common/stm32_types.h

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#define TYPE_STM32F2xx_RCC _STM_F2xx_PART(rcc)
3232
#define TYPE_STM32F4xx_RCC _STM_F4xx_PART(rcc)
3333

34+
#define TYPE_STM32F4xx_FINT _STM_F4xx_PART(fint)
35+
3436
#define TYPE_STM32F2xx_DMA _STM_F2xx_PART(dma)
3537
#define TYPE_STM32F4xx_DMA _STM_F4xx_PART(dma)
3638

hw/arm/prusa/stm32f407/stm32f2xx_flashint.c

+142-42
Original file line numberDiff line numberDiff line change
@@ -25,61 +25,154 @@
2525
#include "migration/vmstate.h"
2626
#include "qemu/log.h"
2727

28-
//#define DEBUG_STM32_FINT
29-
#ifdef DEBUG_STM32_FINT
30-
// NOTE: The usleep() helps the MacOS stdout from freezing when we have a lot of print out
31-
#define DPRINTF(fmt, ...) \
32-
do { printf("STM32F2XX_FINT: " fmt , ## __VA_ARGS__); \
33-
usleep(100); \
34-
} while (0)
35-
#else
36-
#define DPRINTF(fmt, ...)
37-
#endif
28+
enum RegIndex{
29+
RI_ACR,
30+
RI_KEYR,
31+
RI_OPTKEYR,
32+
RI_SR,
33+
RI_CR,
34+
RI_OPTCR,
35+
RI_END
36+
};
3837

38+
enum wp_state
39+
{
40+
LOCKED,
41+
KEY1_OK,
42+
UNLOCKED
43+
};
44+
45+
static stm32_reginfo_t stm32f4xx_flashif_reginfo[RI_END] = {
46+
[RI_ACR] = {.mask = 0x1F07, .unimp_mask = 0x1F07},
47+
[RI_KEYR] = {.mask = UINT32_MAX},
48+
[RI_OPTKEYR] = {.unimp_mask = UINT32_MAX },
49+
[RI_SR] = {.mask = 0x100F3, .unimp_mask = 0x100F3},
50+
[RI_CR] = {.mask = 0x8101037F, .unimp_mask = 0x1010304},
51+
[RI_OPTCR] = {.unimp_mask = UINT32_MAX, .reset_val =0x0FFFAAED },
52+
};
53+
54+
#define KEY1 0x45670123UL
55+
#define KEY2 0xCDEF89ABUL
56+
57+
#define OPTKEY1 0x08192A3BUL
58+
#define OPTKEY2 0x4C5D6E7FUL
59+
60+
static uint32_t sector_boundaries[][2] =
61+
{
62+
{ 0U*KiB, ( 16U*KiB)-1U},
63+
{ 16U*KiB, ( 32U*KiB)-1U},
64+
{ 32U*KiB, ( 48U*KiB)-1U},
65+
{ 48U*KiB, ( 64U*KiB)-1U},
66+
{ 64U*KiB, (128U*KiB)-1U},
67+
{128U*KiB, (256U*KiB)-1U},
68+
{256U*KiB, (384U*KiB)-1U},
69+
{384U*KiB, (512U*KiB)-1U},
70+
{512U*KiB, (640U*KiB)-1U},
71+
{640U*KiB, (768U*KiB)-1U},
72+
{768U*KiB, (896U*KiB)-1U},
73+
{896U*KiB, (1U*MiB)-1U},
74+
};
75+
76+
77+
QEMU_BUILD_BUG_MSG(RI_END != STM32_FINT_MAX, "Register index misaligned in " __FILE__);
3978

4079
static uint64_t
4180
stm32f2xx_fint_read(void *arg, hwaddr offset, unsigned int size)
4281
{
43-
stm32f2xx_fint *s = arg;
82+
STM32F4XX_STRUCT_NAME(FlashIF) *s = arg;
4483
uint32_t r;
4584

46-
offset >>= 2;
47-
r = s->regs[offset];
85+
uint32_t index = offset >> 2U;
86+
offset&= 0x3;
87+
88+
switch (index)
89+
{
90+
case RI_CR:
91+
s->regs.defs.CR.LOCK = (s->flash_state != UNLOCKED);
92+
/* FALLTHRU */
93+
default:
94+
r = s->regs.raw[index];
95+
break;
96+
}
97+
ADJUST_FOR_OFFSET_AND_SIZE_R(r, size, offset, 0b111);
4898
//printf("FINT unit %d reg %x return 0x%x\n", s->periph, (int)offset << 2, r);
4999
return r;
50100
}
51101

102+
static void stm32f4xx_flashif_sector_erase(STM32F4XX_STRUCT_NAME(FlashIF) *s)
103+
{
104+
if (s->regs.defs.CR.LOCK)
105+
{
106+
s->regs.defs.SR.WRPERR = 1;
107+
return;
108+
}
109+
printf("Erasing flash sector %u\n", s->regs.defs.CR.SNB);
110+
uint32_t (*p)[2] = &sector_boundaries[s->regs.defs.CR.SNB];
111+
uint32_t buff = 0xFFFFFFFFU;
112+
for (int i=(*p)[0]; i<=(*p)[1]; i+=4)
113+
{
114+
cpu_physical_memory_write(s->flash->addr +i, &buff, 4);
115+
}
116+
}
117+
52118
static void
53119
stm32f2xx_fint_write(void *arg, hwaddr addr, uint64_t data, unsigned int size)
54120
{
55-
stm32f2xx_fint *s = arg;
121+
STM32F4XX_STRUCT_NAME(FlashIF) *s = arg;
56122
int offset = addr & 0x03;
57123

58124
addr >>= 2;
59-
if (addr > STM32_FINT_MAX) {
60-
qemu_log_mask(LOG_GUEST_ERROR, "invalid FINT write reg 0x%x\n",
61-
(unsigned int)addr << 2);
62-
return;
63-
}
125+
CHECK_BOUNDS_W(addr, data, RI_END, stm32f4xx_flashif_reginfo, "F4xx Flash IF");
126+
ADJUST_FOR_OFFSET_AND_SIZE_W(stm32f2xx_fint_read(arg, addr<<2U, 4U), data, size, offset, 0b111)
127+
CHECK_UNIMP_RESVD(data, stm32f4xx_flashif_reginfo, addr);
64128

65-
switch(size) {
66-
case 1:
67-
data = (s->regs[addr] & ~(0xff << (offset * 8))) | data << (offset * 8);
68-
break;
69-
case 2:
70-
data = (s->regs[addr] & ~(0xffff << (offset * 8))) | data << (offset * 8);
71-
break;
72-
case 4:
73-
break;
74-
default:
75-
abort();
129+
if (s->flash_state == KEY1_OK && addr != RI_KEYR)
130+
{
131+
s->flash_state = LOCKED;
76132
}
77133

78134
switch (addr) {
135+
case RI_KEYR:
136+
{
137+
if (data == KEY1)
138+
s->flash_state = KEY1_OK;
139+
else if (data == KEY2 && s->flash_state == KEY1_OK)
140+
{
141+
s->flash_state = UNLOCKED;
142+
printf("FLASH unlocked!\n");
143+
memory_region_set_readonly(s->flash, false);
144+
}
145+
}
146+
break;
147+
case RI_CR:
148+
{
149+
REGDEF_NAME(flashif, cr) r = {.raw = data};
150+
if ( s->flash_state != UNLOCKED && !r.LOCK)
151+
{
152+
qemu_log_mask(LOG_GUEST_ERROR, __FILE__":Guest tried to clear the set-only flask LOCK bit.");
153+
r.LOCK = 1;
154+
}
155+
else if (s->flash_state == UNLOCKED && r.LOCK)
156+
{
157+
printf("FLASH LOCKED\n");
158+
memory_region_set_readonly(s->flash, true);
159+
s->flash_state = LOCKED;
160+
}
161+
s->regs.defs.CR.raw = r.raw;
162+
s->regs.defs.CR.STRT = false;
163+
if (r.STRT)
164+
{
165+
if (r.SER)
166+
{
167+
stm32f4xx_flashif_sector_erase(s);
168+
} //else if (r.PG)
169+
}
170+
}
171+
break;
79172
default:
80173
qemu_log_mask(LOG_UNIMP, "f2xx FINT reg 0x%x:%d write (0x%x) unimplemented\n",
81174
(int)addr << 2, offset, (int)data);
82-
s->regs[addr] = data;
175+
s->regs.raw[addr] = data;
83176
break;
84177
}
85178
}
@@ -97,27 +190,34 @@ static const MemoryRegionOps stm32f2xx_fint_ops = {
97190
static void
98191
stm32f2xx_fint_reset(DeviceState *dev)
99192
{
100-
stm32f2xx_fint *s = STM32F2XX_FINT(dev);
101-
s->regs[STM32_FINT_CR] = 0x80000000;
102-
s->regs[STM32_FINT_OPTCR] = 0x0FFFAAED;
193+
STM32F4XX_STRUCT_NAME(FlashIF) *s = STM32F4xx_FINT(dev);
194+
s->flash_state = LOCKED;
195+
if (s->flash)
196+
{
197+
memory_region_set_readonly(s->flash, true);
198+
}
199+
for (int i=0; i<RI_END; i++)
200+
{
201+
s->regs.raw[i] = stm32f4xx_flashif_reginfo[i].reset_val;
202+
}
103203
}
104204

105205
static void
106206
stm32f2xx_fint_init(Object *obj)
107207
{
108-
stm32f2xx_fint *s = STM32F2XX_FINT(obj);
109-
110-
memory_region_init_io(&s->iomem, obj, &stm32f2xx_fint_ops, s, "fint", 0x400);
208+
STM32F4XX_STRUCT_NAME(FlashIF) *s = STM32F4xx_FINT(obj);
209+
memory_region_init_io(&s->iomem, obj, &stm32f2xx_fint_ops, s, "flash_if", 1U *KiB);
111210
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
112211
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
113212
}
114213

115214
static const VMStateDescription vmstate_stm32f2xx_fint = {
116-
.name = TYPE_STM32F2XX_FINT,
215+
.name = TYPE_STM32F4xx_FINT,
117216
.version_id = 1,
118217
.minimum_version_id = 1,
119218
.fields = (VMStateField[]) {
120-
VMSTATE_UINT32_ARRAY(regs, stm32f2xx_fint,STM32_FINT_MAX),
219+
VMSTATE_UINT32_ARRAY(regs.raw, STM32F4XX_STRUCT_NAME(FlashIF),STM32_FINT_MAX),
220+
VMSTATE_UINT8(flash_state, STM32F4XX_STRUCT_NAME(FlashIF)),
121221
VMSTATE_END_OF_LIST()
122222
}
123223
};
@@ -132,9 +232,9 @@ stm32f2xx_fint_class_init(ObjectClass *klass, void *data)
132232
}
133233

134234
static const TypeInfo stm32f2xx_fint_info = {
135-
.name = TYPE_STM32F2XX_FINT,
136-
.parent = TYPE_SYS_BUS_DEVICE,
137-
.instance_size = sizeof(stm32f2xx_fint),
235+
.name = TYPE_STM32F4xx_FINT,
236+
.parent = TYPE_STM32_PERIPHERAL,
237+
.instance_size = sizeof(STM32F4XX_STRUCT_NAME(FlashIF)),
138238
.instance_init = stm32f2xx_fint_init,
139239
.class_init = stm32f2xx_fint_class_init
140240
};

hw/arm/prusa/stm32f407/stm32f2xx_flashint.h

+76-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
stm32f2xx_flashint.h - Flash I/F Configuration block for STM32
33
4-
Copyright 2021 VintagePC <https://github.com/vintagepc/>
4+
Copyright 2021-2022 VintagePC <https://github.com/vintagepc/>
55
66
This file is part of Mini404.
77
@@ -25,27 +25,88 @@
2525
#define STM32F2XX_FINT_H
2626

2727
#include "qemu/osdep.h"
28-
#include "hw/sysbus.h"
2928
#include "qemu-common.h"
29+
#include "../stm32_common/stm32_common.h"
3030

31-
#define STM32_FINT_ACR (0x00 / 4)
32-
#define STM32_FINT_KEYR (0x04 / 4)
33-
#define STM32_FINT_OPTKEYR (0x08 / 4)
34-
#define STM32_FINT_SR (0x0c / 4)
35-
#define STM32_FINT_CR (0x10 / 4)
36-
#define STM32_FINT_OPTCR (0x14 / 4)
3731
#define STM32_FINT_MAX (0x18 / 4)
3832

39-
#define TYPE_STM32F2XX_FINT "stm32f2xx-fint"
40-
OBJECT_DECLARE_SIMPLE_TYPE(stm32f2xx_fint, STM32F2XX_FINT)
33+
OBJECT_DECLARE_SIMPLE_TYPE(STM32F4XX_STRUCT_NAME(FlashIF), STM32F4xx_FINT)
4134

42-
struct stm32f2xx_fint {
43-
SysBusDevice busdev;
35+
REGDEF_BLOCK_BEGIN()
36+
REG_K32(LATENCY, 3);
37+
REG_R(5);
38+
REG_B32(PRFTEN);
39+
REG_B32(ICEN);
40+
REG_B32(DCEN);
41+
REG_B32(ICRST);
42+
REG_B32(DCRST);
43+
REGDEF_BLOCK_END(flashif, acr);
44+
45+
REGDEF_BLOCK_BEGIN()
46+
REG_B32(EOP);
47+
REG_B32(OPER);
48+
REG_R(2);
49+
REG_B32(WRPERR);
50+
REG_B32(PGAERR);
51+
REG_B32(PGPERR);
52+
REG_B32(PGSERR);
53+
REG_R(8);
54+
REG_B32(BSY);
55+
REG_R(15);
56+
REGDEF_BLOCK_END(flashif, sr);
57+
58+
REGDEF_BLOCK_BEGIN()
59+
REG_B32(PG);
60+
REG_B32(SER);
61+
REG_B32(MER);
62+
REG_K32(SNB, 4);
63+
REG_RB();
64+
REG_K32(PSIZE,2);
65+
REG_R(6);
66+
REG_B32(STRT);
67+
REG_R(7);
68+
REG_B32(EOPIE);
69+
REG_R(6);
70+
REG_B32(LOCK);
71+
REGDEF_BLOCK_END(flashif, cr);
72+
73+
REGDEF_BLOCK_BEGIN()
74+
REG_B32(OPTLOCK);
75+
REG_B32(OPTSTRT);
76+
REG_K32(BOR_LEV,2);
77+
REG_RB();
78+
REG_B32(WDG_SW);
79+
REG_B32(nRST_STOP);
80+
REG_B32(nRST_STDBY);
81+
REG_K32(RDP,8);
82+
REG_K32(nWRP, 12);
83+
REG_R(4);
84+
REGDEF_BLOCK_END(flashif, optcr);
85+
86+
87+
typedef struct STM32F4XX_STRUCT_NAME(FlashIF) {
88+
STM32Peripheral parent;
4489
MemoryRegion iomem;
4590

46-
uint32_t regs[STM32_FINT_MAX];
91+
union {
92+
struct {
93+
REGDEF_NAME(flashif, acr) ACR;
94+
uint32_t KEYR;
95+
uint32_t OPTKEYR;
96+
REGDEF_NAME(flashif, sr) SR;
97+
REGDEF_NAME(flashif, cr) CR;
98+
REGDEF_NAME(flashif, optcr) OPTCR;
99+
} defs;
100+
uint32_t raw[STM32_FINT_MAX];
101+
} regs;
102+
103+
104+
uint8_t flash_state;
105+
106+
MemoryRegion* flash;
107+
108+
qemu_irq irq;
47109

48-
qemu_irq irq;
49-
};
110+
} STM32F4XX_STRUCT_NAME(FlashIF);
50111

51112
#endif //#ifndef STM32F2XX_FINT_H

hw/arm/prusa/stm32f407/stm32f2xx_rcc.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -299,16 +299,16 @@ static void stm32_rcc_RCC_CFGR_write(Stm32f2xxRcc *s, uint32_t new_value, bool i
299299
REGDEF_NAME(rcc, cfgr) cfgr = {.raw = new_value};
300300
if(cfgr.PPRE2 < 0x4) {
301301
clktree_set_scale(&s->PCLK2, 1, 1);
302-
clktree_set_scale(&s->TIMCLK2, 2, 1);
302+
clktree_set_scale(&s->TIMCLK2, 1, 1);
303303
} else {
304304
clktree_set_scale(&s->PCLK2, 1, 2 * (cfgr.PPRE2 - 3));
305-
clktree_set_scale(&s->TIMCLK2, 1, 1);
305+
clktree_set_scale(&s->TIMCLK2, 2, 1);
306306
}
307307

308308
/* PPRE1 */
309309
if(cfgr.PPRE1 < 4) {
310310
clktree_set_scale(&s->PCLK1, 1, 1);
311-
clktree_set_scale(&s->TIMCLK1, 2, 1);
311+
clktree_set_scale(&s->TIMCLK1, 1, 1);
312312
} else {
313313
clktree_set_scale(&s->PCLK1, 1, 2 * (cfgr.PPRE1 - 3));
314314
clktree_set_scale(&s->TIMCLK1, 2, 1);

0 commit comments

Comments
 (0)