SPRAC21A June 2016 – June 2019 OMAP-L132 , OMAP-L138 , TDA2E , TDA2EG-17 , TDA2HF , TDA2HG , TDA2HV , TDA2LF , TDA2P-ABZ , TDA2P-ACD , TDA2SA , TDA2SG , TDA2SX , TDA3LA , TDA3LX , TDA3MA , TDA3MD , TDA3MV
The programming sequence to use the OCMC RAM ECC feature is:
Address Offset | 0x0 0044 | ||||
Physical Address | 0x4AE00 C144 | Instance | CTRL_MODULE_WKUP__Core_Registers | ||
Description | |||||
Type | RW |
Bits | Field Name | Description | Type | Reset |
---|---|---|---|---|
31:18 | Reserved | RO | 0x0000 | |
17 | EMIF1_NARROW_ONLY | EMIF1 ECC can be enabled | RW | 0 |
0: ECC cannot be enabled | ||||
1: ECC can be enabled | ||||
16 | EMIF1_EN_ECC | |||
15:14 | EMIF1_REG_PHY_NUM_OF_SAMPLES | RW | 0x0 | |
13 | EMIF1_REG_PHY_SEL_LOGIC | RW | 0 | |
12 | EMIF1_REG_PHY_ALL_DQ_MPR_RD_RESP | RW | 0 | |
11:9 | EMIF1_REG_PHY_OUTPUT_STATUS_SELECT | RW | 0x0 | |
8 | EMIF1_DYNAMIC_PWRDN_ENABLE | RW | 1 | |
7 | EMIF1_SDRAM_DISABLE_RESET | RW | 0 | |
6:5 | EMIF1_PHY_RD_LOCAL_ODT | RW | 0x0 | |
4 | EMIF1_STATIC_CMOSEN_ENABLE | RW | 0 | |
3 | EMIF1_DFI_CLOCK_PHASE_CTRL | RW | 0 | |
2 | EMIF1_EN_SLICE_2 | RW | 1 | |
1 | EMIF1_EN_SLICE_1 | RW | 1 | |
0 | EMIF1_EN_SLICE_0 | RW | 1 |
7-bit ECC is calculated over 32-bit data when in 32-bit DDR mode (reg_narrow_mode = 0). 6-bit ECC is calculated over 16-bit data when in 16-bit DDR mode (reg_narrow_mode = 1). The ECC is calculated for all accesses that are within the address ranges protected by ECC.
NOTE
Note that only EMIF1 supports ECC on TDA2xx and TDA2ex.
Bits | Field Name | Description | Type | Reset |
---|---|---|---|---|
31:16 | REG_ECC_END_ADDR_1 | End caddress [31:16] for ECC address range 1. The other 16 LSBs are always 0xFFFF. | R/W | 0x0 |
15:0 | REG_ECC_STRT_ADDR_1 | Start caddress [31:16] for ECC address range 1. The other 16 LSBs are always 0xFFFF. | R/W | 0x0 |
Bits | Field Name | Description | Type | Reset |
---|---|---|---|---|
31:16 | REG_ECC_END_ADDR_2 | End caddress [31:16] for ECC address range 2. The other 16 LSBs are always 0xFFFF. | R/W | 0x0 |
15:0 | REG_ECC_STRT_ADDR_2 | Start caddress [31:16] for ECC address range 2.The other 16 LSBs are always 0xFFFF. | R/W | 0x0 |
Example:
//EMIF_ECC_ADDRESS_RANGE_1 - 0x80000000 to 0x90000000
WR_MEM_32(0x4C000114, 0x0FFF0000);
//EMIF_ECC_ADDRESS_RANGE_2 - 0x90000000 to 0xA0000000
WR_MEM_32(0x4C000118, 0x1FFF1000);
CAUTION
The EMIF ECC region should not overlap; this can lead to unexpected results.
Bits | Field Name | Description | Type | Reset |
---|---|---|---|---|
31 | REG_ECC_EN | ECC enable | R/W | 0x0 |
0: ECC is disabled. | ||||
1: ECC is enabled. | ||||
30 | REG_ECC_ADDR_RGN_PROT | Setting this field to 1 and reg_ecc_en to a 1 will enable ECC calculation for accesses within the address ranges and disable ECC calculation for accesses outside the address ranges. The address ranges can be specified using the ECC Address Range 1 and 2 registers. | R/W | 0x0 |
29:2 | RESERVED | Reserved | R | 0x0 |
1 | REG_ECC_ADDR_RGN_2_EN | ECC address range 2 enable. | R/W | 0x0 |
0: ECC address range 2 is disabled. | ||||
1: ECC address range 2 is enabled. | ||||
0 | REG_ECC_ADDR_RGN_1_EN | ECC address range 1 enable. | R/W | 0x0 |
0: ECC address range 1 is disabled. | ||||
1: ECC address range 1 is enabled. |
NOTE
In DDR3 mode, software must trigger PHY initialization and full-leveling/calibration after enabling ECC for the first time. The ECC can then be enabled/disabled for test purposes without triggering full-leveling.
NOTE
ECC enable bit in CTRL_WKUP_EMIF_SDRAM_CONFIG_EXT register should be set even if ECC feature is not used.
Example:
if (ENABLE_ECC) //ECC Enabled
{
HW_WR_REG32(SOC_CTRL_MODULE_WKUP_CORE_REGISTERS_BASE +
CTRL_WKUP_EMIF1_SDRAM_CONFIG_EXT,
0x0001C127U); /* EMIF1_EN_ECC = 1 */
}
NOTE
EMIF must be set to non-interleaving mode so that the lower 2-GiB memory can be properly mapped to EMIF1 with ECC support and EMIF2 that doesn’t have ECC supported.
Example:
if (MEMMAP_2GB_NON_INTL_EMIFX2)
{
printf("Two EMIFs in non interleaved mode (2GB total)\n");
/* MA_LISA_MAP_i */
WR_MEM_32(0x482AF040, 0x80600100);
WR_MEM_32(0x482AF044, 0xC0600200);
/* DMM_LISA_MAP_i */
WR_MEM_32(0x4E000040, 0x80600100);
WR_MEM_32(0x4E000044, 0xC0600200);
}
Single bit errors are corrected by ECC logic. So user need not get worried about that. But in cases, when there are many single bit errors, this can potentially mean that something in the environment or the memory is not correct. Software may choose to be informed of such condition. For that purpose, EMIF controller provides means to interrupt when single bit error crosses a desired threshold. For details of the register, see Table 78.
Bits | Name | Description |
---|---|---|
31:24 | REG_1B_ECC_ERR_THRSH | 1-bit ECC error threshold. The EMIF will generate an interrupt when the 1-bit ECC error count is greater than this threshold. A value of 0 will disable the generation of interrupt. |
23:16 | RESERVED | RESERVED |
15:0 | REG_1B_ECC_ERR_WIN | 1-bit ECC error window in number of refresh periods. The EMIF will generate an interrupt when the 1-bit ECC error count is equal to or greater than the threshold within this window. A value of 0 will disable the window. Refresh period is defined by reg_refresh_rate in SDRAM Refresh Control register. |
This is again an optional step. Before enabling/using ECC, it is a good programming practice to clear any stale ECC error status. Table 79 and Table 80 should be cleared by writing 0x1 to it.
Bits | Name | Description |
---|---|---|
31:0 | REG_1B_ECC_ERR_ADDR | 1-bit ECC error address. Most significant bits of the starting address(es) related to the SDRAM reads that had a 1-bit ECC error. This field displays up to two addresses logged in the 4 deep address logging FIFO. Writing a 0x1 will pop one element of the FIFO. Writing a 0x2 will pop all elements of the FIFO. Writing any other value has no effect. |
Bits | Name | Description |
---|---|---|
31:0 | REG_2B_ECC_ERR_ADDR | 2-bit ECC error address. Most significant bits of the starting address of the first SDRAM burst that had the 2-bit ECC error. Writing a 0x1 will clear this field. Writing any other value has no effect. |
In order to receive interrupts, one should set the EMIF interrupt enable in the EMIF configuration space. The register description is shown in Table 81.
Bits | Name | Description |
---|---|---|
31:6 | Reserved | Reserved - writes are ignored, always reads zeros. |
5 | ONEBIT_ECC_ERR_SYS | Enabled status of sysem ECC one bit error correction interrupt. Writing a 1 will enable the interrupt, and set this bit as well as the corresponding Interrupt Enable Clear Register. Writing a 0 has no effect. |
4 | TWOBIT_ECC_ERR_SYS | Enabled status of system ECC two bit error detection interrupt. Writing a 1 will enable the interrupt, and set this bit as well as the corresponding Interrupt Enable Clear Register. Writing a 0 has no effect. |
3 | WR_ECC_ERR_SYS | Enabled status of system ECC Error interrupt when a memory access is made to a non-quanta aligned location. Writing a 1 will enable the interrupt, and set this bit as well as the corresponding Interrupt Enable Clear Register. Writing a 0 has no effect. |
2-1 | Reserved | Reserved |
0 | EN_ERR_SYS | Enable set for system OCP interrupt for command and address error. Writing a 1 will enable the interrupt, and set this bit as well as the corresponding Interrupt Enable Clear Register. Writing a 0 has no effect. |
Also, the SoC crossbar should be configured properly to receive the EMIF interrupt to the desired CPU. For example, for A15, SYSBIOS, below code needs to be added in configuration file.
var IntXbar = xdc.useModule('ti.sysbios.family.shared.vayu.IntXbar');
var Hwi = xdc.useModule('ti.sysbios.family.arm.gic.Hwi');
/* IRQ_CROSSBAR_105 EMIF1_IRQ. Interrupt 57 on A15 */
IntXbar.connectIRQMeta(57, 105);
var hwi_param_0 = new Hwi.Params;
hwi_param_0.arg = 0;
Hwi.create(57+32, '&emifErrIrqIsr', hwi_param_0);
There are other steps related to the below that are not listed but can be used and present in software provided by TI:
For more description on how to do these, see the TI software.
NOTE
When cache policy of WB (Write Back)/ WA (Write Allocate) is enabled on the CPU care should be taken to not have the cache lines being read from uninitialized ECC memory. Typically when the CPU cache is enabled in WB-WA mode and the CPU is trying to initialize the EMIF ECC enabled memory the cache line would be first read into the cache leading to the ECC controller to start reporting ECC errors. Additionally the initialization would reside in cache unless explicitly flushed to memory. The way to avoid errors from the ECC controller when using cache is to always initialize the ECC enabled memory before performing any read or write to cached ECC enabled memory region.
It is recommended to set the ECC enabled DDR memory as non-cacheable and strongly ordered during initialization, and then re-configure the memory regions as cacheable, write-back and write-allocate normal memory.
Example:
void setDDRnonCacheable()
{
UInt64 i;
Mmu_DescriptorAttrs attrs;
Mmu_initDescAttrs(&attrs);
attrs.type = Mmu_DescriptorType_BLOCK; // BLOCK descriptor
attrs.shareable = 2; // sharerable
attrs.attrIndx = 1; // Non-cache, strongly ordered
// Mmu_setMAIR(1, 0x04);
for (i=0x80000000; i < 0xA0000000; i = i + 0x00200000)
Mmu_setSecondLevelDesc((Ptr)i, (UInt64)i, &attrs);
}
void setDDRcacheable()
{
UInt64 i;
Mmu_DescriptorAttrs attrs;
Mmu_initDescAttrs(&attrs);
attrs.type = Mmu_DescriptorType_BLOCK; // BLOCK descriptor
attrs.shareable = 2; // sharerable
attrs.attrIndx = 2; // Cached, normal memory
// Mmu_setMAIR(2, 0xFF);
for (i=0x80000000; i < 0xA0000000; i = i + 0x00200000)
Mmu_setSecondLevelDesc((Ptr)i, (UInt64)i, &attrs);
}