cancel
Showing results for 
Search instead for 
Did you mean: 

last-written byte of ITCM apparently getting modified by NVIC_SystemReset();

TallMike
Associate III

We're running into a really weird situation with a bootloader that copies some code into ITCM.  The bootloader initializes various peripherals and clocks and then copies data from the QSPI flash to both the SRAM and to the ITCM memory.  Then we use the NVIC_SystemReset() call to fully reset everything (apparently there's an Errata that some things don't get properly de-initialized unless a full reset is called).  But we are running into a very strange situation whereby it looks like the last byte that was written into ITCM gets corrupted by the SystemReset call!  We've tried a few things like settng  the ITCM to not be cacheable and calling SCB_CleanDCache before doing the reset.  It always seems to be  the last byte written.  As a test, I used memset to zero-out an additional 35 bytes, and the problem happened at the last byte of the memset.  The value seems to be possibly related to some other ITCM contents (e.g. if I zero out the entire ITCM before copying the the code, then the 'bad' value is 0, otherwise it's some other value e.g. 0x1b.  How does it even know what the last-written address is?  The same copy function is then used to copy to SRAM, so it doesn't seem likely that it's some register value.  I'm Shook!

 

1 ACCEPTED SOLUTION

Accepted Solutions

For all internal SRAM having ECC, all write operations followed by a system reset is affected by the same behavior. So you need to add a dummy write to the same memory to avoid the behavior.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

View solution in original post

7 REPLIES 7
SofLit
ST Employee

Hello @TallMike ,

You need to provide the exact MCU part number. Please check Tips on posting.

If I understand well, the issue is not related to the bootloader but to a behavior to ITCM memory?

So if someone writes a 10 length bytes buffer to ITCM RAM , do you mean that after reset the last byte i.e. 10th byte will be wrong?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Right, sorry, here's the part number:;STM32H750IB 

And correct, it's not a per-se bootloader issue, it's a System Reset issue,

And yes your understanding is correct:  the last byte (e.g. the 10th) will get modified.

 

    *((unsigned long *)TOP_OF_RAM) = 0xDEADCAFE; 
    __DSB(); // Fence
...   
    NVIC_SystemReset();
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Is this an actual valid solid solution?  I would be worried that it does other unexpected things too unless this is a known issue?

Hello @TallMike ,

I reproduced the behavior with this sample code:

  #define ITCM_BASE_ADDRESS  0x0
  #define PATTERN            0x55
  uint8_t *Buffer = NULL;
  uint8_t Button_pressed = 0;
  
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
  Buffer = (uint8_t*)ITCM_BASE_ADDRESS;
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if(Button_pressed == 1)
		{
			for(uint32_t i = 0; i<16; i++)
			{
				*(Buffer+i) = PATTERN;
			}
			NVIC_SystemReset();
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == USER_BUTTON_Pin)
  {
    /* Toggle LED1 */
		Button_pressed = 1;
    
  }
}

 And it's a behavior caused by the ECC controller.  In fact all write access go through ECC controller before to be written in the RAM. In your case, when you write the last byte and you reset the MCU, that byte still in the ECC controller and didn't reach the memory. As a workaround, after writing the last byte, do a dummy byte write to the memory. Please, refer to the AN5342 "How to use error correction code (ECC) management for internal memories
protection on STM32 MCUs" / Page 17:

SofLit_0-1729072944775.png

This is how I worked around the behavior:

  #define ITCM_BASE_ADDRESS  0x0
  #define PATTERN            0x55
  #define ITCM_LAST_BYTE_ADDRESS  0xFFFF
  uint8_t *Buffer = NULL;
  uint8_t Button_pressed = 0;
  
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
  Buffer = (uint8_t*)ITCM_BASE_ADDRESS;
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if(Button_pressed == 1)
		{
			for(uint32_t i = 0; i<16; i++)
			{
				*(Buffer+i) = PATTERN;
			}
			*(uint8_t*)ITCM_LAST_BYTE_ADDRESS = 0; // Dummy write after an effective last byte write
			NVIC_SystemReset();
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == USER_BUTTON_Pin)
  {
    /* Toggle LED1 */
		Button_pressed = 1;
    
  }
}

  Hope it does answer your question.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Thanks for the info!  And wow! 

One other question: does this also happen when writing to SRAM?  We are also copying to SRAM.  Does it have the same issue as well?  I didn't get a chance to do a test for that.

For all internal SRAM having ECC, all write operations followed by a system reset is affected by the same behavior. So you need to add a dummy write to the same memory to avoid the behavior.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.