cancel
Showing results for 
Search instead for 
Did you mean: 

The STM32G0 series microcontroller enters undescribed mode.

red15530
Associate II

I have been sitting with this question for more than a week, I have already run out of strength, I cannot understand how it works and what I am doing wrong ...

And so, I have an STM32G030F6P6 microcontroller. My program needs to do two things with flash memory, namely:

1) Save 8 bit number. I do it like this:

	FLASH->KEYR = 0x45670123;
	FLASH->KEYR = 0xCDEF89AB;
 
	while (FLASH->SR & FLASH_SR_BSY1);
 
	FLASH->SR |= FLASH_SR_OPTVERR;
	FLASH->SR |= FLASH_SR_FASTERR;
	FLASH->SR |= FLASH_SR_MISERR;
	FLASH->SR |= FLASH_SR_PGSERR;
	FLASH->SR |= FLASH_SR_SIZERR;
	FLASH->SR |= FLASH_SR_PGAERR;
	FLASH->SR |= FLASH_SR_WRPERR;
	FLASH->SR |= FLASH_SR_PROGERR;
	FLASH->SR |= FLASH_SR_OPERR;
 
	FLASH->CR |= FLASH_CR_PER; //Page erase enable
	FLASH->CR |= (15<<FLASH_CR_PNB_Pos); //Page number selection
	FLASH->CR |= FLASH_CR_EOPIE; //End-of-operation interrupt enable
	FLASH->CR |= FLASH_CR_STRT; // Start erase operation
 
	while (FLASH->SR & FLASH_SR_BSY1);
 
	if (FLASH->SR & FLASH_SR_EOP)
	{
		FLASH->SR |= FLASH_SR_EOP;
	}
 
	FLASH->CR &= ~FLASH_CR_PER; //Page erase disabled
	//--------------------------------------------------
	while (FLASH->SR & FLASH_SR_BSY1);
 
	FLASH->SR |= FLASH_SR_OPTVERR;
	FLASH->SR |= FLASH_SR_FASTERR;
	FLASH->SR |= FLASH_SR_MISERR;
	FLASH->SR |= FLASH_SR_PGSERR;
	FLASH->SR |= FLASH_SR_SIZERR;
	FLASH->SR |= FLASH_SR_PGAERR;
	FLASH->SR |= FLASH_SR_WRPERR;
	FLASH->SR |= FLASH_SR_PROGERR;
	FLASH->SR |= FLASH_SR_OPERR;
 
	FLASH->CR |= FLASH_CR_PG; //Flash memory programming enable
	FLASH->CR |= (15<<FLASH_CR_PNB_Pos); //Page number selection
	FLASH->CR |= FLASH_CR_EOPIE; //End-of-operation interrupt enable
 
	*(__IO uint32_t*)0x08007800=(uint32_t)mydata;
	*(__IO uint32_t*)0x08007804=0;
 
	while (FLASH->SR & FLASH_SR_BSY1);
 
	if (FLASH->SR & FLASH_SR_EOP)
	{
		FLASH->SR |= FLASH_SR_EOP;
	}
	FLASH->CR &= ~FLASH_CR_PG; //Page programming disabled
	FLASH->CR &= ~FLASH_CR_EOPIE; //End-of-operation interrupt disabled
 
	FLASH->CR |= FLASH_CR_LOCK;

2) Set read protection memory. I do it like this:

    if ((FLASH->OPTR & FLASH_OPTR_RDP) != 0xBB)
    {
  	  FLASH->KEYR = 0x45670123;
  	  FLASH->KEYR = 0xCDEF89AB;
 
  	  FLASH->OPTKEYR = 0x08192A3B;
  	  FLASH->OPTKEYR = 0x4C5D6E7F;
 
  	  while (FLASH->SR & FLASH_SR_BSY1);
 
  	  FLASH->OPTR |= (0xBB << FLASH_OPTR_RDP_Pos);
 
  	  while (FLASH->SR & FLASH_SR_BSY1);
  	  FLASH->CR |= FLASH_CR_OPTSTRT;
  	  while (FLASH->SR & FLASH_SR_BSY1);
  	  FLASH->CR |= FLASH_CR_LOCK;
    }

After, if you restart the power supply, the microcontroller goes into some kind of incomprehensible state and it can no longer be programmed. It generally ceases to be determined by the programmer through the SWD interface. I also see that my program is not running. (I know this because it should flash the LED)

At the same time, I noticed that after I program the microcontroller, but do not turn off the power, I have the opportunity to connect to it and even erase the memory or write a new program to it. But no matter what I do after a power reset, everything leads to one result - the inability to connect to this microcontroller in any way.

I also noticed that after programming with this program, when I am in debug mode, sometimes (I did not find a pattern) the program can go into the address space> 0x1fff0000 and crashes there.

I don’t know what exactly affects the microcontroller writing to memory or setting read protection. But if I remove these two functions from the program, everything works without problems.

Thus, I have already spoiled more than 10 microcontrollers, and in order to continue to deal with this problem, I do not want to sacrifice new ones.

I use the original ST LINK V2 programmer and original STM32G030F6P6 microcontrollers, as well as the latest versions of STM32CubeIDE 1.11.2, STM32CubeProgrammer v2.12.0 and STM32 ST-LINK Utility.

The programmer is connected according to this scheme

If I forgot to mention something, I am ready to answer any questions. If you need to provide any diagrams, code snippets or any other information, just ask.

I welcome any idea, any opportunity to get to the bottom of the truth! If you need to "kill" more controllers - I'm ready!

If anyone has any ideas how to bring broken microcontrollers back to life (any idea) I'm willing to try.

13 REPLIES 13

Thank you! Is there a similar LL library? Or maybe someone wrote memory programming in pure CMSIS?

Ahh next regboy . Check with HAL if problem persist, after this you can read HAL sources and rewrite all to your perfectly work reg = on risc mcu.

red15530
Associate II

Thank you all very much for your help. At the cost of another microcontroller, I finally figured out what was going on! I was wrong when I thought it was because of writing to flash. As a result, what I have now:

We do all the points below without turning off the power.

1) We program with any program.

2) We put L1 protection through proprietary utilities. (STM32 ST-LINK Utility or STM32CubeProgrammer, it doesn't matter, the effect is the same), while the program stops executing for some reason.

3) We remove L1 protection through proprietary utilities. The memory is accordingly erased. (STM32 ST-LINK Utility or STM32CubeProgrammer, it doesn't matter, the effect is the same)

4) After that, if you program with any program where there are interruptions, then after any interruption we go to the area> 0x1fff0000 and hang there endlessly.

If you program the program without interruptions, everything works properly.

Next, there are two scenarios:

- If after that you turn off and turn on the power of the microcontroller and at the same time the program is flashed without interruptions, then all work is restored and now you can flash with any program, even with interruptions, even without them. Everything is working normally.

- If after that turn off and turn on the power supply of the microcontroller, but leave the program where the interrupts were, we get a corpse that is not detected by SWD, not by UART.

Note 1: If you program with interrupts and put L1 on and then turn the power off and on, then everything will work fine with L1 protection.

It follows from this that the microcontroller can be transferred to such a state only if you put L1, then remove it, and then, without turning off and on the power, program it with interrupts, which will lead to the microcontroller going to the memory area> 1FFF0000. Then we turn the power off and on and see that at startup (after about 100ms) an interrupt comes (it happened in my program) and then the program goes to the > 1FFF0000 area, from where, as I understand it, SWD is no longer available. But at the same time, in the area> 1FFF0000, the microcontroller somehow freezes, since even the bootloader does not work.

Note 2: Tested with a clean program and a simple blinking LED

Here is the project: https://drive.google.com/file/d/1mtBmZHD-A3YecBccCb6P2EF2i0ArUBNG/view

- programmed, blinking works

- set L1

- removed L1 (memory erased)

- programmed the same program, by interrupt I go to 0x1fff0000

- in this state, turn off and turn on the power and after that the microcontroller is dead

Used STM32CubeIDE 1.11.2, STM32 ST-LINK Utility and ST link V2 programmer. PC win7 x64. I used ST-LINK Utility because I can't get STM32CubeProgrammer to work on Win7. Connecting the programmer according to the scheme: https://developer.arm.com/documentation/101761/1-0/Debug-and-trace-interface/Typical-SWD-circuit. If I forgot to mention something, - just ask.

Piranha
Chief II

Nothing is "dead" there, just use the proper connection mode:

Connect mode: Under Reset.

Reset mode : Hardware reset

The NRST has to be connected to the debugger and remove all of those 10k pull-up/down resistors, if you have those. The correct schematic is shown in AN5096.

FLASH->SR |= FLASH_SR_OPTVERR;
FLASH->SR |= FLASH_SR_FASTERR;
FLASH->SR |= FLASH_SR_MISERR;
FLASH->SR |= FLASH_SR_PGSERR;
FLASH->SR |= FLASH_SR_SIZERR;
FLASH->SR |= FLASH_SR_PGAERR;
FLASH->SR |= FLASH_SR_WRPERR;
FLASH->SR |= FLASH_SR_PROGERR;
FLASH->SR |= FLASH_SR_OPERR;

First, do not use an RMW operation ( |= ). Second, use a single operation for all the flags.

FLASH->SR = FLASH_SR_OPTVERR | FLASH_SR_FASTERR | FLASH_SR_MISERR |
	FLASH_SR_PGSERR | FLASH_SR_SIZERR | FLASH_SR_PGAERR |
	FLASH_SR_WRPERR | FLASH_SR_PROGERR | FLASH_SR_OPERR;