Skip to content

Commit 8e13ebc

Browse files
committed
puya: add support for PY32F002B
The PY32F002B series uses different DBGMCU IDCODE values and there does not seem to be a register containing RAM and flash size. While the procedure for preparing flash access (copying parameters from factory-programmed EPPARAx registers to flash peripheral registers) is the same, the bit allocation inside the registers is slightly different. The structure and values of the DBGMCU IDCODE register are undocumented but the vendor SDK splits it into DEV_ID and REV_ID fields. We use the DEV_ID fields of the IDCODE values observed on PY32F002AW15U and PY32F002BF15P6 to distinguish between the two families. An internet search shows that at least the PY32F002BW15 uses the same value as the PY32F002BF15P6. The full IDCODE values are retained as comments to make it easier to fix the code later if it turns out the DEV_ID/REV_ID split is incorrect. For PY32F002A the EPPARA4 PRETPE mask value was kept the same as before (14 bits). The Reference Manual has conflicting information about it: EPPARA4 26:16 (which are 11 bits) is supposed to contain PRETPE 11:0 (which are 12 bits). FLASH_PRETPE, which is documented as having to be initialised from the EPPARA4 value, has 14 bits for PRETPE. The official Keil Device Family Pack v1.2.1 from Puya uses the full upper 16 bit of EPPARA4 so presumably the reserved bits are simply 0 and using the full 14 bit mask is probably fine.
1 parent 3576cdf commit 8e13ebc

File tree

1 file changed

+150
-29
lines changed

1 file changed

+150
-29
lines changed

src/target/puya.c

Lines changed: 150 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,53 @@
4242
#define PUYA_FLASH_START 0x08000000U
4343
#define PUYA_FLASH_PAGE_SIZE 128
4444

45-
/* Pile of timing parameters needed to make sure flash works,
46-
* see section "4.4. Flash configuration bytes" of the RM.
45+
/*
46+
* Pile of timing parameters needed to make sure flash works, see section "4.5. Flash configuration bytes" of the RM.
4747
*/
48-
#define PUYA_FLASH_TIMING_CAL_BASE 0x1fff0f1cU
48+
#define PUYA_FLASH_TIMING_CAL_PY32F002A_BASE 0x1fff0f1cU
49+
#define PY32F002A_EPPARA0_TS0_SHIFT 0U
50+
#define PY32F002A_EPPARA0_TS0_MASK 0xffU
51+
#define PY32F002A_EPPARA0_TS3_SHIFT 8U
52+
#define PY32F002A_EPPARA0_TS3_MASK 0xffU
53+
#define PY32F002A_EPPARA0_TS1_SHIFT 16U
54+
#define PY32F002A_EPPARA0_TS1_MASK 0x1ffU
55+
#define PY32F002A_EPPARA1_TS2P_SHIFT 0U
56+
#define PY32F002A_EPPARA1_TS2P_MASK 0xffU
57+
#define PY32F002A_EPPARA1_TPS3_SHIFT 16U
58+
#define PY32F002A_EPPARA1_TPS3_MASK 0x7ffU
59+
#define PY32F002A_EPPARA2_PERTPE_SHIFT 0U
60+
#define PY32F002A_EPPARA2_PERTPE_MASK 0x1ffffU
61+
#define PY32F002A_EPPARA3_SMERTPE_SHIFT 0U
62+
#define PY32F002A_EPPARA3_SMERTPE_MASK 0x1ffffU
63+
#define PY32F002A_EPPARA4_PRGTPE_SHIFT 0U
64+
#define PY32F002A_EPPARA4_PRGTPE_MASK 0xffffU
65+
#define PY32F002A_EPPARA4_PRETPE_SHIFT 16U
66+
/* This one is a bit of a mess. The PY32F002A Reference Manual says EPPARA4 26:16 (11 bit) are PRETPE[11:0] (12
67+
* bit). FLASH_PRETPE is 14 bit wide (0:13) and must be initialised from the value in EPPARA4. The PY32F002A flash
68+
* driver (PY32F0xx_20.FLM) contained in the Keil Device Family Pack v1.2.1 provided by Puya stores the full upper 16
69+
* bits of EPPARA4 into FLASH_PRETPE. Presumably the reserved bits are 0. We use the width of FLASH_PRETPE (14 bits)
70+
* for now. */
71+
#define PY32F002A_EPPARA4_PRETPE_MASK 0x3fffU
72+
#define PUYA_FLASH_TIMING_CAL_PY32F002B_BASE 0x1fff011cU
73+
#define PY32F002B_EPPARA0_TS0_SHIFT 0U
74+
#define PY32F002B_EPPARA0_TS0_MASK 0x1ffU
75+
#define PY32F002B_EPPARA0_TS3_SHIFT 9U
76+
#define PY32F002B_EPPARA0_TS3_MASK 0x1ffU
77+
#define PY32F002B_EPPARA0_TS1_SHIFT 18U
78+
#define PY32F002B_EPPARA0_TS1_MASK 0x3ffU
79+
#define PY32F002B_EPPARA1_TS2P_SHIFT 0U
80+
#define PY32F002B_EPPARA1_TS2P_MASK 0x1ffU
81+
#define PY32F002B_EPPARA1_TPS3_SHIFT 16U
82+
#define PY32F002B_EPPARA1_TPS3_MASK 0xfffU
83+
#define PY32F002B_EPPARA2_PERTPE_SHIFT 0U
84+
#define PY32F002B_EPPARA2_PERTPE_MASK 0x3ffffU
85+
#define PY32F002B_EPPARA3_SMERTPE_SHIFT 0U
86+
#define PY32F002B_EPPARA3_SMERTPE_MASK 0x3ffffU
87+
#define PY32F002B_EPPARA4_PRGTPE_SHIFT 0U
88+
#define PY32F002B_EPPARA4_PRGTPE_MASK 0xffffU
89+
#define PY32F002B_EPPARA4_PRETPE_SHIFT 16U
90+
#define PY32F002B_EPPARA4_PRETPE_MASK 0x3fffU
91+
4992
/* This config word is undocumented, but the Puya-ISP boot code
5093
* uses it to determine the valid flash/ram size.
5194
* (yes, this *does* include undocumented free extra flash/ram in the 002A)
@@ -99,6 +142,22 @@
99142
/* DBG */
100143
#define PUYA_DBG_BASE 0x40015800U
101144
#define PUYA_DBG_IDCODE (PUYA_DBG_BASE + 0x00U)
145+
/*
146+
* The format and values of the IDCODE register are undocumented but the vendor SDK splits IDCODE into 11:0 DEV_ID and
147+
* 31:16 REV_ID.
148+
*/
149+
#define PUYA_DBG_IDCODE_DEV_ID_SHIFT 0U
150+
#define PUYA_DBG_IDCODE_DEV_ID_MASK 0xfffU
151+
#define PUYA_DBG_IDCODE_REV_ID_SHIFT 16U
152+
#define PUYA_DBG_IDCODE_REV_ID_MASK 0xffffU
153+
154+
/* On PY32F002AW15U an IDCODE value of 0x60001000 was observed */
155+
#define PUYA_DEV_ID_PY32F002A 0x000U
156+
/*
157+
* On PY32F002BF15P an IDCODE value of 0x20220064 was observed. Internet search shows the same value is used on
158+
* PY32F002BW15.
159+
*/
160+
#define PUYA_DEV_ID_PY32F002B 0x064U
102161

103162
/*
104163
* Flash functions
@@ -114,18 +173,32 @@ bool puya_probe(target_s *target)
114173
size_t flash_size = 0U;
115174

116175
const uint32_t dbg_idcode = target_mem32_read32(target, PUYA_DBG_IDCODE);
117-
if ((dbg_idcode & 0xfffU) == 0) {
176+
const uint16_t dev_id = (dbg_idcode >> PUYA_DBG_IDCODE_DEV_ID_SHIFT) & PUYA_DBG_IDCODE_DEV_ID_MASK;
177+
switch (dev_id) {
178+
case PUYA_DEV_ID_PY32F002A: {
118179
const uint32_t flash_ram_sz = target_mem32_read32(target, PUYA_FLASH_RAM_SZ);
119180
flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT) & PUYA_FLASH_SZ_MASK) + 1) << PUYA_FLASH_UNIT_SHIFT;
120181
ram_size = (((flash_ram_sz >> PUYA_RAM_SZ_SHIFT) & PUYA_RAM_SZ_MASK) + 1) << PUYA_RAM_UNIT_SHIFT;
121-
// TODO: which part families does this actually correspond to?
122-
// Tested with a PY32F002AW15U which returns 0x60001000 in IDCODE
123-
target->driver = "PY32Fxxx";
124-
} else {
182+
target->driver = "PY32F002A";
183+
break;
184+
}
185+
case PUYA_DEV_ID_PY32F002B:
186+
/*
187+
* 0x1fff0ffc contains 0; did not find any other location that looks like it might contain the flash
188+
* and RAM sizes. We'll hard-code the datasheet values for now. Both flash size and RAM size actually
189+
* match the datasheet value, unlike PY32F002A which (sometimes?) has more RAM and flash than
190+
* documented.
191+
*/
192+
flash_size = 24U * 1024U;
193+
ram_size = 3U * 1024U;
194+
target->driver = "PY32F002B";
195+
break;
196+
default:
125197
DEBUG_TARGET("Unknown PY32 device %08" PRIx32 "\n", dbg_idcode);
126198
return false;
127199
}
128200

201+
target->part_id = dev_id;
129202
target_add_ram32(target, PUYA_RAM_START, ram_size);
130203
target_flash_s *flash = calloc(1, sizeof(*flash));
131204
if (!flash) { /* calloc failed: heap exhaustion */
@@ -151,33 +224,81 @@ static bool puya_flash_prepare(target_flash_s *flash)
151224
target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY1);
152225
target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY2);
153226

154-
uint8_t hsi_fs =
155-
(target_mem32_read32(flash->t, PUYA_RCC_ICSCR) >> PUYA_RCC_ICSCR_HSI_FS_SHIFT) & PUYA_RCC_ICSCR_HSI_FS_MASK;
156-
if (hsi_fs > 4)
157-
hsi_fs = 0;
158-
DEBUG_TARGET("HSI frequency selection is %d\n", hsi_fs);
159-
160-
const uint32_t eppara0 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 0);
161-
const uint32_t eppara1 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 4);
162-
const uint32_t eppara2 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 8);
163-
const uint32_t eppara3 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 12);
164-
const uint32_t eppara4 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 16);
227+
target_s *target = flash->t;
228+
uint32_t cal_base;
229+
230+
switch (target->part_id) {
231+
case PUYA_DEV_ID_PY32F002A: {
232+
uint8_t hsi_fs =
233+
(target_mem32_read32(flash->t, PUYA_RCC_ICSCR) >> PUYA_RCC_ICSCR_HSI_FS_SHIFT) & PUYA_RCC_ICSCR_HSI_FS_MASK;
234+
if (hsi_fs > 4)
235+
hsi_fs = 0;
236+
DEBUG_TARGET("HSI frequency selection is %d\n", hsi_fs);
237+
cal_base = PUYA_FLASH_TIMING_CAL_PY32F002A_BASE + hsi_fs * 20;
238+
break;
239+
}
240+
case PUYA_DEV_ID_PY32F002B:
241+
cal_base = PUYA_FLASH_TIMING_CAL_PY32F002B_BASE;
242+
break;
243+
default:
244+
/* Should have never made it past probe */
245+
DEBUG_TARGET("Unknown PY32 device %08" PRIx32 "\n", target->part_id);
246+
return false;
247+
}
248+
249+
const uint32_t eppara0 = target_mem32_read32(flash->t, cal_base + 0);
250+
const uint32_t eppara1 = target_mem32_read32(flash->t, cal_base + 4);
251+
const uint32_t eppara2 = target_mem32_read32(flash->t, cal_base + 8);
252+
const uint32_t eppara3 = target_mem32_read32(flash->t, cal_base + 12);
253+
const uint32_t eppara4 = target_mem32_read32(flash->t, cal_base + 16);
165254
DEBUG_TARGET("PY32 flash timing cal 0: %08" PRIx32 "\n", eppara0);
166255
DEBUG_TARGET("PY32 flash timing cal 1: %08" PRIx32 "\n", eppara1);
167256
DEBUG_TARGET("PY32 flash timing cal 2: %08" PRIx32 "\n", eppara2);
168257
DEBUG_TARGET("PY32 flash timing cal 3: %08" PRIx32 "\n", eppara3);
169258
DEBUG_TARGET("PY32 flash timing cal 4: %08" PRIx32 "\n", eppara4);
170259

171-
target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara0 & 0xffU);
172-
target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara0 >> 16U) & 0x1ffU);
173-
target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara0 >> 8U) & 0xffU);
174-
target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara1 & 0xffU);
175-
target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara1 >> 16U) & 0x7ffU);
176-
target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara2 & 0x1ffffU);
177-
target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara3 & 0x1ffffU);
178-
target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara4 & 0xffffU);
179-
target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara4 >> 16U) & 0x3fffU);
180-
260+
switch (target->part_id) {
261+
case PUYA_DEV_ID_PY32F002A:
262+
target_mem32_write32(flash->t, PUYA_FLASH_TS0,
263+
(eppara0 >> PY32F002A_EPPARA0_TS0_SHIFT) & PY32F002A_EPPARA0_TS0_MASK);
264+
target_mem32_write32(flash->t, PUYA_FLASH_TS1,
265+
(eppara0 >> PY32F002A_EPPARA0_TS1_SHIFT) & PY32F002A_EPPARA0_TS1_MASK);
266+
target_mem32_write32(flash->t, PUYA_FLASH_TS3,
267+
(eppara0 >> PY32F002A_EPPARA0_TS3_SHIFT) & PY32F002A_EPPARA0_TS3_MASK);
268+
target_mem32_write32(flash->t, PUYA_FLASH_TS2P,
269+
(eppara1 >> PY32F002A_EPPARA1_TS2P_SHIFT) & PY32F002A_EPPARA1_TS2P_MASK);
270+
target_mem32_write32(flash->t, PUYA_FLASH_TPS3,
271+
(eppara1 >> PY32F002A_EPPARA1_TPS3_SHIFT) & PY32F002A_EPPARA1_TPS3_MASK);
272+
target_mem32_write32(flash->t, PUYA_FLASH_PERTPE,
273+
(eppara2 >> PY32F002A_EPPARA2_PERTPE_SHIFT) & PY32F002A_EPPARA2_PERTPE_MASK);
274+
target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE,
275+
(eppara3 >> PY32F002A_EPPARA3_SMERTPE_SHIFT) & PY32F002A_EPPARA3_SMERTPE_MASK);
276+
target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE,
277+
(eppara4 >> PY32F002A_EPPARA4_PRGTPE_SHIFT) & PY32F002A_EPPARA4_PRGTPE_MASK);
278+
target_mem32_write32(flash->t, PUYA_FLASH_PRETPE,
279+
(eppara4 >> PY32F002A_EPPARA4_PRETPE_SHIFT) & PY32F002A_EPPARA4_PRETPE_MASK);
280+
break;
281+
case PUYA_DEV_ID_PY32F002B:
282+
target_mem32_write32(flash->t, PUYA_FLASH_TS0,
283+
(eppara0 >> PY32F002B_EPPARA0_TS0_SHIFT) & PY32F002B_EPPARA0_TS0_MASK);
284+
target_mem32_write32(flash->t, PUYA_FLASH_TS1,
285+
(eppara0 >> PY32F002B_EPPARA0_TS1_SHIFT) & PY32F002B_EPPARA0_TS1_MASK);
286+
target_mem32_write32(flash->t, PUYA_FLASH_TS3,
287+
(eppara0 >> PY32F002B_EPPARA0_TS3_SHIFT) & PY32F002B_EPPARA0_TS3_MASK);
288+
target_mem32_write32(flash->t, PUYA_FLASH_TS2P,
289+
(eppara1 >> PY32F002B_EPPARA1_TS2P_SHIFT) & PY32F002B_EPPARA1_TS2P_MASK);
290+
target_mem32_write32(flash->t, PUYA_FLASH_TPS3,
291+
(eppara1 >> PY32F002B_EPPARA1_TPS3_SHIFT) & PY32F002B_EPPARA1_TPS3_MASK);
292+
target_mem32_write32(flash->t, PUYA_FLASH_PERTPE,
293+
(eppara2 >> PY32F002B_EPPARA2_PERTPE_SHIFT) & PY32F002B_EPPARA2_PERTPE_MASK);
294+
target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE,
295+
(eppara3 >> PY32F002B_EPPARA3_SMERTPE_SHIFT) & PY32F002B_EPPARA3_SMERTPE_MASK);
296+
target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE,
297+
(eppara4 >> PY32F002B_EPPARA4_PRGTPE_SHIFT) & PY32F002B_EPPARA4_PRGTPE_MASK);
298+
target_mem32_write32(flash->t, PUYA_FLASH_PRETPE,
299+
(eppara4 >> PY32F002B_EPPARA4_PRETPE_SHIFT) & PY32F002B_EPPARA4_PRETPE_MASK);
300+
break;
301+
}
181302
return true;
182303
}
183304

0 commit comments

Comments
 (0)