Skip to content
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

Unknown Cortex-M0+, likely STM32F030R8 clone #2020

Open
ranma opened this issue Dec 14, 2024 · 6 comments
Open

Unknown Cortex-M0+, likely STM32F030R8 clone #2020

ranma opened this issue Dec 14, 2024 · 6 comments
Labels
New Target New debug target

Comments

@ranma
Copy link

ranma commented Dec 14, 2024

BMP v1.9.0-189-g417f1616

Target voltage: 3.07V
Please report unknown device with Designer 0x43b Part ID 0x4c0
Available Targets:
No. Att Driver
*** 1   Unknown ARM Cortex-M Designer 0x43b Part ID 0x4c0 M0+
(gdb) at 1
[...]
(gdb) set mem inaccessible-by-default off
(gdb) x 0x40021000  [RCC_CR]
0x40021000:     0x00005583
(gdb) x 0x40021014  [RCC_AHBENR]
0x40021014:     0x00000014
(gdb) x 0x40021018  [RCC_APB2ENR]
0x40021018:     0x00000000
(gdb) x 0x4002101c  [RCC_APB1ENR]
0x4002101c:     0x00000000
(gdb) set {int}0x40021018 = 0xffffffff  [enable all APB2 clocks]
(gdb) set {int}0x4002101c = 0xffffffff  [enable all APB1 clocks]
(gdb) x 0x40021018
0x40021018:     0x00475a01 [settable APB2ENR bits]
(gdb) x 0x4002101c
0x4002101c:     0x70624913  [settable APB1ENR bits]
(gdb) x 0x40015800  [DBGMCU]
0x40015800:     0x20006440

For STM, DEVICE_ID 0x20006440 would be the STM32F030R8, however that is a Cortex-M0, not a M0+.
Also, accesses beyond flash/ram size don't fault, they just read as 0

Flash size appears to be 64KiB
RAM size appears to be 8KiB

System memory region is 0x1fffec00 - 0x1ffff800
Option bytes region is 0x1ffff800 - 0x1ffffc00

Both flash and RAM size match the STM32 DEVICE_ID.

Unfortunately the device has fake markings (claiming to be AY408F520C), no idea what the actual manufacturer is.

LFQP48 with at least UART RX/TX and SWCLK/SWDAT matching STM32 pinout.

Anyone know a chinese clone manufacturer that makes one with these characteristics?

@dragonmux
Copy link
Member

For what it's worth, it would be useful if you could get a scan and part information from a more recent version of BMD - specifically main, as a whole lot to do with identification has changed since the version you're running and which may yield some more useful identification information in regards to the ROM tables dumped via BMDA as blackmagic -tv 5.

We will let someone else more familiar with the STM32 clones answer regarding who might have made this part and so what might be needed to support the part properly for reprogramming.

@dragonmux dragonmux added the New Target New debug target label Dec 14, 2024
@ranma
Copy link
Author

ranma commented Dec 14, 2024

For what it's worth, it would be useful if you could get a scan and part information from a more recent version of BMD - specifically main

Done: Black Magic Probe (BlackPill-F401CE) v1.10.0-1578-g8bcdc489-dirty

(gdb) target ext /dev/ttyACM0
Remote debugging using /dev/ttyACM0
(gdb) monitor swdp_scan
Target voltage: Unknown
Please report unknown device with Designer 0x43b Part ID 0x4c0
Available Targets:
No. Att Driver
*** 1   Unknown ARM Cortex-M Designer 0x43b Part ID 0x4c0 M0+
$ ./blackmagic -tv5 -d /dev/ttyACM0 
Black Magic Debug App v1.10.0-1578-g8bcdc489-dirty
 for Black Magic Probe, ST-Link v2 and v3, CMSIS-DAP, J-Link and FTDI (MPSSE)
Running in Test Mode
Target voltage: Unknown
Speed set to 7.000MHz for SWD
Switching from JTAG to dormant
Switching out of dormant state into SWD
DP DPIDR 0x0bc11477 (v1 MINDP rev0) designer 0x43b partno 0xbc
AP   0: IDR=04770031 CFG=00000000 BASE=e00ff000 CSW=e3000040 (AHB3-AP var3 rev0)
Halt via DHCSR(00030003): success after 3ms
ROM Table: BASE=0xe00ff000 SYSMEM=1, Manufacturer 43b Partno 4c0 (PIDR = 0x04000bb4c0)
0 0x0e000e000: Generic IP component - Cortex-M0 SCS (System Control Space) (PIDR = 0x04000bb008 DEVTYPE = 0x00 ARCHID = 0x0000)
-> cortexm_probe
CPUID 0x410cc601 (M0+ var 0 rev 1)
cortexm_probe: Examining Part ID 0x04c0, AP Part ID: 0x04c0
Calling lpc11xx_probe
Calling hc32l110_probe
Calling puya_probe
Unknown PY32 device 20006440
Please report unknown device with Designer 0x43b Part ID 0x4c0
1 0x0e0001000: Generic IP component - Cortex-M0 DWT (Data Watchpoint and Trace) (PIDR = 0x04000bb00a DEVTYPE = 0x00 ARCHID = 0x0000)
2 0x0e0002000: Generic IP component - Cortex-M0 BPU (Breakpoint Unit) (PIDR = 0x04000bb00b DEVTYPE = 0x00 ARCHID = 0x0000)
ROM Table: END
Resuming target
***  1   Unknown ARM Cortex-M Designer 0x43b Part ID 0x4c0 M0+
Attaching to target..
Halting target
Target halted: Halt requested
Attach success
Detaching from target

Note that while this says "Unknown PY32 device", the system memory region doesn't match and the PUYA_FLASH_RAM_SZ address reads as 0, which doesn't match the flash/ram size.

@ranma
Copy link
Author

ranma commented Dec 14, 2024

Picture of the mystery:
image

Note that this logo is "Shenzhen Aoyang Technology Co., Ltd.", who make Solar charge controllers, I doubt they make their own STM32 clones, so its certainly remarked (or custom marked?).

@ranma
Copy link
Author

ranma commented Dec 15, 2024

From program code disassembly, the flash erase/write pretty much matches the STM32 datasheet, to unlock it writes to FLASH_KEYR:
• Write KEY1 = 0x45670123
• Write KEY2 = 0xCDEF89AB

Then does page erase, 16bit word writes, locks flash by writing 0x80 to CR

@ranma
Copy link
Author

ranma commented Dec 20, 2024

diff --git a/src/target/cortexm.c b/src/target/cortexm.c
index 77ca32c7..69ed6f5a 100644
--- a/src/target/cortexm.c
+++ b/src/target/cortexm.c
@@ -454,6 +454,7 @@ bool cortexm_probe(adiv5_access_port_s *ap)
                        PROBE(lpc11xx_probe);               /* LPC8 */
                        PROBE(hc32l110_probe);              /* HDSC HC32L110 */
                        PROBE(puya_probe);                  /* Puya PY32 */
+                       PROBE(stm32f1_probe);               /* Care for other STM32F0 clones (?) */
                } else if (target->part_id == 0x4c1U) { /* NXP Cortex-M0+ ROM */
                        PROBE(lpc11xx_probe);               /* newer LPC11U6x */
                } else if (target->part_id == 0x4c3U) { /* Cortex-M3 ROM */
diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c
index 34f2354b..aba628b0 100644
--- a/src/target/stm32f1.c
+++ b/src/target/stm32f1.c
@@ -196,6 +196,7 @@ static void stm32f1_add_flash(target_s *target, uint32_t addr, size_t length, si
 static uint16_t stm32f1_read_idcode(target_s *const target, target_addr32_t *const config_taddr)
 {
        if ((target->cpuid & CORTEX_CPUID_PARTNO_MASK) == CORTEX_M0 ||
+               (target->cpuid & CORTEX_CPUID_PARTNO_MASK) == CORTEX_M0P ||
                (target->cpuid & CORTEX_CPUID_PARTNO_MASK) == CORTEX_M23) {
                *config_taddr = STM32F0_DBGMCU_CONFIG;
                return target_mem32_read32(target, STM32F0_DBGMCU_IDCODE) & 0xfffU;

With this change:

(gdb) target ext localhost:2000
Remote debugging using localhost:2000
(gdb) monitor swdp_scan
Target voltage: Unknown
Available Targets:
No. Att Driver
 1      STM32F05/F030x8 M0+

Then does page erase, 16bit word writes, locks flash by writing 0x80 to CR

So it seems it needs to be 16bit writes at a time, since the default STM32 flash routine doesn't quite work, after flashing code into an empty (all 0xff) area I see:

(gdb) x/4 0x08008000 
0x8008000 <startup()>:  0xffffb510      0xffff4903      0xfffffdc9      0xffffe7fd

So it is missing all the upper words...

Hmm, if I enable STM32F1_TOPT_32BIT_WRITES I see

(gdb) x/8 0x08008000 
0x8008000 <startup()>:  0x4803b510      0xffffffff      0xbf30fdc9      0xffffffff
0x8008010 <startup()+16>:       0x08008018      0xffffffff      0x6c6c6548      0xffffffff

@ranma
Copy link
Author

ranma commented Dec 20, 2024

I think the problem is that cortexm_mem_write_aligned writes the whole block at a time, without waiting for flash BSY in between word writes.

Having more luck with this change switching to write 32bit at a time:

@@ -1133,18 +1135,24 @@ static bool stm32f1_flash_write(target_flash_s *flash, target_addr_t dest, const
 
        /* Start by writing any bank 1 data */
        if (offset) {
-               stm32f1_flash_clear_eop(target, FLASH_BANK1_OFFSET);
-
-               target_mem32_write32(target, FLASH_CR, FLASH_CR_PG);
-               /* Use the target API instead of a direct Cortex-M call for GD32VF103 parts */
-               if (target->designer_code == JEP106_MANUFACTURER_RV_GIGADEVICE && target->cpuid == 0x80000022U)
-                       target_mem32_write(target, dest, src, offset);
-               else
-                       cortexm_mem_write_aligned(target, dest, src, offset, psize);
-
-               /* Wait for completion or an error */
-               if (!stm32f1_flash_busy_wait(target, FLASH_BANK1_OFFSET, NULL))
-                       return false;
+               target_addr_t wptr = dest;
+               const uint32_t *rptr = src;
+               for (size_t remain = offset; remain > 0; remain -= 4, wptr += 4, rptr++) {
+                       uint32_t data = *rptr;
+                       if (data == 0xffffffff) {
+                               continue;
+                       }
+
+                       stm32f1_flash_clear_eop(target, FLASH_BANK1_OFFSET);
+
+                       target_mem32_write32(target, FLASH_CR, FLASH_CR_PG);
+                       DEBUG_TARGET("write32 %08x @%08x\n", data, wptr);
+                       target_mem32_write32(target, wptr, data);
+
+                       /* Wait for completion or an error */
+                       if (!stm32f1_flash_busy_wait(target, FLASH_BANK1_OFFSET, NULL))
+                               return false;
+               }
        }
 
        /* If there's anything to write left over and we're on a part with a second bank, write to bank 2 */

Although it hangs on flash_busy_wait at the end of a 512 byte block:

Attach success
stm32f1_flash_erase: at 08008000
stm32f1_flash_write: at 08008000 for 1024 bytes
write32 4803b510 @08008000
write32 f7fc4903 @08008004
write32 bf30fdc9 @08008008
write32 46c0e7fd @0800800c
write32 08008018 @08008010
write32 000004d2 @08008014
write32 6c6c6548 @08008018
write32 6425206f @0800801c
write32 ffff000a @08008020
write32 ffffffff @08008024
write32 ffffffff @08008028
[...]
write32 ffffffff @080081fc [hang]

At least the data was written successfully:

(gdb) x/8 0x08008000 
0x8008000 <startup()>:  0x4803b510      0xf7fc4903      0xbf30fdc9      0x46c0e7fd
0x8008010 <startup()+16>:       0x08008018      0x000004d2      0x6c6c6548      0x6425206f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New Target New debug target
Projects
None yet
Development

No branches or pull requests

2 participants