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.
47+ *
48+ * The layout is very similar across devices. The start address differs and sometimes the entries are 64-bit aligned
49+ * rather than just 32-bit but otherwise the offsets are identical for entries that are present.
4750 */
48- #define PUYA_FLASH_TIMING_CAL_BASE 0x1fff0f1cU
51+ /* PY32F002A, PY32F003 */
52+ #define PUYA_TIMING_INFO_START_002A_003 0x1fff0f00u
53+
54+ /* PY32F002B (starting at page 2) */
55+ #define PUYA_TIMING_INFO_START_002B 0x1fff0100u
56+
57+ /* PY32[FM]07x */
58+ #define PUYA_TIMING_INFO_START_07X 0x1fff3200u
59+
60+ /* Start index for HSI_TRIM calibration values. */
61+ #define PUYA_FLASH_TIMING_HSITRIM_IDX 0x00U
62+
63+ /* Start index for EPPARA0…4 entries. */
64+ #define PUYA_FLASH_TIMING_EPPARA0_IDX 0x07U
65+
66+ /* PY32F002A, PY32F003 and PY32[FM]07x have the same layout. */
67+ #define PY32F0XX_EPPARA0_TS0_SHIFT 0U
68+ #define PY32F0XX_EPPARA0_TS0_MASK 0xffU
69+ #define PY32F0XX_EPPARA0_TS3_SHIFT 8U
70+ #define PY32F0XX_EPPARA0_TS3_MASK 0xffU
71+ #define PY32F0XX_EPPARA0_TS1_SHIFT 16U
72+ #define PY32F0XX_EPPARA0_TS1_MASK 0x1ffU
73+ #define PY32F0XX_EPPARA1_TS2P_SHIFT 0U
74+ #define PY32F0XX_EPPARA1_TS2P_MASK 0xffU
75+ #define PY32F0XX_EPPARA1_TPS3_SHIFT 16U
76+ #define PY32F0XX_EPPARA1_TPS3_MASK 0x7ffU
77+ #define PY32F0XX_EPPARA2_PERTPE_SHIFT 0U
78+ #define PY32F0XX_EPPARA2_PERTPE_MASK 0x1ffffU
79+ #define PY32F0XX_EPPARA3_SMERTPE_SHIFT 0U
80+ #define PY32F0XX_EPPARA3_SMERTPE_MASK 0x1ffffU
81+ #define PY32F0XX_EPPARA4_PRGTPE_SHIFT 0U
82+ #define PY32F0XX_EPPARA4_PRGTPE_MASK 0xffffU
83+ #define PY32F0XX_EPPARA4_PRETPE_SHIFT 16U
84+ /* The English version of PY32F002A Reference Manual says EPPARA4 26:16 (11 bit) are PRETPE[11:0] (12 bit) and
85+ * FLASH_PRETPE is 14 bit wide (0:13). However the Chinese version consistently has 14 bits for PRETPE everywhere and
86+ * that's also how the hardware behaves. */
87+ #define PY32F0XX_EPPARA4_PRETPE_MASK 0x3fffU
88+
89+ /* PY32F002B has a layout different from the other supported models. */
90+ #define PY32F002B_EPPARA0_TS0_SHIFT 0U
91+ #define PY32F002B_EPPARA0_TS0_MASK 0x1ffU
92+ #define PY32F002B_EPPARA0_TS3_SHIFT 9U
93+ #define PY32F002B_EPPARA0_TS3_MASK 0x1ffU
94+ #define PY32F002B_EPPARA0_TS1_SHIFT 18U
95+ #define PY32F002B_EPPARA0_TS1_MASK 0x3ffU
96+ #define PY32F002B_EPPARA1_TS2P_SHIFT 0U
97+ #define PY32F002B_EPPARA1_TS2P_MASK 0x1ffU
98+ #define PY32F002B_EPPARA1_TPS3_SHIFT 16U
99+ #define PY32F002B_EPPARA1_TPS3_MASK 0xfffU
100+ #define PY32F002B_EPPARA2_PERTPE_SHIFT 0U
101+ #define PY32F002B_EPPARA2_PERTPE_MASK 0x3ffffU
102+ #define PY32F002B_EPPARA3_SMERTPE_SHIFT 0U
103+ #define PY32F002B_EPPARA3_SMERTPE_MASK 0x3ffffU
104+ #define PY32F002B_EPPARA4_PRGTPE_SHIFT 0U
105+ #define PY32F002B_EPPARA4_PRGTPE_MASK 0xffffU
106+ #define PY32F002B_EPPARA4_PRETPE_SHIFT 16U
107+ #define PY32F002B_EPPARA4_PRETPE_MASK 0x3fffU
108+
49109/* This config word is undocumented, but the Puya-ISP boot code
50110 * uses it to determine the valid flash/ram size.
51111 * (yes, this *does* include undocumented free extra flash/ram in the 002A)
91151#define PUYA_RAM_START 0x20000000U
92152
93153/* RCC */
94- #define PUYA_RCC_BASE 0x40021000U
95- #define PUYA_RCC_ICSCR (PUYA_RCC_BASE + 0x04U)
96- #define PUYA_RCC_ICSCR_HSI_FS_SHIFT 13U
97- #define PUYA_RCC_ICSCR_HSI_FS_MASK 7U
154+ #define PUYA_RCC_BASE 0x40021000U
155+ #define PUYA_RCC_ICSCR (PUYA_RCC_BASE + 0x04U)
156+ #define PUYA_RCC_ICSCR_HSI_FS_SHIFT 13U
157+ #define PUYA_RCC_ICSCR_HSI_FS_MASK 7U
158+ #define PUYA_RCC_ICSCR_HSI_TRIM_SHIFT 0U
159+ #define PUYA_RCC_ICSCR_HSI_TRIM_MASK 0x1fffU
98160
99161/* DBG */
100162#define PUYA_DBG_BASE 0x40015800U
101163#define PUYA_DBG_IDCODE (PUYA_DBG_BASE + 0x00U)
164+ /*
165+ * The format and values of the IDCODE register are undocumented but the vendor SDK splits IDCODE into 11:0 DEV_ID and
166+ * 31:16 REV_ID.
167+ */
168+ #define PUYA_DBG_IDCODE_DEV_ID_SHIFT 0U
169+ #define PUYA_DBG_IDCODE_DEV_ID_MASK 0xfffU
170+ #define PUYA_DBG_IDCODE_REV_ID_SHIFT 16U
171+ #define PUYA_DBG_IDCODE_REV_ID_MASK 0xffffU
172+
173+ /*
174+ * Observed IDCODE (0x40015800) and FLASH_RAM_SZ (0x1fff0ffc) values:
175+ *
176+ * | Model | IDCODE | FLASH_RAM_SZ |
177+ * |---------------------------+------------+--------------|
178+ * | PY32F002AF15P6 | 0x60001000 | 0xffec0013 |
179+ * | PY32F002AL15S6 | 0x60001000 | 0xffec0013 |
180+ * | PY32F002AW15U? | 0x60001000 | ? |
181+ * | PY32F002BD15S6 | 0x20220064 | 0x00000000 |
182+ * | PY32F002BF15P6 | 0x20220064 | 0x00000000 |
183+ * | PY32F003L24D6 | 0x60001000 | 0xfffe0001 |
184+ * | PY32F030F18P6 | 0x60001000 | 0xffc80037 |
185+ * | PY32F030F38P6 | 0x60001000 | 0xffc80037 |
186+ * | PY32M070K1BU7-C | 0x06188061 | n/a |
187+ */
188+ /* PY32F002A, PY32F003, PY32F030 */
189+ #define PUYA_DEV_ID_PY32F0XX 0x000U
190+ #define PUYA_DEV_ID_PY32F002B 0x064U
191+ #define PUYA_DEV_ID_PY32X07X 0x061U
102192
103193/*
104194 * Flash functions
@@ -114,18 +204,40 @@ bool puya_probe(target_s *target)
114204 size_t flash_size = 0U ;
115205
116206 const uint32_t dbg_idcode = target_mem32_read32 (target , PUYA_DBG_IDCODE );
117- if ((dbg_idcode & 0xfffU ) == 0 ) {
207+ const uint16_t dev_id = (dbg_idcode >> PUYA_DBG_IDCODE_DEV_ID_SHIFT ) & PUYA_DBG_IDCODE_DEV_ID_MASK ;
208+ switch (dev_id ) {
209+ case PUYA_DEV_ID_PY32F0XX : {
118210 const uint32_t flash_ram_sz = target_mem32_read32 (target , PUYA_FLASH_RAM_SZ );
119211 flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT ) & PUYA_FLASH_SZ_MASK ) + 1 ) << PUYA_FLASH_UNIT_SHIFT ;
120212 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 {
213+ target -> driver = "PY32F0xx" ;
214+ break ;
215+ }
216+ case PUYA_DEV_ID_PY32F002B :
217+ /*
218+ * 0x1fff0ffc contains 0; did not find any other location that looks like it might contain the flash
219+ * and RAM sizes. We'll hard-code the datasheet values for now. Both flash size and RAM size actually
220+ * match the datasheet value, unlike PY32F002A which (sometimes?) has more RAM and flash than
221+ * documented.
222+ */
223+ flash_size = 24U * 1024U ;
224+ ram_size = 3U * 1024U ;
225+ target -> driver = "PY32F002B" ;
226+ break ;
227+ case PUYA_DEV_ID_PY32X07X :
228+ /* 0x1fff0ffc is in boot loader code. The vendor BSP references 0x1fff31fc as FLASHSIZE_BASE for
229+ * PY32[FM]07x but that location contains 0xffffffff on the PY32M070K1BU7. Hardcode the values for
230+ * now. */
231+ flash_size = 128U * 1024U ;
232+ ram_size = 16U * 1024U ;
233+ target -> driver = "PY32x07x" ;
234+ break ;
235+ default :
125236 DEBUG_TARGET ("Unknown PY32 device %08" PRIx32 "\n" , dbg_idcode );
126237 return false;
127238 }
128239
240+ target -> part_id = dev_id ;
129241 target_add_ram32 (target , PUYA_RAM_START , ram_size );
130242 target_flash_s * flash = calloc (1 , sizeof (* flash ));
131243 if (!flash ) { /* calloc failed: heap exhaustion */
@@ -151,33 +263,102 @@ static bool puya_flash_prepare(target_flash_s *flash)
151263 target_mem32_write32 (flash -> t , PUYA_FLASH_KEYR , PUYA_FLASH_KEYR_KEY1 );
152264 target_mem32_write32 (flash -> t , PUYA_FLASH_KEYR , PUYA_FLASH_KEYR_KEY2 );
153265
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 ;
266+ target_s * target = flash -> t ;
267+ uint32_t cal_base ;
268+ /* On most models the configuration "bytes" are 32-bit aligned. Exceptions (64-bit alignment) are handled
269+ * below. */
270+ uint8_t cal_shift = 2 ;
271+
272+ switch (target -> part_id ) {
273+ case PUYA_DEV_ID_PY32F0XX : {
274+ cal_base = PUYA_TIMING_INFO_START_002A_003 ;
275+ break ;
276+ }
277+ case PUYA_DEV_ID_PY32F002B :
278+ cal_base = PUYA_TIMING_INFO_START_002B ;
279+ break ;
280+ case PUYA_DEV_ID_PY32X07X :
281+ cal_base = PUYA_TIMING_INFO_START_07X ;
282+ /* configuration bytes are 64-bit aligned rather than just 32-bit */
283+ cal_shift = 3 ;
284+ break ;
285+ default :
286+ /* Should have never made it past probe */
287+ DEBUG_TARGET ("Unknown PY32 device %08" PRIx32 "\n" , target -> part_id );
288+ return false;
289+ }
290+
291+ const uint32_t icscr_old = target_mem32_read32 (flash -> t , PUYA_RCC_ICSCR );
292+ /* Not all models support all frequencies but the mapping is
293+ * the same for all of them. */
294+ uint8_t hsi_fs = (icscr_old >> PUYA_RCC_ICSCR_HSI_FS_SHIFT ) & PUYA_RCC_ICSCR_HSI_FS_MASK ;
156295 if (hsi_fs > 4 )
157296 hsi_fs = 0 ;
297+ if (target -> part_id == PUYA_DEV_ID_PY32F002B ) {
298+ /* PY32F002B only supports 24MHz HSI. The HSI_TRIM and EPPARA0 entries for 24MHz are at offset 0,
299+ * disregarding the HSI_FS value. */
300+ hsi_fs = 0 ;
301+ }
158302 DEBUG_TARGET ("HSI frequency selection is %d\n" , hsi_fs );
159303
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 );
165- DEBUG_TARGET ("PY32 flash timing cal 0: %08" PRIx32 "\n" , eppara0 );
166- DEBUG_TARGET ("PY32 flash timing cal 1: %08" PRIx32 "\n" , eppara1 );
167- DEBUG_TARGET ("PY32 flash timing cal 2: %08" PRIx32 "\n" , eppara2 );
168- DEBUG_TARGET ("PY32 flash timing cal 3: %08" PRIx32 "\n" , eppara3 );
169- DEBUG_TARGET ("PY32 flash timing cal 4: %08" PRIx32 "\n" , eppara4 );
170-
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 );
304+ const uint32_t hsi_trim =
305+ target_mem32_read32 (flash -> t , cal_base + ((PUYA_FLASH_TIMING_HSITRIM_IDX + (hsi_fs * 5 ) + 0 ) << cal_shift ));
306+ uint32_t eppara [5 ];
307+ for (uint32_t idx = 0 ; idx < 5 ; idx ++ ) {
308+ eppara [idx ] = target_mem32_read32 (
309+ flash -> t , cal_base + ((PUYA_FLASH_TIMING_EPPARA0_IDX + (hsi_fs * 5 ) + idx ) << cal_shift ));
310+ }
311+ DEBUG_TARGET ("PY32 HSI trim value: %08" PRIx32 "\n" , hsi_trim );
312+ DEBUG_TARGET ("PY32 flash timing cal 0: %08" PRIx32 "\n" , eppara [0 ]);
313+ DEBUG_TARGET ("PY32 flash timing cal 1: %08" PRIx32 "\n" , eppara [1 ]);
314+ DEBUG_TARGET ("PY32 flash timing cal 2: %08" PRIx32 "\n" , eppara [2 ]);
315+ DEBUG_TARGET ("PY32 flash timing cal 3: %08" PRIx32 "\n" , eppara [3 ]);
316+ DEBUG_TARGET ("PY32 flash timing cal 4: %08" PRIx32 "\n" , eppara [4 ]);
180317
318+ target_mem32_write32 (flash -> t , PUYA_RCC_ICSCR ,
319+ (icscr_old & ~PUYA_RCC_ICSCR_HSI_TRIM_MASK ) | (hsi_trim & PUYA_RCC_ICSCR_HSI_TRIM_MASK ));
320+ switch (target -> part_id ) {
321+ case PUYA_DEV_ID_PY32F002B :
322+ target_mem32_write32 (
323+ flash -> t , PUYA_FLASH_TS0 , (eppara [0 ] >> PY32F002B_EPPARA0_TS0_SHIFT ) & PY32F002B_EPPARA0_TS0_MASK );
324+ target_mem32_write32 (
325+ flash -> t , PUYA_FLASH_TS1 , (eppara [0 ] >> PY32F002B_EPPARA0_TS1_SHIFT ) & PY32F002B_EPPARA0_TS1_MASK );
326+ target_mem32_write32 (
327+ flash -> t , PUYA_FLASH_TS3 , (eppara [0 ] >> PY32F002B_EPPARA0_TS3_SHIFT ) & PY32F002B_EPPARA0_TS3_MASK );
328+ target_mem32_write32 (
329+ flash -> t , PUYA_FLASH_TS2P , (eppara [1 ] >> PY32F002B_EPPARA1_TS2P_SHIFT ) & PY32F002B_EPPARA1_TS2P_MASK );
330+ target_mem32_write32 (
331+ flash -> t , PUYA_FLASH_TPS3 , (eppara [1 ] >> PY32F002B_EPPARA1_TPS3_SHIFT ) & PY32F002B_EPPARA1_TPS3_MASK );
332+ target_mem32_write32 (
333+ flash -> t , PUYA_FLASH_PERTPE , (eppara [2 ] >> PY32F002B_EPPARA2_PERTPE_SHIFT ) & PY32F002B_EPPARA2_PERTPE_MASK );
334+ target_mem32_write32 (flash -> t , PUYA_FLASH_SMERTPE ,
335+ (eppara [3 ] >> PY32F002B_EPPARA3_SMERTPE_SHIFT ) & PY32F002B_EPPARA3_SMERTPE_MASK );
336+ target_mem32_write32 (
337+ flash -> t , PUYA_FLASH_PRGTPE , (eppara [4 ] >> PY32F002B_EPPARA4_PRGTPE_SHIFT ) & PY32F002B_EPPARA4_PRGTPE_MASK );
338+ target_mem32_write32 (
339+ flash -> t , PUYA_FLASH_PRETPE , (eppara [4 ] >> PY32F002B_EPPARA4_PRETPE_SHIFT ) & PY32F002B_EPPARA4_PRETPE_MASK );
340+ break ;
341+ default :
342+ target_mem32_write32 (
343+ flash -> t , PUYA_FLASH_TS0 , (eppara [0 ] >> PY32F0XX_EPPARA0_TS0_SHIFT ) & PY32F0XX_EPPARA0_TS0_MASK );
344+ target_mem32_write32 (
345+ flash -> t , PUYA_FLASH_TS1 , (eppara [0 ] >> PY32F0XX_EPPARA0_TS1_SHIFT ) & PY32F0XX_EPPARA0_TS1_MASK );
346+ target_mem32_write32 (
347+ flash -> t , PUYA_FLASH_TS3 , (eppara [0 ] >> PY32F0XX_EPPARA0_TS3_SHIFT ) & PY32F0XX_EPPARA0_TS3_MASK );
348+ target_mem32_write32 (
349+ flash -> t , PUYA_FLASH_TS2P , (eppara [1 ] >> PY32F0XX_EPPARA1_TS2P_SHIFT ) & PY32F0XX_EPPARA1_TS2P_MASK );
350+ target_mem32_write32 (
351+ flash -> t , PUYA_FLASH_TPS3 , (eppara [1 ] >> PY32F0XX_EPPARA1_TPS3_SHIFT ) & PY32F0XX_EPPARA1_TPS3_MASK );
352+ target_mem32_write32 (
353+ flash -> t , PUYA_FLASH_PERTPE , (eppara [2 ] >> PY32F0XX_EPPARA2_PERTPE_SHIFT ) & PY32F0XX_EPPARA2_PERTPE_MASK );
354+ target_mem32_write32 (flash -> t , PUYA_FLASH_SMERTPE ,
355+ (eppara [3 ] >> PY32F0XX_EPPARA3_SMERTPE_SHIFT ) & PY32F0XX_EPPARA3_SMERTPE_MASK );
356+ target_mem32_write32 (
357+ flash -> t , PUYA_FLASH_PRGTPE , (eppara [4 ] >> PY32F0XX_EPPARA4_PRGTPE_SHIFT ) & PY32F0XX_EPPARA4_PRGTPE_MASK );
358+ target_mem32_write32 (
359+ flash -> t , PUYA_FLASH_PRETPE , (eppara [4 ] >> PY32F0XX_EPPARA4_PRETPE_SHIFT ) & PY32F0XX_EPPARA4_PRETPE_MASK );
360+ break ;
361+ }
181362 return true;
182363}
183364
0 commit comments