Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit c104489

Browse files
committed
puya: add support for Puya PY32F07x flash
1 parent 0a7901e commit c104489

1 file changed

Lines changed: 86 additions & 26 deletions

File tree

src/target/puya.c

Lines changed: 86 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,25 @@
3939
#include "buffer_utils.h"
4040

4141
/* Flash */
42-
#define PUYA_FLASH_START 0x08000000U
43-
#define PUYA_FLASH_PAGE_SIZE 128
42+
#define PUYA_FLASH_START 0x08000000U
43+
#define PUYA_00A_FLASH_PAGE_SIZE 128
44+
#define PUYA_07X_FLASH_PAGE_SIZE 256
4445

4546
/* Pile of timing parameters needed to make sure flash works,
4647
* see section "4.4. Flash configuration bytes" of the RM.
4748
*/
48-
#define PUYA_FLASH_TIMING_CAL_BASE 0x1fff0f1cU
49+
#define PUYA_00A_FLASH_TIMING_CAL_BASE 0x1fff0f1cU
50+
4951
/* This config word is undocumented, but the Puya-ISP boot code
5052
* uses it to determine the valid flash/ram size.
5153
* (yes, this *does* include undocumented free extra flash/ram in the 002A)
5254
*
5355
* bits[2:0] => flash size in multiples of 0x2000 bytes, minus 1
5456
* bits[5:4] => RAM size in multiples of 0x800 bytes, minus 1
5557
*/
56-
#define PUYA_FLASH_RAM_SZ 0x1fff0ffcU
58+
#define PUYA_00A_FLASH_RAM_SZ 0x1fff0ffcU
59+
#define PUYA_07X_FLASH_RAM_SZ 0x1FFF31FCU
60+
5761
#define PUYA_FLASH_SZ_SHIFT 0U
5862
#define PUYA_FLASH_SZ_MASK 7U
5963
#define PUYA_FLASH_UNIT_SHIFT 13U
@@ -105,7 +109,8 @@
105109
*/
106110
static bool puya_flash_erase(target_flash_s *flash, target_addr_t addr, size_t len);
107111
static bool puya_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t len);
108-
static bool puya_flash_prepare(target_flash_s *flash);
112+
static bool puya_00a_flash_prepare(target_flash_s *flash);
113+
static bool puya_07x_flash_prepare(target_flash_s *flash);
109114
static bool puya_flash_done(target_flash_s *flash);
110115

111116
bool puya_probe(target_s *target)
@@ -114,39 +119,52 @@ bool puya_probe(target_s *target)
114119
size_t flash_size = 0U;
115120

116121
const uint32_t dbg_idcode = target_mem32_read32(target, PUYA_DBG_IDCODE);
117-
if ((dbg_idcode & 0xfffU) == 0) {
118-
const uint32_t flash_ram_sz = target_mem32_read32(target, PUYA_FLASH_RAM_SZ);
122+
if (dbg_idcode == 0x06188061U) {
123+
const uint32_t flash_ram_sz = target_mem32_read32(target, PUYA_07X_FLASH_RAM_SZ);
124+
flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT) & PUYA_FLASH_SZ_MASK) + 1) << PUYA_FLASH_UNIT_SHIFT;
125+
ram_size = (((flash_ram_sz >> PUYA_RAM_SZ_SHIFT) & PUYA_RAM_SZ_MASK) + 1) << PUYA_RAM_UNIT_SHIFT;
126+
target->driver = "PY32F07x";
127+
target_add_ram32(target, PUYA_RAM_START, 0x4000);
128+
} else if ((dbg_idcode & 0xfffU) == 0) {
129+
const uint32_t flash_ram_sz = target_mem32_read32(target, PUYA_00A_FLASH_RAM_SZ);
119130
flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT) & PUYA_FLASH_SZ_MASK) + 1) << PUYA_FLASH_UNIT_SHIFT;
120131
ram_size = (((flash_ram_sz >> PUYA_RAM_SZ_SHIFT) & PUYA_RAM_SZ_MASK) + 1) << PUYA_RAM_UNIT_SHIFT;
121132
// TODO: which part families does this actually correspond to?
122133
// Tested with a PY32F002AW15U which returns 0x60001000 in IDCODE
123134
target->driver = "PY32Fxxx";
135+
target_add_ram32(target, PUYA_RAM_START, ram_size);
124136
} else {
125137
DEBUG_TARGET("Unknown PY32 device %08" PRIx32 "\n", dbg_idcode);
126138
return false;
127139
}
128140

129-
target_add_ram32(target, PUYA_RAM_START, ram_size);
130141
target_flash_s *flash = calloc(1, sizeof(*flash));
131142
if (!flash) { /* calloc failed: heap exhaustion */
132143
DEBUG_ERROR("calloc: failed in %s\n", __func__);
133144
return false;
134145
}
146+
135147
flash->start = PUYA_FLASH_START;
136148
flash->length = flash_size;
137-
flash->blocksize = PUYA_FLASH_PAGE_SIZE;
138-
flash->writesize = PUYA_FLASH_PAGE_SIZE;
139149
flash->erase = puya_flash_erase;
140150
flash->write = puya_flash_write;
141-
flash->prepare = puya_flash_prepare;
151+
if (dbg_idcode == 0x06188061U) {
152+
flash->blocksize = PUYA_07X_FLASH_PAGE_SIZE;
153+
flash->writesize = PUYA_07X_FLASH_PAGE_SIZE;
154+
flash->prepare = puya_07x_flash_prepare;
155+
} else {
156+
flash->blocksize = PUYA_00A_FLASH_PAGE_SIZE;
157+
flash->writesize = PUYA_00A_FLASH_PAGE_SIZE;
158+
flash->prepare = puya_00a_flash_prepare;
159+
}
142160
flash->done = puya_flash_done;
143161
flash->erased = 0xffU;
144162
target_add_flash(target, flash);
145163

146164
return true;
147165
}
148166

149-
static bool puya_flash_prepare(target_flash_s *flash)
167+
static bool puya_00a_flash_prepare(target_flash_s *flash)
150168
{
151169
target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY1);
152170
target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY2);
@@ -157,20 +175,62 @@ static bool puya_flash_prepare(target_flash_s *flash)
157175
hsi_fs = 0;
158176
DEBUG_TARGET("HSI frequency selection is %d\n", hsi_fs);
159177

160-
uint32_t eppara[5] = {0};
161-
for (uint16_t i = 0; i < 5; i++) {
162-
eppara[i] = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + i * 4U);
163-
DEBUG_TARGET("PY32 flash timing cal %u: %08" PRIx32 "\n", i, eppara[i]);
164-
}
165-
target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara[0] & 0xffU);
166-
target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara[0] >> 16U) & 0x1ffU);
167-
target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara[0] >> 8U) & 0xffU);
168-
target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara[1] & 0xffU);
169-
target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara[1] >> 16U) & 0x7ffU);
170-
target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara[2] & 0x1ffffU);
171-
target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara[3] & 0x1ffffU);
172-
target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara[4] & 0xffffU);
173-
target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara[4] >> 16U) & 0x3fffU);
178+
const uint32_t eppara0 = target_mem32_read32(flash->t, PUYA_00A_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 0);
179+
const uint32_t eppara1 = target_mem32_read32(flash->t, PUYA_00A_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 4);
180+
const uint32_t eppara2 = target_mem32_read32(flash->t, PUYA_00A_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 8);
181+
const uint32_t eppara3 = target_mem32_read32(flash->t, PUYA_00A_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 12);
182+
const uint32_t eppara4 = target_mem32_read32(flash->t, PUYA_00A_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 16);
183+
DEBUG_TARGET("PY32 flash timing cal 0: %08" PRIx32 "\n", eppara0);
184+
DEBUG_TARGET("PY32 flash timing cal 1: %08" PRIx32 "\n", eppara1);
185+
DEBUG_TARGET("PY32 flash timing cal 2: %08" PRIx32 "\n", eppara2);
186+
DEBUG_TARGET("PY32 flash timing cal 3: %08" PRIx32 "\n", eppara3);
187+
DEBUG_TARGET("PY32 flash timing cal 4: %08" PRIx32 "\n", eppara4);
188+
189+
target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara0 & 0xffU);
190+
target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara0 >> 16U) & 0x1ffU);
191+
target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara0 >> 8U) & 0xffU);
192+
target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara1 & 0xffU);
193+
target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara1 >> 16U) & 0x7ffU);
194+
target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara2 & 0x1ffffU);
195+
target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara3 & 0x1ffffU);
196+
target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara4 & 0xffffU);
197+
target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara4 >> 16U) & 0x3fffU);
198+
199+
return true;
200+
}
201+
202+
static bool puya_07x_flash_prepare(target_flash_s *flash)
203+
{
204+
target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY1);
205+
target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY2);
206+
207+
uint8_t hsi_fs =
208+
(target_mem32_read32(flash->t, PUYA_RCC_ICSCR) >> PUYA_RCC_ICSCR_HSI_FS_SHIFT) & PUYA_RCC_ICSCR_HSI_FS_MASK;
209+
if (hsi_fs > 4)
210+
hsi_fs = 0;
211+
DEBUG_TARGET("HSI frequency selection is %d\n", hsi_fs);
212+
213+
const uint32_t eppara0 = target_mem32_read32(flash->t, 0x1FFF3238 + 4 * 0x28);
214+
const uint32_t eppara1 = target_mem32_read32(flash->t, 0x1FFF3240 + 4 * 0x28);
215+
const uint32_t eppara2 = target_mem32_read32(flash->t, 0x1FFF3248 + 4 * 0x28);
216+
const uint32_t eppara3 = target_mem32_read32(flash->t, 0x1FFF3250 + 4 * 0x28);
217+
const uint32_t eppara4 = target_mem32_read32(flash->t, 0x1FFF3258 + 4 * 0x28);
218+
219+
DEBUG_TARGET("PY32 flash timing cal 0: %08" PRIx32 "\n", eppara0);
220+
DEBUG_TARGET("PY32 flash timing cal 1: %08" PRIx32 "\n", eppara1);
221+
DEBUG_TARGET("PY32 flash timing cal 2: %08" PRIx32 "\n", eppara2);
222+
DEBUG_TARGET("PY32 flash timing cal 3: %08" PRIx32 "\n", eppara3);
223+
DEBUG_TARGET("PY32 flash timing cal 4: %08" PRIx32 "\n", eppara4);
224+
225+
target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara0 & 0xffU);
226+
target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara0 >> 16U) & 0x1ffU);
227+
target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara0 >> 8U) & 0xffU);
228+
target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara1 & 0xffU);
229+
target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara1 >> 16U) & 0x7ffU);
230+
target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara2 & 0x1ffffU);
231+
target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara3 & 0x1ffffU);
232+
target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara4 & 0xffffU);
233+
target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara4 >> 16U) & 0xFFFFU); // diff
174234

175235
return true;
176236
}

0 commit comments

Comments
 (0)