Skip to main content
Graduate
July 10, 2024
Solved

STM32H750 RAMECC Testing

  • July 10, 2024
  • 1 reply
  • 2795 views

Hi,
I have been trying to trigger a RAM ECC error for testing. I have referenced the code Here. However, I cant trigger an ecc error.

The plan is to read uninitialized ram as mentioned in AN5342. I am using SRAM(1-3) (Mem address 0x30000000 - 0x30047FFF). Please find the code snippet below. 

 

RAMECC_HandleTypeDef hramecc2_m1;
RAMECC_HandleTypeDef hramecc2_m2;
RAMECC_HandleTypeDef hramecc2_m3;
RAMECC_HandleTypeDef hramecc2_m4;
RAMECC_HandleTypeDef hramecc2_m5;

#define SRAM_3_START 	(char*)0x30040000
#define SRAM_3_END 	(char*)0x30047FFF

#define SRAM_2_START 	(char*)0x30020000
#define SRAM_2_END 	(char*)0x3003FFFF

#define SRAM_1_START 	(char*)0x30000000
#define SRAM_1_END 	(char*)0x3001FFFF

static void MX_RAMECC_Init(void)
{
	/* USER CODE BEGIN RAMECC_Init 0 */

	/* USER CODE END RAMECC_Init 0 */

	/* USER CODE BEGIN RAMECC_Init 1 */

	/* USER CODE END RAMECC_Init 1 */

	/** Initialize RAMECC2 M1 : SRAM1_0
	 */
	hramecc2_m1.Instance = RAMECC2_Monitor1;
	if (HAL_RAMECC_Init(&hramecc2_m1) != HAL_OK)
	{
		Error_Handler();
	}

	/** Initialize RAMECC2 M2 SRAM1_1
	 */
	hramecc2_m2.Instance = RAMECC2_Monitor2;
	if (HAL_RAMECC_Init(&hramecc2_m2) != HAL_OK)
	{
		Error_Handler();
	}

	/** Initialize RAMECC2 M3 : SRAM2_0
	 */
	hramecc2_m3.Instance = RAMECC2_Monitor3;
	if (HAL_RAMECC_Init(&hramecc2_m3) != HAL_OK)
	{
		Error_Handler();
	}

	/** Initialize RAMECC2 M4 : SRAM2_1
	 */
	hramecc2_m4.Instance = RAMECC2_Monitor4;
	if (HAL_RAMECC_Init(&hramecc2_m4) != HAL_OK)
	{
		Error_Handler();
	}

	/** Initialize RAMECC2 M5 : SRAM3
	 */
	hramecc2_m5.Instance = RAMECC2_Monitor5;
	if (HAL_RAMECC_Init(&hramecc2_m5) != HAL_OK)
	{
		Error_Handler();
	}
	/* USER CODE BEGIN RAMECC_Init 2 */

	INIT_RAMECC(&hramecc2_m1);
	INIT_RAMECC(&hramecc2_m2);
	INIT_RAMECC(&hramecc2_m3);
	INIT_RAMECC(&hramecc2_m4);
	INIT_RAMECC(&hramecc2_m5);

	/* NVIC configuration for RAMECC interrupt */
	/* Priority: high-priority */
	HAL_NVIC_SetPriority(ECC_IRQn, 1, 0);
	HAL_NVIC_EnableIRQ(ECC_IRQn);

	/* USER CODE END RAMECC_Init 2 */
}

void INIT_RAMECC(RAMECC_HandleTypeDef* hramecc){
	/* Enable monitor notifications */
	/* ECC single error notification and ECC double error notification */
	if (HAL_RAMECC_EnableNotification(hramecc, (RAMECC_IT_MONITOR_SINGLEERR_R | RAMECC_IT_MONITOR_DOUBLEERR_R))!= HAL_OK)
	{
		Error_Handler();
	}

	/* Start Monitor : Enable latching failing information
	 Failing information : * Failing address
	 * Failing Data Low
	 * Failing Data High
	 * Hamming bits injected
	 */
	if (HAL_RAMECC_StartMonitor(hramecc) != HAL_OK)
	{
		Error_Handler();
	}

}

int main(void)
{

	/* USER CODE BEGIN 1 */
	CPU_CACHE_Enable();

	/* USER CODE END 1 */

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

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

	/* USER CODE BEGIN Init */

	/* 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();
	MX_RAMECC_Init();
	/* USER CODE BEGIN 2 */

	/* Analyse all memory */
	volatile uint32_t* mem_pointer = (volatile uint32_t*)SRAM_1_START;
	while(1){
		CurrentData = *mem_pointer;
		mem_pointer++;
		if(mem_pointer >= (volatile uint32_t*)SRAM_1_END){
			break;
		}
	}

	mem_pointer = (volatile uint32_t*)SRAM_2_START;
	while(1){
		CurrentData = *(mem_pointer);
		mem_pointer++;
		if(mem_pointer >= (volatile uint32_t*)SRAM_2_END){
			break;
		}
	}
	

	mem_pointer = (volatile uint32_t*)SRAM_3_START;
	while(1){
		CurrentData = *(mem_pointer);
		mem_pointer++;
		if(mem_pointer >= (volatile uint32_t*)SRAM_3_END){
			break;
		}
	}

	HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_13);


	/* USER CODE END 2 */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1)
	{
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */
		if(HAL_RAMECC_IsECCSingleErrorDetected(&hramecc2_m1) |
				HAL_RAMECC_IsECCSingleErrorDetected(&hramecc2_m2) |
				HAL_RAMECC_IsECCSingleErrorDetected(&hramecc2_m3) |
				HAL_RAMECC_IsECCSingleErrorDetected(&hramecc2_m4) |
				HAL_RAMECC_IsECCSingleErrorDetected(&hramecc2_m5)){

			HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET);
		}

		if(HAL_RAMECC_IsECCDoubleErrorDetected(&hramecc2_m1) |
				HAL_RAMECC_IsECCDoubleErrorDetected(&hramecc2_m2) |
				HAL_RAMECC_IsECCDoubleErrorDetected(&hramecc2_m3) |
				HAL_RAMECC_IsECCDoubleErrorDetected(&hramecc2_m4) |
				HAL_RAMECC_IsECCDoubleErrorDetected(&hramecc2_m5)){

			HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET);
		}

	}
	/* USER CODE END 3 */
}

 

 

Something I noticed is that even after a cold boot, the SRAM is still set to 0. Which would explain why an ecc error isn't triggered. 

snmunters_0-1720621950335.png

Any idea what Im missing? Thanks!

 

    This topic has been closed for replies.
    Best answer by snmunters

    I got it working finally.

    My initial code was right but it seems that the SRAM sectors I was looking at (D2 RAMECC Domain Unit) is initialized automatically on startup. By changing to D1- AXI SRAM, the code worked. This sector maintains random data on startup. Reading this random data will trigger an ECC error as the ECC hasnt been updated.

    My final code is attached below:

    1. Modified HAL RAMECC Init function

     

    static void MX_RAMECC_Init(void)
    {
    
    	/* USER CODE BEGIN RAMECC_Init 0 */
    
    	/* USER CODE END RAMECC_Init 0 */
    
    	/* USER CODE BEGIN RAMECC_Init 1 */
    
    	/* USER CODE END RAMECC_Init 1 */
    
    	/** Initialize RAMECC1 M1 : AXI SRAM
    	 */
    	hramecc1_m1.Instance = RAMECC1_Monitor1;
    	if (HAL_RAMECC_Init(&hramecc1_m1) != HAL_OK)
    	{
    		Error_Handler();
    	}
    
    	/* USER CODE BEGIN RAMECC_Init 2 */
    
    	/* Start Monitor : Enable latching failing information
    	 Failing information : * Failing address
    	 * Failing Data Low
    	 * Failing Data High
    	 * Hamming bits injected
    	 */
    	if (HAL_RAMECC_StartMonitor(&hramecc1_m1) != HAL_OK)
    	{
    		Error_Handler();
    	}
    
    
    	/* Enable monitor notifications */
    	/* ECC single error notification and ECC double error notification */
    	if (HAL_RAMECC_EnableNotification(&hramecc1_m1, (RAMECC_IT_MONITOR_SINGLEERR_R | RAMECC_IT_MONITOR_DOUBLEERR_R))!= HAL_OK)
    	{
    		Error_Handler();
    	}
    
    	/* NVIC configuration for RAMECC interrupt */
    	/* Priority: high-priority */
    	HAL_NVIC_SetPriority(ECC_IRQn, 0, 0);
    	HAL_NVIC_EnableIRQ(ECC_IRQn);
    
    	/* USER CODE END RAMECC_Init 2 */
    
    }

     

    2. HAL Detect Error Callback

     

    /**
     * @brief Single or double ECC error detected callback.
     * hramecc : RAMECC handle
     * @retval None
     */
    void HAL_RAMECC_DetectErrorCallback(RAMECC_HandleTypeDef *hramecc)
    {
    	if ((HAL_RAMECC_GetRAMECCError(hramecc) & HAL_RAMECC_SINGLEERROR_DETECTED) != 0U)
    	{
    		RAMECCSingleErrorDetected ++;
    	}
    
    	if ((HAL_RAMECC_GetRAMECCError(hramecc) & HAL_RAMECC_DOUBLEERROR_DETECTED) != 0U)
    	{
    		RAMECCDoubleErrorDetected ++;
    	}
    
    	hramecc->RAMECCErrorCode = HAL_RAMECC_NO_ERROR;
    
    	HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET);
    }

     

    3. ECC IRQ Handler added in main.c

     

    void ECC_IRQHandler(void)
    {
    	HAL_RAMECC_IRQHandler(&hramecc1_m1);
    }

     

    4. main

     

    RAMECC_HandleTypeDef hramecc1_m1;
    #define SRAM_AXI_START	(uint32_t*)0x24000000			//512kb
    #define SRAM_AXI_END	(uint32_t*)0x2407FFFF
    
    int main(void)
    {
    /* USER CODE BEGIN 1 */
    	CPU_CACHE_Enable();
    
    	/* USER CODE END 1 */
    
    	/* MCU Configuration--------------------------------------------------------*/
    
    	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    	HAL_Init();
    
    	/* USER CODE BEGIN Init */
    
    	/* 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();
    	MX_RAMECC_Init();
    	/* USER CODE BEGIN 2 */
    
    	// Initialise GPIO LED's
    	{
    		// GPIO_PIN_2 -> LD7 on board -> Green LED -> Lit when we enter the ECC Error callback function
    		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    		GPIO_InitStruct.Pull = GPIO_PULLUP;
    		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    
    		// Used to indicate an ECC RAM error has occurred
    		GPIO_InitStruct.Pin = GPIO_PIN_2;
    		HAL_GPIO_Init(GPIOJ, &GPIO_InitStruct);
    
    		// Reset
    		HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_SET);
    	}
    
    	uint32_t* mem_pointer4 = (uint32_t*)SRAM_AXI_START;
    
    	while(1){
    		CurrentData = *(mem_pointer4++);
    		if(mem_pointer4 >= (volatile uint32_t*)SRAM_AXI_END){
    			break;
    		}
    	}
    	while (1)
    }

     


     

    1 reply

    Graduate II
    September 20, 2024

    I am having the same issue. Were you ever able to figure this out?

    Technical Moderator
    September 26, 2024

    Hello @snmunters and  @20jmorrison 

    To generate a RAM ECC error, please follow these steps:

    1. Enable the RAMCFG clock and initialize the handle.
    2. Execute a mass erase.
    3. Start ECC.
    4. Write 32 bits of data.
    5. Stop ECC.
    6. Modify one bit within the previously written 32 bits of data.
    7. Start ECC and enable IT.
    8. Perform a data read.

    Graduate II
    September 26, 2024

    Hello,

    Thanks for the response! I was not able to find anything about how to enable the RAMCFG clock, could you please provide more detail on that?

    Additionally, is there any example code I could look at for generating RAMECC errors?

    Thanks again,

    Jared