Author Topic: $0.11 PY32F002A: Cortex-M0+ MCU, actually a PY32F030! 32/4KB, 48MHz, PLL, DMA...  (Read 30571 times)

0 Members and 2 Guests are viewing this topic.

Offline danymogh

  • Regular Contributor
  • *
  • Posts: 51
  • Country: ge
Very strange , I have the same config but mine automatically erases the chip after attempting to read the data.

I noticed in your first post you mentioned to programed the RDP using Jlink and then had to use puya isp to reset it.

How did you set RDP using Jlink? is it possible to program optionbyes using Jlink or cmsis dap ?
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
I said I had set RDP, not that I used Jlink for that. In fact I did it with code:
Code: [Select]
FLASH_OBProgramInitTypeDef pOBInit;

LL_FLASH_OBGetConfig(&pOBInit);

if(pOBInit.RDPLevel != OB_RDP_LEVEL_1){
    pOBInit.OptionType = OPTIONBYTE_RDP;
    pOBInit.RDPLevel = OB_RDP_LEVEL_1;
    LL_FLASH_Unlock();
    LL_FLASH_OB_Unlock();
    LL_FLASH_OBProgram(&pOBInit);
    LL_FLASH_OB_Lock();
    LL_FLASH_Lock();
    LL_FLASH_OB_Launch();
}

If you want a quick program for testing, here's one.
It loops USART1 (PA2, PA3), all you send is TX'ed back using DMA (115200 baud).
Also there're 3 leds: PA0, PB0, PB1 (Meant to be a RGB led), connect them to VDD trough a resistor (The mcu pulls low to lit it).
Just like the schematics in the 1st post, as I'm using that board.
« Last Edit: August 06, 2023, 05:42:22 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: danymogh

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
I tried, and it can be set while programming by modifying the linker script:
Code: [Select]
MEMORY
{
  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 4K
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 32K
  RDP (r)    : ORIGIN = 0x1FFF0E80, LENGTH = 4
}

/* Define output sections */
SECTIONS
{
  .rdp :
  {
    KEEP(*(.rdp)) /* .rdp section */
    KEEP(*(.rdp*))
  } >RDP

Then defining the value:
Code: [Select]
// RDP 0
__attribute__((section(".rdp"))) const uint32_t rdp = 0x4155beaa;

//RDP 1
__attribute__((section(".rdp"))) const uint32_t rdp = 0x41aabe55;
But be careful, setting BOOT1 will make BOOT0 unable from entering the bootloader (boot0 & boot1 high boots from ram instead).
Better simply to not touch RDP unless you really want to protect it (For production, etc).
Interestingly, after setting RDP1 this way, PUYA ISP doesn't complain for readout protection, it still reads the MCU, though it's all 0xFF.

Also, the default value stated in the RM seems wrong, it says it's 0x0155BEAA but should be 0x4155BEAA.
(The upper 16 bits are the lower 16 bits, inverted).
The 2nd byte (0xBE) byte defines the behaviour of nRST, BOOT1 (Not available as pin), BOR, IWDG, WWDG...
Read the referece manual to find out what these bits mean, section "Flash option byte".

Also, Puya ISP won't work properly if you set RDP like this, it crashes when opening the hex file.
Don't enable bin generation, it will fill the gap between the end of the flash (0x8008000) and the start of RDP(0x1FFF0E80), making a giant file of 383MB.
« Last Edit: August 07, 2023, 09:17:55 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: danymogh

Offline prosper

  • Regular Contributor
  • *
  • Posts: 79
  • Country: ca
you should be able to write opt from within your application, or, attach GDB to it (with the DAP and pyocd) and write the bytes manually

(gdb) set *((unsigned int *) 0x1FFF0E80) = <value>



you could include a gdb one or two liner in your makefile.
« Last Edit: August 08, 2023, 04:07:10 am by prosper »
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
So I'm having a really weird situation.

Edit:
I set everything to fit 100% to the official PY32F002A specs, leaving the code to the very minimum...
Now it only uses Systick and Timer1.

Timer1 capture triggers in any falling edge, sets "new_capture" variable when detected and stops itself.

Systick isr monitors this variable, sets a led indicating a new capture was received and restarts the capture timer.
It also toggles a second led indicating the system is working.

Systick isr has the highest priority, so no other IRQ can execute over it except HardFault.

It all works as expected, no matter the optimization level.
When I set RDP1, it will randomly freeze when toggling the input capture signal, killing everything.
I made a checkum of the entire flash before and after locking, printing it through serial, it matched.
This also happens if I set RDP using PuyaISP.
I only know it's not a HardFault, as it has a routine that quickly flashes the led.
I can trigger it by accessing unimplemented memory, but it's not being called when this strange fault happens.
I even filled all the empty NVIC entries in case it was triggering some undocumented vector... nope.

I can attach the debugger, as RDP is set I can only see the cpu registers, the PC can be read so I have a slight idea of what's going on.
The debugger halts when toggling the capture input, so clearly there's some exception happening.
Quote
...Target halted (Vector catch, PC = 0xFFFFFFFE)
Reading common registers: Read register 'r0' (4 bytes) from hardware: 0x0000000A
Read register 'r1' (4 bytes) from hardware: 0x05000000
Read register 'r2' (4 bytes) from hardware: 0x01000000
Read register 'r3' (4 bytes) from hardware: 0x01000000
Read register 'r4' (4 bytes) from hardware: 0xE70B0020
Read register 'r5' (4 bytes) from hardware: 0x01000000
Read register 'r6' (4 bytes) from hardware: 0xDC0BFF1F
Read register 'r7' (4 bytes) from hardware: 0xD80B0020
Read register 'r8' (4 bytes) from hardware: 0x24B763A1
Read register 'r9' (4 bytes) from hardware: 0x64020020
Read register 'r10' (4 bytes) from hardware: 0x1BD00CED
Read register 'r11' (4 bytes) from hardware: 0x273F3419
Read register 'r12' (4 bytes) from hardware: 0x00E0FFFF
Read register 'sp' (4 bytes) from hardware: 0xB80B0020
Read register 'lr' (4 bytes) from hardware: 0xF9FFFFFF
Read register 'pc' (4 bytes) from hardware: 0xFEFFFFFF
Read register 'xpsr' (4 bytes) from hardware: 0x03000061
WARNING: Failed to read memory @ address 0xFFFFFFFE
Read 4 bytes @ address 0x20000BD4 (Data = 0x61000000)
Reading 64 bytes @ address 0x20000BC0
WARNING: Failed to read memory @ address 0x0800080C
WARNING: Failed to read memory @ address 0x08001EFA
WARNING: Failed to read memory @ address 0x08001EFA
Read 4 bytes @ address 0xE000ED04 (Data = 0x00420003)
Read 4 bytes @ address 0xE000ED0C (Data = 0xFA050000)
Read 4 bytes @ address 0xE000ED04 (Data = 0x00420003)
Read 4 bytes @ address 0xE000ED1C (Data = 0x00000000)
Read 4 bytes @ address 0xE000ED20 (Data = 0x00000000)
Read 4 bytes @ address 0xE000ED24 (Data = 0x00000000)
Read 4 bytes @ address 0xE000ED08 (Data = 0x08000000)
Read 4 bytes @ address 0xE000E010 (Data = 0x00000004)
Read 4 bytes @ address 0xE000E014 (Data = 0x000F398E)
Read 4 bytes @ address 0xE000E018 (Data = 0x009F0E6E)
Read 4 bytes @ address 0xE000E01C (Data = 0x80000000)
Read 4 bytes @ address 0xE000E01C (Data = 0x80000000)
« Last Edit: August 18, 2023, 01:01:32 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline danymogh

  • Regular Contributor
  • *
  • Posts: 51
  • Country: ge
your PC = 0xFFFFFFFE

that's an invalid address. if this happens only when RDP is set then it might have to do with flash protection options.

have you read Table 4-8 from the English reference manual?

Edit : try to apply the RDP protection from outside the code. (from PuyaISP) see if that changes anything.
« Last Edit: August 18, 2023, 12:19:27 pm by danymogh »
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
your PC = 0xFFFFFFFE
that's an invalid address
I know!

try to apply the RDP protection from outside the code. (from PuyaISP) see if that changes anything.
I forgot to mention that. Yes, it also happens. Thats's what made me think of a real hardware issue.

It's not the flash, as I said I checksumed the entire 32K, before and after locking and the result matched.
Also I could write to the flash in the code after setting RDP.
The executed code is always the same...

I attached the binary just in case you want to try, RDP disabled.

MCU:PY32F002AF15P6TU
System LED: PB1, active low
CCP LED: PB0, active low
CCP input: PA1, falling edge, internal pullup.
Oscillator: Internal 24MHZ HSI
Leds are active-low, connected to VDD, the mcu pin pull it low when active.

Nothing else is required. Just poke the CCP input and see the CCP led doing stuff.
If RDP is enabled, it will randomly stall.

Without RDP it can run for hours. 
« Last Edit: August 18, 2023, 01:02:38 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
Made it so the led blinks for only 1ms when a falling edge is detected.
Led duration is not very accurate, as it can happen right after a systick IRQ, so it might remain enabled anywhere between 1 and 2ms.
Not the problem here!
100Hz CCP signal, when RDP off it runs forever.
With RDP on, it crashed after 2 seconds or so.
The system only crashes when toggling the ccp input, otherwise it will run fine.
Time for crashing is random, sometimes it happens in 100ms, others in 3 seconds.
« Last Edit: August 18, 2023, 04:28:57 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 1989
  • Country: dk
@David

ATM i just have two F002 devel boards, same mcu as you.

I can't really test, will loose my "chip"
I'm quite sure you wrote that only the puya programmer could clear the read protection.
And the puya programmer s Win-only, i'm linux only.

Hope someone else can help out.

/Bingo
« Last Edit: August 18, 2023, 03:41:34 pm by bingo600 »
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
Might it work in Wine? I tried but it's not recognizing the serial ports...

Edit: It's only happening if more than one interrupt is enabled.
Seems like some sort of stack corruption? One interrupt happens over other one, then the it restores a wrong or corrupted context?
If I disable systick it won't happen. But this will also happen if any other interrupt is running.
It can't get any simpler than this!
Code: [Select]
#include "main.h"

volatile uint8_t new_capture;

/*--------------------------------------------------*/
void system_init(void)
{
  LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_24MHz);
  while (LL_RCC_HSI_IsReady() != 1);

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA | LL_IOP_GRP1_PERIPH_GPIOB | LL_IOP_GRP1_PERIPH_GPIOF);
  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM1);

  WritePin(RED,1);
  WritePin(BLUE,1);
  LL_GPIO_Init(CCP_Port,  &(LL_GPIO_InitTypeDef){ CCP_Pin,  LL_GPIO_MODE_ALTERNATE, LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL, LL_GPIO_PULL_NO, CCP_AF });
  LL_GPIO_Init(RED_Port,  &(LL_GPIO_InitTypeDef){ RED_Pin,  LL_GPIO_MODE_OUTPUT,    LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL });
  LL_GPIO_Init(BLUE_Port, &(LL_GPIO_InitTypeDef){ BLUE_Pin, LL_GPIO_MODE_OUTPUT,    LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL });

  LL_TIM_Init(CCP_TIM, &(LL_TIM_InitTypeDef){ 23, LL_TIM_COUNTERDIRECTION_UP, 65535, LL_TIM_CLOCKDIVISION_DIV1, 0});                              // 1MHz clock, 65ms overflow
  LL_TIM_IC_Init(CCP_TIM, CCP_CH, &(LL_TIM_IC_InitTypeDef){ LL_TIM_IC_POLARITY_FALLING, LL_TIM_ACTIVEINPUT_DIRECTTI, LL_TIM_ICPSC_DIV1, 4 });      // Falling edge
  LL_TIM_EnableCounter(CCP_TIM);

  NVIC_SetPriority(TIM1_CC_IRQn, 1);
  NVIC_EnableIRQ(TIM1_CC_IRQn);

  SysTick_Config(24000);      // 24MHz cpu clock, 1ms period.
}

/*--------------------------------------------------*/
void capture_start(void)
{
  LL_TIM_ClearFlag_CC4(CCP_TIM);
  LL_TIM_EnableIT_CC4(CCP_TIM);
}

/*--------------------------------------------------*/
int main(void)
{
  uint32_t red=0, blue=0;

  system_init();
  capture_start();

  while(1)
  {
    /*-------------*/                 // Handle red led
    if(new_capture)
    {                                 // Turn on the red LED for some time when a capture is received.
      new_capture=0;
      red=100;                        // Load led counter
      capture_start();                // Start a new capture
    }
    else if(red && !--red)            // Decrease led counter until 0
      WritePin(RED,1);                // Led expired, turn off

    /*-------------*/                 // Handle blue led
    if (!blue  || !--blue )           // Generate small pulses in the blue led as heartbeat signal
    {
      bool b = ReadPin(BLUE);
      WritePin(BLUE,!b);
      blue = b ? 1000 : 1100000;
    }
    /*-------------*/
  }
}

/*--------------------------------------------------*/
void systick_isr(void)
{
    asm("nop");       // Do nothing
}

/*--------------------------------------------------*/
void capture_isr(void)
{
  LL_TIM_SetCounter(CCP_TIM, 0);                    // Reset timer counter
  if(LL_TIM_IsActiveFlag_CC4(CCP_TIM))              // Capture flag active
  {
    LL_TIM_IC_GetCaptureCH4(CCP_TIM);               // Capture CCP value
    LL_TIM_DisableIT_CC4(CCP_TIM);                  // Disable CC interrupt
    LL_TIM_ClearFlag_CC4(CCP_TIM);                  // Clear flag
    WritePin(RED,0);                                // Turn led on
    new_capture=1;                                  // Set flag
  }
}
« Last Edit: August 18, 2023, 07:01:23 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 1989
  • Country: dk
Seems like some sort of stack corruption? One interrupt happens over other one, then the it restores a wrong or corrupted context?

And still only when RDP is enabled ??

/Bingo
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
Yes! That's why I started this. Otherwise I would think it was my fault.

The code should not be affected in any way by RDP!
I left it with RDP off, receiving 200Hz pulses from the generator for more than an hour, no problem!
Same file, programmed setting RDP in PuyaISP - crashes in 1-2 seconds.
How is that?!

So anything planned to be sold and RDP-protected - back to stm32 LOL.
I knew something had to happen at some point :-DD
« Last Edit: August 18, 2023, 07:56:03 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline danymogh

  • Regular Contributor
  • *
  • Posts: 51
  • Country: ge
That's a big problem if it really is a problem on the chip level.
AFAIK they buy or implement the cortex M0+ core as is on the chip and only add peripherals. what you described is on the core level which means the core is faulty somehow?

I think it needs a little more digging.
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
I sent a mail to Puya, I don't expect getting any solution3 but who knows.
Meanwhile this will be my own fix:  :-DD
https://a.aliexpress.com/_Eu8sh0B
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline man_anyone

  • Newbie
  • Posts: 5
  • Country: my
Did you test the hk32f030 to see if it has the same problem? Maybe there's a common thing that all Chinese MCUs cheap out on that leads to this problem
Maybe we can get help from hangshun too if their MCU has the same problem
« Last Edit: August 21, 2023, 10:19:16 am by man_anyone »
 

Offline PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1545
  • Country: au
Or other PUYA MCU, do they have the same issue?
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
The HK only had a small issue, requiring power cycling after programming. Yeah this same project is working in the HK, in fact I've sold a few.
I tried migrating to the PY32 as it's a better mcu overall while less than half the price, but didn't go as planned.
« Last Edit: August 21, 2023, 11:23:17 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline man_anyone

  • Newbie
  • Posts: 5
  • Country: my
What about trying other puya MCUs? Also try other units maybe this one is defective
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
I tried 3 chips, all had the same behaviour.
So I tried moving the interrupt vector table to the SRAM as @bingo600 suggested.
The issue is gone! Working now!
Created a PR at IOSetting's repo.

However this is not optimal, anyone could dump the flash by overwriting the sram, for example placing custom code in the systick ISR or changing the vector addresses.
After that, you can place up to 4KB of code... you can do anything with so many space!
« Last Edit: August 21, 2023, 06:55:44 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 1989
  • Country: dk
 :-DD

Longshot ... but it worked out  :-+ :-+

@David
Thank you for the PR  :-+

/Bingo
« Last Edit: August 21, 2023, 07:01:47 pm by bingo600 »
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
Yeah but it's not ok... leaves the system poorly protected!
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 1989
  • Country: dk
However this is not optimal, anyone could dump the flash by overwriting the sram, for example placing custom code in the systick ISR or changing the vector addresses.
After that, you can place up to 4KB of code... you can do anything with so many space!
Can you (a debugger) still write to the ram if it's protected , or do you mean "buffer overflow" attack ??

« Last Edit: August 21, 2023, 07:32:04 pm by bingo600 »
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
Yeah, a debugger has complete access to the ram.
Systick vector is now placed at 0x2000003C:
You could halt the system, load a program into 0x20001000, made to dump the flash through the serial port, and write that address to systick vector.
When the IRQ triggers, game over!

At least I can mitigate this by disabling SWD port and setting the nRST config bit.
The reset pin function becoems completely disabled, even when shorting the reset pin before power is applied, it no longer works.
Then I have a special unlock procedure in the code that resets the RDP, this completely erases the mcu so it can be accesed again.

nBOOT1 config bit switches between bootloader mode ad system ram booting. Not sure what would be the safest!
Let me guess.. Burn the pin down! :-DD
« Last Edit: August 21, 2023, 08:16:05 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: bingo600

Offline prosper

  • Regular Contributor
  • *
  • Posts: 79
  • Country: ca
I don't understand the vulnerability. If you have debug, can't you *already* modify SRAM, and then point the program counter wherever you want to execute arbitrary code?
 

Offline DavidAlfaTopic starter

  • Super Contributor
  • ***
  • Posts: 5912
  • Country: es
I guess you could also write to VTOR with the debugger, yeah!
Well, if possible at all, nRST=OFF, BOR=ON, SWD=OFF and BOOT1=OFF should give plenty of headaches to the attackers  :).
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf