cancel
Showing results for 
Search instead for 
Did you mean: 

How to use SRAM Parity in your application

MCU Support TD
ST Employee
Many of our microcontrollers provide the option to enable a parity check on SRAM via the option bytes. This feature becomes particularly useful when trying to get your product certified for safety critical applications, as without the parity check it would be necessary for the RAM to periodically perform a self-test, which can consume processing time and code space. The purpose of this article is to show how to enable and utilize SRAM parity in your application. This article will use the NULCEO-G071RB to demonstrate the process, but most of these steps will apply to all STM32 microcontrollers.

1. Enabling SRAM Parity in the Option Bytes

 

First, we must enable SRAM parity via the option bytes. There are multiple ways to do this, but this simplest way is to use STM32CubeProgrammer to program the option bytes via an SWD connection. Connect to the target board, then navigate to the option bytes tab. Under the User Configuration option bytes, uncheck the RAM_PARITY_CHECK box, and click apply. This will enable SRAM parity.

1325.png

1327.png

 

 

2. Ensure Linker File Reflects Potential SRAM Size Changes

On some MCUs, enabling parity for the SRAM will change the size of the SRAM. This is the case for the example MCU used in this article: the STM32G071RB.


1328.png

In the reference manual for the part, in the section regarding the embedded SRAM, it shows a table outlining how parity affects the size of SRAM. We need to ensure that the size of SRAM is defined correctly in the linker file. If it is not, the linker file will assign the stack to the end of SRAM assuming it is 36kB, but since it is 32kB now the stack will be assigned to a non-valid address. This will cause a hard fault. In the linker file STM32G071RBTX_FLASH.ld, change the size of the RAM to reflect enabled parity:
 

/* Memories definition */
MEMORY
{
	/* Commented out old memory defintion of 36kB */
  /* RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 36K */
  
  /* Parity changes SRAM size to 32kB */
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 32K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 128K
}

If you are experiencing a hardfault when enabling parity for SRAM, this could likely be the issue. Be sure to check in the reference manual for your MCU whether parity changes the size of the SRAM or not.
 

3. Initialize the SRAM in the Startup File.

It is necessary to initialize the SRAM in the startup file before any other operations occur. Since the SRAM parity will automatically write the parity bit when an SRAM address is written to, initializing SRAM in startup before anything else occurs will avoid the possibility of reading an SRAM address that hasn’t been initialized and therefore doesn’t have the correct parity bit. In the startup file, startup_stm32g071rbtx.s, add a loop that initializes SRAM to all 0’s. This should be done right at the beginning of Reset_Handler.

Reset_Handler:
/* Start SRAM init */
  ldr r1, =0x20000000  // start address of SRAM
  ldr r2, =0x20008000  // end address of SRAM
  movs r3, #0   // we want to write 0 to all address
initializeSRAM:
  str r3, [r1]   // store 0 at address
  adds r1, r1, #4  // increment to next address
  cmp r1, r2   // update flags
  bne initializeSRAM // branch if write address equals end of SRAM
/* End SRAM Init */
/* Rest of reset handler continues below */


 

4. Modifying the NMI_Handler Interrupt to Handle Parity errors.

When a parity error occurs, the processor throws an NMI interrupt. To handle a parity error, the SRAM_ PEF in the SYSCFG_CFGR2 is checked:


1330.png

As can be seen above, the SRAM_PEF is labeled as a rc_w1. This means it is readable, and it is also cleared by writing 1 to it. Knowing this, we can perform the parity error handling in the NMI_Handler. In the file, stm32g0xx_it.c, we need to add the following code the USER CODE BEGIN NonMaskableInt_IRQn 0 in the NMI_Handler:

void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
  /* Read the parity error flag to see if parity error occurred */
  if (SYSCFG->CFGR2 & 1<<8)
  {
	  /* You can handle the error here however you see fit */

	/* Clear bit if desired */
	SYSCFG->CFGR2 |= 1<<8;
  }
  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
  while (1)
  {
  }
  /* USER CODE END NonMaskableInt_IRQn 1 */
}

5. Intentionally triggering parity error to test functionality

Unfortunately, there is no way to consistently trigger a parity error. The steps to trigger the parity error somewhat regularly using CubeIDE are below. This is solely intended to prove to yourself that the parity error checking is indeed enabled and working as expected.
 

  1. To make it easier to see when the error occurs, turn on an LED when parity error occurs, and add a while(1) to stop execution in the parity error check:

void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
  /* Read the parity error flag to see if parity error occurred */
  if (SYSCFG->CFGR2 & 1<<8)
  {
              // A parity error has occurred
              HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, 1);
              while(1){}

  }
  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
  while (1)
  {
  }
  /* USER CODE END NonMaskableInt_IRQn 1 */
}

  1. Comment out the assembly code in the startup file that initializes SRAM so that we can induce a parity error by reading uninitialized RAM.

  2. Build the code and start debugging. By default the execution will stop on the first line of main(). Continue execution, then pause. This should have you stopped in the main while(1) loop. While execution is paused, open the memory browser window and type the beginning of SRAM (0x2000 0000) into the browser. Scroll through SRAM in the memory browser until you see some values that are unreadable (????) and interspersed with garbage values:


1332.png
 

  1. Now continue execution.

  2. The LED should turn on, indicating a parity error. You can pause debugging to see that program execution is now inside parity error check:


1333.png
 

Comments
ABals.2
Associate II

How to enable the SRAM parity bit through code instead of using STM32CubeProgrammer, 

I am trying to enable the SRAM parity check, code snippet is as follows:

FLASH_OBProgramInitTypeDef config;
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
HAL_FLASHEx_OBErase();
HAL_FLASHEx_OBGetConfig(&config);
config.USERConfig = 0x00;
HAL_FLASHEx_OBProgram(&config);
HAL_FLASH_OB_Launch();
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();

The code gets stuck at HAL_FLASH_OB_Launch(); and the IAR IDE hangs and exits out of debug mode.

Version history
Last update:
‎2022-11-10 05:26 AM
Updated by: