diff --git a/src/target/puya.c b/src/target/puya.c index 236bbe0ff6c..c821d7146ac 100644 --- a/src/target/puya.c +++ b/src/target/puya.c @@ -45,7 +45,8 @@ /* Pile of timing parameters needed to make sure flash works, * see section "4.4. Flash configuration bytes" of the RM. */ -#define PUYA_FLASH_TIMING_CAL_BASE 0x1fff0f1cU +#define PUYA_FLASH_TIMING_CAL_PY32F002A_BASE 0x1fff0f1cU +#define PUYA_FLASH_TIMING_CAL_PY32F002B_BASE 0x1fff011cU /* This config word is undocumented, but the Puya-ISP boot code * uses it to determine the valid flash/ram size. * (yes, this *does* include undocumented free extra flash/ram in the 002A) @@ -99,6 +100,22 @@ /* DBG */ #define PUYA_DBG_BASE 0x40015800U #define PUYA_DBG_IDCODE (PUYA_DBG_BASE + 0x00U) +/* + * The format and values of the IDCODE register are undocumented but the vendor SDK splits IDCODE into 11:0 DEV_ID and + * 31:16 REV_ID. + */ +#define PUYA_DBG_IDCODE_DEV_ID_SHIFT 0U +#define PUYA_DBG_IDCODE_DEV_ID_MASK 0xfffU +#define PUYA_DBG_IDCODE_REV_ID_SHIFT 16U +#define PUYA_DBG_IDCODE_REV_ID_MASK 0xffffU + +/* On PY32F002AW15U an IDCODE value of 0x60001000 was observed */ +#define PUYA_DEV_ID_PY32F002A 0x000 +/* + * On PY32F002BF15P an IDCODE value of 0x20220064 was observed. Internet search shows the same value is used on + * PY32F002BW15. + */ +#define PUYA_DEV_ID_PY32F002B 0x064 /* * Flash functions @@ -114,18 +131,33 @@ bool puya_probe(target_s *target) size_t flash_size = 0U; const uint32_t dbg_idcode = target_mem32_read32(target, PUYA_DBG_IDCODE); - if ((dbg_idcode & 0xfffU) == 0) { + const uint16_t dev_id = (dbg_idcode >> PUYA_DBG_IDCODE_DEV_ID_SHIFT) & PUYA_DBG_IDCODE_DEV_ID_MASK; + switch (dev_id) { + case PUYA_DEV_ID_PY32F002A: { const uint32_t flash_ram_sz = target_mem32_read32(target, PUYA_FLASH_RAM_SZ); - flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT) & PUYA_FLASH_SZ_MASK) + 1) << PUYA_FLASH_UNIT_SHIFT; + flash_size = (((flash_ram_sz >> PUYA_FLASH_SZ_SHIFT) & PUYA_FLASH_SZ_MASK) + 1) + << PUYA_FLASH_UNIT_SHIFT; ram_size = (((flash_ram_sz >> PUYA_RAM_SZ_SHIFT) & PUYA_RAM_SZ_MASK) + 1) << PUYA_RAM_UNIT_SHIFT; - // TODO: which part families does this actually correspond to? - // Tested with a PY32F002AW15U which returns 0x60001000 in IDCODE - target->driver = "PY32Fxxx"; - } else { + target->driver = "PY32F002A"; + break; + } + case PUYA_DEV_ID_PY32F002B: + /* + * 0x1fff0ffc contains 0; did not find any other location that looks like it might contain the flash + * and RAM sizes. We'll hard-code the datasheet values for now. Both flash size and RAM size actually + * match the datasheet value, unlike PY32F002A which (sometimes?) has more RAM and flash than + * documented. + */ + flash_size = 24 * 1024; + ram_size = 3 * 1024; + target->driver = "PY32F002B"; + break; + default: DEBUG_TARGET("Unknown PY32 device %08" PRIx32 "\n", dbg_idcode); return false; } + target->part_id = dev_id; target_add_ram32(target, PUYA_RAM_START, ram_size); target_flash_s *flash = calloc(1, sizeof(*flash)); if (!flash) { /* calloc failed: heap exhaustion */ @@ -151,33 +183,64 @@ static bool puya_flash_prepare(target_flash_s *flash) target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY1); target_mem32_write32(flash->t, PUYA_FLASH_KEYR, PUYA_FLASH_KEYR_KEY2); - uint8_t hsi_fs = - (target_mem32_read32(flash->t, PUYA_RCC_ICSCR) >> PUYA_RCC_ICSCR_HSI_FS_SHIFT) & PUYA_RCC_ICSCR_HSI_FS_MASK; - if (hsi_fs > 4) - hsi_fs = 0; - DEBUG_TARGET("HSI frequency selection is %d\n", hsi_fs); - - const uint32_t eppara0 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 0); - const uint32_t eppara1 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 4); - const uint32_t eppara2 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 8); - const uint32_t eppara3 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 12); - const uint32_t eppara4 = target_mem32_read32(flash->t, PUYA_FLASH_TIMING_CAL_BASE + hsi_fs * 20 + 16); + target_s *target = flash->t; + uint32_t cal_base; + + switch (target->part_id) { + case PUYA_DEV_ID_PY32F002A: { + uint8_t hsi_fs = + (target_mem32_read32(flash->t, PUYA_RCC_ICSCR) >> PUYA_RCC_ICSCR_HSI_FS_SHIFT) + & PUYA_RCC_ICSCR_HSI_FS_MASK; + if (hsi_fs > 4) + hsi_fs = 0; + DEBUG_TARGET("HSI frequency selection is %d\n", hsi_fs); + cal_base = PUYA_FLASH_TIMING_CAL_PY32F002A_BASE + hsi_fs * 20; + break; + } + case PUYA_DEV_ID_PY32F002B: + cal_base = PUYA_FLASH_TIMING_CAL_PY32F002B_BASE; + break; + default: + /* Should have never made it past probe */ + DEBUG_TARGET("Unknown PY32 device %08" PRIx32 "\n", target->part_id); + return false; + } + + const uint32_t eppara0 = target_mem32_read32(flash->t, cal_base + 0); + const uint32_t eppara1 = target_mem32_read32(flash->t, cal_base + 4); + const uint32_t eppara2 = target_mem32_read32(flash->t, cal_base + 8); + const uint32_t eppara3 = target_mem32_read32(flash->t, cal_base + 12); + const uint32_t eppara4 = target_mem32_read32(flash->t, cal_base + 16); DEBUG_TARGET("PY32 flash timing cal 0: %08" PRIx32 "\n", eppara0); DEBUG_TARGET("PY32 flash timing cal 1: %08" PRIx32 "\n", eppara1); DEBUG_TARGET("PY32 flash timing cal 2: %08" PRIx32 "\n", eppara2); DEBUG_TARGET("PY32 flash timing cal 3: %08" PRIx32 "\n", eppara3); DEBUG_TARGET("PY32 flash timing cal 4: %08" PRIx32 "\n", eppara4); - target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara0 & 0xffU); - target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara0 >> 16U) & 0x1ffU); - target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara0 >> 8U) & 0xffU); - target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara1 & 0xffU); - target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara1 >> 16U) & 0x7ffU); - target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara2 & 0x1ffffU); - target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara3 & 0x1ffffU); - target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara4 & 0xffffU); - target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara4 >> 16U) & 0x3fffU); - + switch (target->part_id) { + case PUYA_DEV_ID_PY32F002A: + target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara0 & 0xffU); + target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara0 >> 16U) & 0x1ffU); + target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara0 >> 8U) & 0xffU); + target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara1 & 0xffU); + target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara1 >> 16U) & 0x7ffU); + target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara2 & 0x1ffffU); + target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara3 & 0x1ffffU); + target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara4 & 0xffffU); + target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara4 >> 16U) & 0x3fffU); + break; + case PUYA_DEV_ID_PY32F002B: + target_mem32_write32(flash->t, PUYA_FLASH_TS0, eppara0 & 0x1ffU); + target_mem32_write32(flash->t, PUYA_FLASH_TS1, (eppara0 >> 18U) & 0x3ffU); + target_mem32_write32(flash->t, PUYA_FLASH_TS3, (eppara0 >> 9U) & 0x1ffU); + target_mem32_write32(flash->t, PUYA_FLASH_TS2P, eppara1 & 0x1ffU); + target_mem32_write32(flash->t, PUYA_FLASH_TPS3, (eppara1 >> 16U) & 0xfffU); + target_mem32_write32(flash->t, PUYA_FLASH_PERTPE, eppara2 & 0x3ffffU); + target_mem32_write32(flash->t, PUYA_FLASH_SMERTPE, eppara3 & 0x3ffffU); + target_mem32_write32(flash->t, PUYA_FLASH_PRGTPE, eppara4 & 0xffffU); + target_mem32_write32(flash->t, PUYA_FLASH_PRETPE, (eppara4 >> 16U) & 0x3fffU); + break; + } return true; }