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+ /* This one is a bit of a mess. The PY32F002A Reference Manual says EPPARA4 26:16 (11 bit) are PRETPE[11:0] (12
85+ * bit). FLASH_PRETPE is 14 bit wide (0:13) and must be initialised from the value in EPPARA4. The non-PY32F002B flash
86+ * drivers (Flash/{PY32F0xx,PY32F031xx,PY32F072xx}/FlashPrg.c) contained in the Keil Device Family Pack v1.2.1 provided
87+ * by Puya stores the full upper 16 bits of EPPARA4 into FLASH_PRETPE. Presumably the reserved bits are 0. We use the
88+ * width of FLASH_PRETPE (14 bits) for now. */
89+ #define PY32F0XX_EPPARA4_PRETPE_MASK 0x3fffU
90+
91+ /* PY32F002B has a layout different from the other supported models. */
92+ #define PY32F002B_EPPARA0_TS0_SHIFT 0U
93+ #define PY32F002B_EPPARA0_TS0_MASK 0x1ffU
94+ #define PY32F002B_EPPARA0_TS3_SHIFT 9U
95+ #define PY32F002B_EPPARA0_TS3_MASK 0x1ffU
96+ #define PY32F002B_EPPARA0_TS1_SHIFT 18U
97+ #define PY32F002B_EPPARA0_TS1_MASK 0x3ffU
98+ #define PY32F002B_EPPARA1_TS2P_SHIFT 0U
99+ #define PY32F002B_EPPARA1_TS2P_MASK 0x1ffU
100+ #define PY32F002B_EPPARA1_TPS3_SHIFT 16U
101+ #define PY32F002B_EPPARA1_TPS3_MASK 0xfffU
102+ #define PY32F002B_EPPARA2_PERTPE_SHIFT 0U
103+ #define PY32F002B_EPPARA2_PERTPE_MASK 0x3ffffU
104+ #define PY32F002B_EPPARA3_SMERTPE_SHIFT 0U
105+ #define PY32F002B_EPPARA3_SMERTPE_MASK 0x3ffffU
106+ #define PY32F002B_EPPARA4_PRGTPE_SHIFT 0U
107+ #define PY32F002B_EPPARA4_PRGTPE_MASK 0xffffU
108+ #define PY32F002B_EPPARA4_PRETPE_SHIFT 16U
109+ #define PY32F002B_EPPARA4_PRETPE_MASK 0x3fffU
110+
49111/* This config word is undocumented, but the Puya-ISP boot code
50112 * uses it to determine the valid flash/ram size.
51113 * (yes, this *does* include undocumented free extra flash/ram in the 002A)
91153#define PUYA_RAM_START 0x20000000U
92154
93155/* 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
156+ #define PUYA_RCC_BASE 0x40021000U
157+ #define PUYA_RCC_ICSCR (PUYA_RCC_BASE + 0x04U)
158+ #define PUYA_RCC_ICSCR_HSI_FS_SHIFT 13U
159+ #define PUYA_RCC_ICSCR_HSI_FS_MASK 7U
160+ #define PUYA_RCC_ICSCR_HSI_TRIM_SHIFT 0U
161+ #define PUYA_RCC_ICSCR_HSI_TRIM_MASK 0x1fffU
98162
99163/* DBG */
100164#define PUYA_DBG_BASE 0x40015800U
101165#define PUYA_DBG_IDCODE (PUYA_DBG_BASE + 0x00U)
166+ /*
167+ * The format and values of the IDCODE register are undocumented but the vendor SDK splits IDCODE into 11:0 DEV_ID and
168+ * 31:16 REV_ID.
169+ */
170+ #define PUYA_DBG_IDCODE_DEV_ID_SHIFT 0U
171+ #define PUYA_DBG_IDCODE_DEV_ID_MASK 0xfffU
172+ #define PUYA_DBG_IDCODE_REV_ID_SHIFT 16U
173+ #define PUYA_DBG_IDCODE_REV_ID_MASK 0xffffU
174+
175+ /*
176+ * Observed IDCODE (0x40015800) and FLASH_RAM_SZ (0x1fff0ffc) values:
177+ *
178+ * | Model | IDCODE | FLASH_RAM_SZ |
179+ * |---------------------------+------------+--------------|
180+ * | PY32F002AF15P6 | 0x60001000 | 0xffec0013 |
181+ * | PY32F002AL15S6 | 0x60001000 | 0xffec0013 |
182+ * | PY32F002AW15U? | 0x60001000 | ? |
183+ * | PY32F002BD15S6 | 0x20220064 | 0x00000000 |
184+ * | PY32F002BF15P6 | 0x20220064 | 0x00000000 |
185+ * | PY32F003L24D6 | 0x60001000 | 0xfffe0001 |
186+ * | PY32F030F18P6 | 0x60001000 | 0xffc80037 |
187+ * | PY32F030F38P6 | 0x60001000 | 0xffc80037 |
188+ * | PY32M070K1BU7-C | 0x06188061 | n/a |
189+ */
190+ /* PY32F002A, PY32F003, PY32F030 */
191+ #define PUYA_DEV_ID_PY32F0XX 0x000U
192+ #define PUYA_DEV_ID_PY32F002B 0x064U
193+ #define PUYA_DEV_ID_PY32X07X 0x061U
102194
103195/*
104196 * Flash functions
@@ -114,18 +206,40 @@ bool puya_probe(target_s *target)
114206 size_t flash_size = 0U ;
115207
116208 const uint32_t dbg_idcode = target_mem32_read32 (target , PUYA_DBG_IDCODE );
117- if ((dbg_idcode & 0xfffU ) == 0 ) {
209+ const uint16_t dev_id = (dbg_idcode >> PUYA_DBG_IDCODE_DEV_ID_SHIFT ) & PUYA_DBG_IDCODE_DEV_ID_MASK ;
210+ switch (dev_id ) {
211+ case PUYA_DEV_ID_PY32F0XX : {
118212 const uint32_t flash_ram_sz = target_mem32_read32 (target , PUYA_FLASH_RAM_SZ );
119213 flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT ) & PUYA_FLASH_SZ_MASK ) + 1 ) << PUYA_FLASH_UNIT_SHIFT ;
120214 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 {
215+ target -> driver = "PY32F0xx" ;
216+ break ;
217+ }
218+ case PUYA_DEV_ID_PY32F002B :
219+ /*
220+ * 0x1fff0ffc contains 0; did not find any other location that looks like it might contain the flash
221+ * and RAM sizes. We'll hard-code the datasheet values for now. Both flash size and RAM size actually
222+ * match the datasheet value, unlike PY32F002A which (sometimes?) has more RAM and flash than
223+ * documented.
224+ */
225+ flash_size = 24U * 1024U ;
226+ ram_size = 3U * 1024U ;
227+ target -> driver = "PY32F002B" ;
228+ break ;
229+ case PUYA_DEV_ID_PY32X07X :
230+ /* 0x1fff0ffc is in boot loader code. The vendor BSP references 0x1fff31fc as FLASHSIZE_BASE for
231+ * PY32[FM]07x but that location contains 0xffffffff on the PY32M070K1BU7. Hardcode the values for
232+ * now. */
233+ flash_size = 128U * 1024U ;
234+ ram_size = 16U * 1024U ;
235+ target -> driver = "PY32x07x" ;
236+ break ;
237+ default :
125238 DEBUG_TARGET ("Unknown PY32 device %08" PRIx32 "\n" , dbg_idcode );
126239 return false;
127240 }
128241
242+ target -> part_id = dev_id ;
129243 target_add_ram32 (target , PUYA_RAM_START , ram_size );
130244 target_flash_s * flash = calloc (1 , sizeof (* flash ));
131245 if (!flash ) { /* calloc failed: heap exhaustion */
@@ -151,33 +265,102 @@ static bool puya_flash_prepare(target_flash_s *flash)
151265 target_mem32_write32 (flash -> t , PUYA_FLASH_KEYR , PUYA_FLASH_KEYR_KEY1 );
152266 target_mem32_write32 (flash -> t , PUYA_FLASH_KEYR , PUYA_FLASH_KEYR_KEY2 );
153267
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 ;
268+ target_s * target = flash -> t ;
269+ uint32_t cal_base ;
270+ /* On most models the configuration "bytes" are 32-bit aligned. Exceptions (64-bit alignment) are handled
271+ * below. */
272+ uint8_t cal_shift = 2 ;
273+
274+ switch (target -> part_id ) {
275+ case PUYA_DEV_ID_PY32F0XX : {
276+ cal_base = PUYA_TIMING_INFO_START_002A_003 ;
277+ break ;
278+ }
279+ case PUYA_DEV_ID_PY32F002B :
280+ cal_base = PUYA_TIMING_INFO_START_002B ;
281+ break ;
282+ case PUYA_DEV_ID_PY32X07X :
283+ cal_base = PUYA_TIMING_INFO_START_07X ;
284+ /* configuration bytes are 64-bit aligned rather than just 32-bit */
285+ cal_shift = 3 ;
286+ break ;
287+ default :
288+ /* Should have never made it past probe */
289+ DEBUG_TARGET ("Unknown PY32 device %08" PRIx32 "\n" , target -> part_id );
290+ return false;
291+ }
292+
293+ const uint32_t icscr_old = target_mem32_read32 (flash -> t , PUYA_RCC_ICSCR );
294+ /* Not all models support all frequencies but the mapping is
295+ * the same for all of them. */
296+ uint8_t hsi_fs = (icscr_old >> PUYA_RCC_ICSCR_HSI_FS_SHIFT ) & PUYA_RCC_ICSCR_HSI_FS_MASK ;
156297 if (hsi_fs > 4 )
157298 hsi_fs = 0 ;
299+ if (target -> part_id == PUYA_DEV_ID_PY32F002B ) {
300+ /* PY32F002B only supports 24MHz HSI. The HSI_TRIM and EPPARA0 entries for 24MHz are at offset 0,
301+ * disregarding the HSI_FS value. */
302+ hsi_fs = 0 ;
303+ }
158304 DEBUG_TARGET ("HSI frequency selection is %d\n" , hsi_fs );
159305
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 );
306+ const uint32_t hsi_trim =
307+ target_mem32_read32 (flash -> t , cal_base + ((PUYA_FLASH_TIMING_HSITRIM_IDX + (hsi_fs * 5 ) + 0 ) << cal_shift ));
308+ uint32_t eppara [5 ];
309+ for (uint32_t idx = 0 ; idx < 5 ; idx ++ ) {
310+ eppara [idx ] = target_mem32_read32 (
311+ flash -> t , cal_base + ((PUYA_FLASH_TIMING_EPPARA0_IDX + (hsi_fs * 5 ) + idx ) << cal_shift ));
312+ }
313+ DEBUG_TARGET ("PY32 HSI trim value: %08" PRIx32 "\n" , hsi_trim );
314+ DEBUG_TARGET ("PY32 flash timing cal 0: %08" PRIx32 "\n" , eppara [0 ]);
315+ DEBUG_TARGET ("PY32 flash timing cal 1: %08" PRIx32 "\n" , eppara [1 ]);
316+ DEBUG_TARGET ("PY32 flash timing cal 2: %08" PRIx32 "\n" , eppara [2 ]);
317+ DEBUG_TARGET ("PY32 flash timing cal 3: %08" PRIx32 "\n" , eppara [3 ]);
318+ DEBUG_TARGET ("PY32 flash timing cal 4: %08" PRIx32 "\n" , eppara [4 ]);
180319
320+ target_mem32_write32 (flash -> t , PUYA_RCC_ICSCR ,
321+ (icscr_old & ~PUYA_RCC_ICSCR_HSI_TRIM_MASK ) | (hsi_trim & PUYA_RCC_ICSCR_HSI_TRIM_MASK ));
322+ switch (target -> part_id ) {
323+ case PUYA_DEV_ID_PY32F002B :
324+ target_mem32_write32 (
325+ flash -> t , PUYA_FLASH_TS0 , (eppara [0 ] >> PY32F002B_EPPARA0_TS0_SHIFT ) & PY32F002B_EPPARA0_TS0_MASK );
326+ target_mem32_write32 (
327+ flash -> t , PUYA_FLASH_TS1 , (eppara [0 ] >> PY32F002B_EPPARA0_TS1_SHIFT ) & PY32F002B_EPPARA0_TS1_MASK );
328+ target_mem32_write32 (
329+ flash -> t , PUYA_FLASH_TS3 , (eppara [0 ] >> PY32F002B_EPPARA0_TS3_SHIFT ) & PY32F002B_EPPARA0_TS3_MASK );
330+ target_mem32_write32 (
331+ flash -> t , PUYA_FLASH_TS2P , (eppara [1 ] >> PY32F002B_EPPARA1_TS2P_SHIFT ) & PY32F002B_EPPARA1_TS2P_MASK );
332+ target_mem32_write32 (
333+ flash -> t , PUYA_FLASH_TPS3 , (eppara [1 ] >> PY32F002B_EPPARA1_TPS3_SHIFT ) & PY32F002B_EPPARA1_TPS3_MASK );
334+ target_mem32_write32 (
335+ flash -> t , PUYA_FLASH_PERTPE , (eppara [2 ] >> PY32F002B_EPPARA2_PERTPE_SHIFT ) & PY32F002B_EPPARA2_PERTPE_MASK );
336+ target_mem32_write32 (flash -> t , PUYA_FLASH_SMERTPE ,
337+ (eppara [3 ] >> PY32F002B_EPPARA3_SMERTPE_SHIFT ) & PY32F002B_EPPARA3_SMERTPE_MASK );
338+ target_mem32_write32 (
339+ flash -> t , PUYA_FLASH_PRGTPE , (eppara [4 ] >> PY32F002B_EPPARA4_PRGTPE_SHIFT ) & PY32F002B_EPPARA4_PRGTPE_MASK );
340+ target_mem32_write32 (
341+ flash -> t , PUYA_FLASH_PRETPE , (eppara [4 ] >> PY32F002B_EPPARA4_PRETPE_SHIFT ) & PY32F002B_EPPARA4_PRETPE_MASK );
342+ break ;
343+ default :
344+ target_mem32_write32 (
345+ flash -> t , PUYA_FLASH_TS0 , (eppara [0 ] >> PY32F0XX_EPPARA0_TS0_SHIFT ) & PY32F0XX_EPPARA0_TS0_MASK );
346+ target_mem32_write32 (
347+ flash -> t , PUYA_FLASH_TS1 , (eppara [0 ] >> PY32F0XX_EPPARA0_TS1_SHIFT ) & PY32F0XX_EPPARA0_TS1_MASK );
348+ target_mem32_write32 (
349+ flash -> t , PUYA_FLASH_TS3 , (eppara [0 ] >> PY32F0XX_EPPARA0_TS3_SHIFT ) & PY32F0XX_EPPARA0_TS3_MASK );
350+ target_mem32_write32 (
351+ flash -> t , PUYA_FLASH_TS2P , (eppara [1 ] >> PY32F0XX_EPPARA1_TS2P_SHIFT ) & PY32F0XX_EPPARA1_TS2P_MASK );
352+ target_mem32_write32 (
353+ flash -> t , PUYA_FLASH_TPS3 , (eppara [1 ] >> PY32F0XX_EPPARA1_TPS3_SHIFT ) & PY32F0XX_EPPARA1_TPS3_MASK );
354+ target_mem32_write32 (
355+ flash -> t , PUYA_FLASH_PERTPE , (eppara [2 ] >> PY32F0XX_EPPARA2_PERTPE_SHIFT ) & PY32F0XX_EPPARA2_PERTPE_MASK );
356+ target_mem32_write32 (flash -> t , PUYA_FLASH_SMERTPE ,
357+ (eppara [3 ] >> PY32F0XX_EPPARA3_SMERTPE_SHIFT ) & PY32F0XX_EPPARA3_SMERTPE_MASK );
358+ target_mem32_write32 (
359+ flash -> t , PUYA_FLASH_PRGTPE , (eppara [4 ] >> PY32F0XX_EPPARA4_PRGTPE_SHIFT ) & PY32F0XX_EPPARA4_PRGTPE_MASK );
360+ target_mem32_write32 (
361+ flash -> t , PUYA_FLASH_PRETPE , (eppara [4 ] >> PY32F0XX_EPPARA4_PRETPE_SHIFT ) & PY32F0XX_EPPARA4_PRETPE_MASK );
362+ break ;
363+ }
181364 return true;
182365}
183366
0 commit comments