for our application , we need to enable ECC in OCRAM and DDR3 and we use Vybrid Tower kit TWR-VF65GS10.
1) On-Chip Memory Controllers
In chapter 65 of Vybrid reference manual version 5 , it is written
"... The OCRAM_sys ECC function can be summarized in the following steps. Consider reads and writes
separately.
For data writes received by the OCRAM_sys memory controller:
• If enabled, the ECC logic generates the 8-bit checkbit field based on the 29-bit address + 64-bit data
• The 64 data bits + 8 checkbits are stored in the memory ...
&
Note standard ECC operation requires that the entire memory be written during system startup to
“initialize” correct checkbit values for all locations before read operations can be checked. To assist in this
process, the device implements two independent control flags for each OCRAM_sys controller: one that
enables checkbit generation on writes and another to enable checking on read operations. The memory
initialization writes can be performed directly by a processor or an appropriately configured DMA
channel."
When I am reading the paragrah above , it seem we need to enable and modify some register to activate the ECC but I have searched in reference Manual and I didn't find how initialize the controller to activate ECC
What is the process to enable the ECC on OCRAM ?
2) DDR3
I use the following procedure to enable ECC on DDR3
- I written the field ctrl-raw with value " ECC reporting is on, but no attempts to correct. or ECC reporting and correcting on" in register DDRMC_CR_57
- I set the field REDUC in register DDRMC_78
- I initialize the DDR3 with value 0xFFFFFFFF
- I enable the DDRMC interrupt to catch any issue
When I read the DDR3 memory with the following width32, 64, 128, 256 bits , it's OK
When I written the DDR3 memory with the following width 128, 256 bits , it's OK
but I written the DDR3 memory with the following width 32 or 64 bits , then the cortex A5 crashed and I need push the button reset
is that someone has already had this problem?
Thanks for any help
Regards
FRancois
jiri-b36968 do you have an update?
Hi,
not yet
/Jiri
hi
Do you need more information ?
Br
francois
Hi Francois,
sorry need more time
/Jiri
Hi Francois,
I just want inform you: keep on working.
/Jiri
Hi Francois,
had to create new project to test the issue. Now DS-5 project is prepared with Caches and MMU setting and I'm testing your use case. You wrote that you have problem with ECC on OCRAM, but in the function ecc_32bit_test() is uint32 memStart = 0x80000000; this is SDRAM (DDR3). Please confirm.
/Jiri
hi jiri
In this benchmark , I create an assembler function to enable ECC OCRAM and initialize the OCRAM . the name of this function is ca5_ocram_ecc_stack_init in cortex_a5_test.s
the stack is located in OCRAM1
When ECC is enable and after execute this function , We have the following behaviour
benchinit()
->MMUConfigAndEnable();
->ca5_ocram_ecc_stack_init(); ( ECC Enable )
->perf_init(PerfMonEventSelect);
-> push ( write OCRAM1 )
-> _pmuInit_()
-> push ( write OCRAM1 )
...
-> pop ( read OCRAM1 ) -> ECC error
In the function ca5_ocram_ecc_stack_init, when I disable the following instruction , then it's ok
| ; enable ECC read | |
| mov r3,#0x3 | |
| str r3,[r0,#0x4] |
Br
francois
Hi Francois,
OK. your error happens when you try to read from the stack. I assume that mov r3,#0x3 and str r3,[r0,#0x4] configure OCMDR1 register and enables ECC read check. When you erase those instructions then ECC read check is not enabled so then ECC read error is not raised. Just for sure: You copied stack into OCRAM1. Did you checked if target space where stack is located is initiated (if stacker points are correctly replaced)?
Let me summarize it:
It happening when
REGION regionOcmc = { MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC, MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_NON_CACHEABLE, MMU_NON_CACHEABLE), MMU_REGION_NON_SECURE,MMU_AP_PRV_RW_USR_RW,
(unsigned int*)pageTable
};
but it is not happening when
REGION regionOcmc = { MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC, MMU_MEMTYPE_DEVICE_NON_SHAREABLE, MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
(unsigned int*)pageTable
};
right ?
Are you using just L1 cache (I,D) or also L2 cache ?
Did you try to enable ECC prior to stack creation during init code?
/Jiri
Hi Francois,
OK. your error happens when you try to read from the stack. I assume that mov r3,#0x3 and str r3,[r0,#0x4] configure OCMDR1 register and enables ECC read check. When you erase those instructions then ECC read check is not enabled so then ECC read error is not raised. Just for sure: You copied stack into OCRAM1. Did you checked if target space where stack is located is initiated (if stacker points are correctly replaced)?
FJ->YES
Let me summarize it:
It happening when
REGION regionOcmc = { MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC, MMU_MEMTYPE_NORMAL_NON_SHAREABLE(MMU_NON_CACHEABLE, MMU_NON_CACHEABLE), MMU_REGION_NON_SECURE,MMU_AP_PRV_RW_USR_RW,
(unsigned int*)pageTable
};
but it is not happening when
REGION regionOcmc = { MMU_PGTYPE_SECTION, START_ADDR_OCMC, NUM_SECTIONS_OCMC, MMU_MEMTYPE_DEVICE_NON_SHAREABLE, MMU_REGION_NON_SECURE, MMU_AP_PRV_RW_USR_RW,
(unsigned int*)pageTable
};
right ?
FJ-> YES
Are you using just L1 cache (I,D) or also L2 cache ?
FJ->We don't use L2 Cache
Did you try to enable ECC prior to stack creation during init code?
FJ->NO
Hi Francois,
I can finally confirm the issue in OCRAM when ECC is enabled (8,16,32 bit write access). Memory access cause precise abort when:
All is OK when:
So cache + ecc does not work correctly. It needs to be discussed with the designer and ARM.
Nevertheless when the stack is in OCRAM our default setting which is strong order(device) is preferred.
/Jiri
hi jiri
Ok , we will use strong order and ECC and we will wait an answer
Do you think that it's the same issue with ECC on DDR3 ?
Br
francois
Hi Francois,
Designers working on it. I do not think that same issue could be on DDR. ECC is part of given memory. Do you see any other troubles with ECC and DDR? I presume that we have solved everything in previous communication.
/Jiri
hi jiri
02/17 , I sent you 2 zip file for 2 issue
1 -> ecc_ocram_issue.zip for OCRAM issue
2->ecc_ddr3_issue.zip for DDR3 issue
Br
francois
Hi Francois,
I'm sorry. I thought that it was solved - moreover I had to use my own project.
So the issue is this? You wrote "but I written the DDR3 memory with the following width 32 or 64 bits , then the cortex A5 crashed and I need push the button reset"
Is it also happening when cache is set to write though and not happening when set to strong order, device or non cached?
/Jiri
hi jiri
condition
No CACHE enable , NO MMU enable
In the project ecc_ddr3_issue.zip , in function sysinit , We call the function user_testcase.
sysinit
-> user_testcase
.....
->ecc_32bit_test
-> enable ECC and initialize ECC on DDR3 ( base addr =0x80000000)
-> loop read DDR3 at 0x80000000
->loop write DDR3 at 0x80000000
-> ca5_bench_ecc_test()
LDR r0,=ReadBase_ADDR=0x80000000
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r6}
LDR r0,=ReadBase_ADDR
STMIA r0!,{r3-r4} -> crash
LDR r0,=ReadBase_ADDR
When ECC ddr3 is disable , this test is ok
francois
Hi Francois,
I was able to replicate the abort event. It happen when:
so please ensure that in your init code
After some cleaning DS-5 project will be available. So far my init code is:
void ecc_sdram_init(void)
{
uint32 memStart = 0x80000000;
uint32 memSize = 0x1000000;
uint32 i;
/* Clear ECC errors in IN_STAT DDRMC_CR80 */
reg32_write(DDR_CR081, 0x00000078);
/* Re-configure the DDR controller for an 8-bit port width; reduc = 1*/
reg32_write(DDR_CR078, 0x0000010c);
// reduc = 1
//reg32_write(DDR_CR078, 0x0700010c); // q_fullness reduc
/* Enable ECC - reporting and correcting on; ctrl_raw = 11 */
reg32_write(DDR_CR057, 0x03000000);
/* Need to disable checking on partial writes to get test to pass */
reg32_write(DDR_CR058, 0x01000000);
printf("Writing initial values to SDRAM\n");
for (i = 0; i < memSize; i = i + 4)
{
//*(uint32 *) (memStart + i) = memStart + i;
*(uint32 *) (memStart + i) = 0x0;
}
printf("SDRAM Initialization Complete!\n");
}
/Jiri
hi jiri
Ok I initialize the memory at 0x0 but I have always the same issue ( why we need initialise the memory at 0 and not an other value ?)
the instruction for disable checking on partial writes reg32_write(DDR_CR058, 0x01000000) is not missing
and at the end of memory initialisation , we must enable the correction reg32_write(DDR_CR058, 0x00000000)
ECC_DIS_WCRER
Disables automatic corruption of the ECC codes for an entire user word when the read portion of a read/
modify/write operation has an un-correctable error. If this is not disabled, the corruption will occur even if
the erroneous byte is overwritten with new data.
0 Allow the ECC codes for the entire user word to be corrupted. (Default)
1 Disable the corruption. The ECC codes written to memory will match the new write data written to
memory.
after I have always the error
-> ca5_bench_ecc_test()
LDR r0,=ReadBase_ADDR=0x80000000
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r6}
LDR r0,=ReadBase_ADDR
STMIA r0!,{r3-r4} -> crash
LDR r0,=ReadBase_ADDR
I join the code modified
Hi Francois,
ECC check is enabled in CR57 (reg32_write(DDR_CR057, 0x03000000); ) not in DDR_CR058.
I tried also to allow corruption after correct memory initiation by reg32_write(DDR_CR058, 0x00000000);
No issue found. Data are correctly stored in the memory and there are no EEC errors in DDR_CR80. Code and dis-assembly below.
My program (compiler) uses STRB, STBH and STB instructions for store 8,16 and 32 bits data, LDR,LDRH, LDRB for load. Exact work of STMIA, you use, can be find in ARM documentation, but ECC_DIS_WCRER bit is here especially in the case of CPU access to ECC protected SDRAM memory.
Confirm that you see no issues when line reg32_write(DDR_CR058, 0x00000000); is removed. Maybe you can try to use STR instructions also.
/Jiri
/* init of ECC check in SDRAM function */
void ecc_sdram_init(void)
{
uint32 memStart = 0x80000000;
uint32 memSize = 0x1000000;
uint32 i;
/* Clear ECC errors in IN_STAT DDRMC_CR80 */
reg32_write(DDR_CR081, 0x00000078);
/* Re-configure the DDR controller for an 8-bit port width; reduc = 1*/
reg32_write(DDR_CR078, 0x0000010c);
//reg32_write(DDR_CR078, 0x0700010c); // q_fullness reduc
/* Enable ECC - reporting and correcting on; ctrl_raw = 11 */
reg32_write(DDR_CR057, 0x03000000);
/* Need to disable checking on partial writes to get test to pass */
reg32_write(DDR_CR058, 0x01000000);
printf("Writing initial values to SDRAM\n");
for (i = 0; i < memSize; i = i + 4)
{
//*(uint32 *) (memStart + i) = memStart + i;
*(uint32 *) (memStart + i) = 0x0;
}
printf("SDRAM Initialization Complete!\n");
/* Allow the ECC codes for the entire user word to be corrupted */
reg32_write(DDR_CR058, 0x00000000);
}
void ecc_sdram_test(void)
{
uint32 memStart = 0x80000000;
uint32 memEnd = 0x81000000;
uint32 memIncrement = 0x0100;
uint32 i;
for (i = memStart; i < memEnd; i = i + memIncrement)
{
printf("Testing SDRAM memory \n");
mem8_write(i, (uint8_t) pattern);
mem16_write(i+2, (uint16_t) pattern);
mem32_write(i+4, (uint32_t) pattern);
printf("Adress:%08x i8:%02x i16:%04x i32: %08x \n", i, mem8_read(i), mem16_read(i+2), mem32_read(i+4));
mem8_write(i, (uint8_t) antipattern);
mem16_write(i+2, (uint16_t) antipattern);
mem32_write(i+4, (uint32_t) antipattern);
printf("Adress:%08x i8:%02x i16:%04x i32: %08x \n", i, mem8_read(i), mem16_read(i+2), mem32_read(i+4));
}
}
hi jiri
I forgot to tell you that only this exact sequence kills the processor
( if you suppress one STMIA , then it's work )
ca5_bench_ecc_test
push {r3-r12,r14}
;init parameter
LDR r0,=ReadBase_ADDR
;init limit
LDR r2,=ReadLimit
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r10}
STMIA r0!,{r3-r6}
LDR r0,=ReadBase_ADDR
STMIA r0!,{r3-r4} - > crash
LDR r0,=ReadBase_ADDR
hi
thank you for document
francois