-
-
Notifications
You must be signed in to change notification settings - Fork 773
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
puya: add support for PY32F002B #2000
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,32 @@ 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; | ||
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; | ||
Comment on lines
+150
to
+151
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please suffix all these constants with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed locally; will push together with the other changes once they are done. |
||
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 +182,63 @@ 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); | ||
Comment on lines
+220
to
+239
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the number of magic numbers involved, it might make sense to name them via There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In progress. While doing so I noticed that the existing code uses additional bits from EPPARA4 for PRETPE (datasheet says 26:16 are PRETPE so the mask should be 0x7ff but the code uses 0x3fff). @ArcaneNibble was this on purpose? If not, would you be willing to test my changes if I fix this to match the datasheet values? I don't have a PY32F002A myself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed locally to use defines named like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excellent, let's hope that they get back to you on this query fairly soon then 🙂 |
||
break; | ||
} | ||
return true; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please suffix these with
U
so they are defined unsigned.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed locally; will push together with the other changes once they are done.