2024-07-10 07:39 AM
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.
Any idea what Im missing? Thanks!
Solved! Go to Solution.
2024-10-10 09:05 AM - edited 2024-10-10 09:25 AM
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)
}
2024-09-20 12:10 PM
I am having the same issue. Were you ever able to figure this out?
2024-09-26 05:42 AM
Hello @snmunters and @20jmorrison
To generate a RAM ECC error, please follow these steps:
2024-09-26 01:31 PM
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
2024-10-01 06:27 AM - edited 2024-10-01 06:28 AM
Hey. I tried your recommendation but still no luck. Please find the code used below.
I notice that when stepping through, writing to the sram shows no change in value. Could that be indicative of something wrong?
I have also assumed the HAL generated init functions are configuring the clock of the ramecc as you mentioned.
Thank you for your help!
main loop:
#define SRAM_3_START (uint32_t*)0x30040000
#define SRAM_3_END (uint32_t*)0x30047FFF
#define SRAM_2_START (uint32_t*)0x30020000
#define SRAM_2_END (uint32_t*)0x3003FFFF
#define SRAM_1_START (uint32_t*)0x30000000
#define SRAM_1_END (uint32_t*)0x3001FFFF
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();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_RAMECC_Init();
/* USER CODE BEGIN 2 */
volatile uint32_t* mem_pointer1 = (volatile uint32_t*)SRAM_1_START;
volatile uint32_t* mem_pointer2 = (volatile uint32_t*)SRAM_2_START;
volatile uint32_t* mem_pointer3 = (volatile uint32_t*)SRAM_3_START;
/* Execute a mass erase */
memset(SRAM_1_START, 0, sizeof(uint8_t)*0x7FFF); // 32 kb
memset(SRAM_2_START, 0, sizeof(uint8_t)*0x1FFFF); // 128 kb
memset(SRAM_3_START, 0, sizeof(uint8_t)*0x1FFFF); // 128 kb
/* Start RAM ECC */
START_RAMECC(&hramecc2_m1);
START_RAMECC(&hramecc2_m2);
START_RAMECC(&hramecc2_m3);
START_RAMECC(&hramecc2_m4);
START_RAMECC(&hramecc2_m5);
/* Write to memory location */
*mem_pointer1 = (uint32_t)0x12345678;
*mem_pointer2 = (uint32_t)0x12345678;
*mem_pointer3 = (uint32_t)0x12345678;
/* Stop RAM ECC */
STOP_RAMECC(&hramecc2_m1);
STOP_RAMECC(&hramecc2_m2);
STOP_RAMECC(&hramecc2_m3);
STOP_RAMECC(&hramecc2_m4);
STOP_RAMECC(&hramecc2_m5);
/* Modify 1 bit of data in memory location */
*mem_pointer1 ^= 0x00000001; // Flip one bit
*mem_pointer2 ^= 0x00010000;
*mem_pointer3 ^= 0x10000000;
/* Start ECC */
START_RAMECC(&hramecc2_m1);
START_RAMECC(&hramecc2_m2);
START_RAMECC(&hramecc2_m3);
START_RAMECC(&hramecc2_m4);
START_RAMECC(&hramecc2_m5);
/* Enable Interrupts */
ENABLE_RAMECC_INT(&hramecc2_m1);
ENABLE_RAMECC_INT(&hramecc2_m2);
ENABLE_RAMECC_INT(&hramecc2_m3);
ENABLE_RAMECC_INT(&hramecc2_m4);
ENABLE_RAMECC_INT(&hramecc2_m5);
/* Read Data */
while(1){
CurrentData = *mem_pointer1;
mem_pointer1++;
if(mem_pointer1 >= (volatile uint32_t*)SRAM_1_END){
break;
}
}
while(1){
CurrentData = *mem_pointer2;
mem_pointer2++;
if(mem_pointer2 >= (volatile uint32_t*)SRAM_2_END){
break;
}
}
while(1){
CurrentData = *mem_pointer3;
mem_pointer3++;
if(mem_pointer3 >= (volatile uint32_t*)SRAM_3_END){
break;
}
}
while(1);
}
CubeMX 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 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 */
/* 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 */
}
Helper functions:
void ENABLE_RAMECC_INT(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();
}
}
void START_RAMECC(RAMECC_HandleTypeDef* hramecc){
/* 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();
}
}
void STOP_RAMECC(RAMECC_HandleTypeDef* hramecc){
if (HAL_RAMECC_StopMonitor(hramecc) != HAL_OK)
{
Error_Handler();
}
}
Callback Functions:
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);
}
void ECC_ErrorCallback(RAMECC_HandleTypeDef *hramecc)
{
HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET);
// Handle the ECC error
while(1);
}
2024-10-01 07:17 AM
Hello @snmunters ,
See this thread.
2024-10-01 07:38 AM
Hello @SofLit,
I authored the post you linked, is that really the recommended way of triggering a ram ecc error? I made the post because it was literally the only way I was able to figure out how to inject an error. Any feedback would be appreciated.
-Jared
2024-10-01 07:46 AM
Hi Sof,
That post is completely different from the steps you recommended.
As far as I understand, @20jmorrison seems to be reading uninitialized memory
I'm a little confused now?
Thanks!
2024-10-01 08:02 AM
To emulate an ECC error you need to read from an initialized memory.
2024-10-10 09:05 AM - edited 2024-10-10 09:25 AM
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)
}