RT1170 CMSIS DAP+IDE debug based on ECC enabled

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RT1170 CMSIS DAP+IDE debug based on ECC enabled

RT1170 CMSIS DAP+IDE debug based on ECC enabled

RT1170 CMSIS DAP+IDE debug based on ECC enabled

1.    Abstract

This article aims to solve the problem that after enabling the ECC function, RT1170 cannot be debugged using CMSIS DAP in the three major IDEs (MCUXpresso, IAR, MDK). ECC is enabled by burning the relevant fuses and enabling ROM preloading, which means that the ROM will help initialize the RAM. However, in actual use, it is found that different debuggers have different appearances on the IDE. For example, Segger JLINK can directly implement debugging, but when CMSIS DAP is combined with the three major IDEs, there will be a problem that the code cannot be debugged after being downloaded to RAM. Here, taking MCUXpresso IDE as an example, after burning the ECC-related fuses on the MIMXRT1170-EVK board, if the project is burned to RAM, it can be debugged directly. However, if the project is burned to flash, there will be problems with flashloader:

1.jpg

Fig 1

   So is this problem caused by the mismatch of flashloader, or does it require additional operations? This article will give a specific solution!

2. RT1170 ECC basic enable and solution

2.1 RT1170 ECC basic

   ECC stands for Error Correcting Code, which can detect and correct memory errors. So what ECC does RT1170 have? They are: MECC64, XECC, FlexRAM ECC.

  • MECC64

MECC64 supports 1-bit error correction and 2-bit error detection,to 2bit, it cannot correct errors, just detect the error. MECC64 is mainly protects OCRAM1 and 2 in the chip. MECC1 protects OCRAM1, and MECC2 protects OCRAM2. OCRAM1 ECC and OCRAM2 ECC are used to store ECC check values. If ECC64 is not enabled, it can be used as a normal OCRAM. An 8-bit ECC check value (8 bits) is calculated for every 64 bits of data. The ECC algorithm is Hsiao Hamming.

  • XECC

XECC is External ECC controller, which is used to provide ECC function for external storage space. XECC supports 1-bit error correction and 2-bit error detection. External memory includes XECC_FLEXSPI1, XECC_FLEXSPI2, and XECC+SEMC. XECC can calculate a 4-bit ECC check value for every 4 bits. The XECC check value is immediately following the original value. For example, for a 32-bit data, a 4-bit ECC check value is generated for every 4 bits. 32-bit original data needs to generate 32-bit ECC check data, which requires a total of 64 bits of space. Algorithm: Hsiao Hamming algorithm

  • FlexRAM ECC

FlexRAM ECC is used to protect the ITCM, DTCM and OCRAM of FlexRAM. It supports 1-bit error correction and 2-bit error detection. A 7/8-bit ECC check value is calculated for every 4 bytes of DTCM or 8 bytes of ITCM/OCRAM, and the ECC check value is placed in the ECC RAM.

2.2 RT1170 ECC enable

   The method used in this article to enable ECC is to directly enable the relevant fuse bit.

- MECC_ENABLE (0x840[2]) = 1

- XECC_ENABLE (0x840[3]) = 1

- ROM preloading (0x950[0]) = 1

- FLEXRAMECC_ENABLE (0x840[15]) = 1

For more software configuration information, please refer to the official application note AN13204:

https://www.nxp.com/docs/en/application-note/AN13204.pdf

The following is the situation after burning the relevant fuses. Burning the fuses can enter the serial download mode and use MCUbootutility to burn:

2.jpg

Fig 2

2.3 ECC debug issue solution methods

After testing in many ways, such as initializing RAM in the script, because of the characteristics of ECC, RAM needs to be flashed once, but it is found that the general code speed of flashing RAM directly is too slow, resulting in download timeout problems, and then it is changed to use DMA to move data to RAM to ensure that RAM is flashed once, but the result is still not good, so flashing RAM is not the fundamental way to solve the debug problem. Finally, by chance, ECC is turned off in the connection script first, especially FlexRAM ECC, and it is found that the burning algorithm can be called to perform external flash operations at this time. In this way, the code can be successfully downloaded, and then reset to let the ROM turn on the ECC function by itself.

The reason why the RAM project can work is that the process of downloading RAM is a process of flashing RAM, so the RAM code can work directly.

For the debugger burning and simulation of Flash code, it is still necessary to turn off the ECC module first, mainly the FlexRAM ECC module. Of course, for the sake of insurance, we can directly turn off all MECC and FlexRAM ECC register enable bits, let the flashloader work first, and directly control the register address:

0x40014100=00x40018100=00x40028108=0

  • 0x40014100 PIPE_ECC_EN[ECC_EN], control MECC1
  • 0x40018100 PIPE_ECC_EN[ECC_EN], control MECC2

3.jpg

Fig 3

  • 0x40028108 FLEXRAM_CTRL ECC_EN, control FlexRAM ECC
4.jpg

Fig 4

According to the actual test situation, disabling FlexRAM ECC is effective. The problem should be that the area where the flashloader used is stored is the DTCM of FlexRAM. Check the area of ​​the Flashloader of the burning algorithm as follows:

5.jpg

Fig 5

3  Three major IDEs script and testing

Here, share the three IDE(MCUXPresso, IAR, MDK)+CMSIS DAP+ECC related modified script file.

3.1 MCUXpresso IDE

Script path in the IDE:

C:\nxp\MCUXpressoIDE_11.9.0_2144\ide\LinkServer\binaries\Scripts

Prepare one script file T1170_connect_M7_wake_M4_ecc.scp,copy it to the above path, and the content is:

1 REM ======================================
2 REM Copyright 2020-2024 NXP
3 REM All rights reserved.
4 REM SPDX-License-Identifier: BSD-3-Clause
5 REM ======================================

100  REM =======================================================================
110  REM RT1170_connect_M7_wake_M4.scp
150  REM =======================================================================
160  PRINT "RT1170 Connect M7 and Wake M4 Script"
170  REM =======================================================================
180  REM Uncomment ProbeList for standalone script use (outside the stub)
190  REM =======================================================================
200  REM ProbeList
210  p% = ProbeFirstFound
220  REM ProbeOpenByIndex p%
230  WireSwdConnect p%
240  SelectProbeCore p% 0
250  CMInitApDp this
252  REM =======================================================================
254  REM Disable ECC
256  GOSUB 1500
260  REM =======================================================================
270  REM The M4 AP is not visible while the core is held in reset
280  REM Prepare a spin code in RAM and wake up / reset the M4 to it
290  REM This serves two purposes:
300  REM   - enables the M4 AP, required for debug visibility
310  REM   - prevents M4 code from interfering with flash programming on M7
320  REM =======================================================================
330  REM Prepare spin code
340  GOSUB 1000
350  REM =======================================================================
360  PRINT "Setting M4 clock"
370  REM Set m4_clk_root to OSC_RC_400M / 2: CLOCK_ROOT1 = mux(2), div(1)
380  Poke32 this 0x40CC0080 0x201
390  PRINT "Resetting M4 core"
400  REM Save current reset SRMR and prevent M4 SW reset affecting the system
410  s% = Peek32 this 0x40C04004
420  Poke32 this 0x40C04004 0x00000C00
430  Poke32 this 0x40C04284 0x1
440  Poke32 this 0x40C04004 s%
450  REM =======================================================================
460  REM Release M4 if needed
500  s% = Peek32 this 0x40c04000
510  IF s% & 1 == 1 THEN GOTO 560
520  PRINT "Releasing M4"
530  s% = s% | 1
540  Poke32 this 0x40c04000 s%
550  REM =======================================================================
560  PRINT "View cores on the DAP AP"
570  WireSwdConnect p%
580  CoreList p%
590  SelectProbeCore p% 0
600  REM =======================================================================
610  REM Potentially FlexRAM might need to be set to ensure TCMs are available
620  REM Uncomment next line if needed
630  REM GOSUB 800
640  REM =======================================================================
650  REM Finished - 0 to select the M7, 1 to select M4
660  d% = 0
670  REM =======================================================================
680  REM Setup VTOR in preparation for VECTRESET
690  GOSUB 1300
700  REM =======================================================================
710  END
800  REM ====================== SUB: Configure FlexRAM ========================
810  PRINT "Configuring FlexRAM for 256KB I-TCM, 256KB D-TCM, 0KB OCRAM"
820  REM FlexRAM TCM_CTRL - force RAM clocking ON and set fast mode = b100
830  Poke32 this 0x40028000 0x4
840  REM IOMUXC_GPR17/18 FlexRAM 32KB banks allocation - I(b11), D(b10), OC(b01)
850  Poke32 this 0x400E4044 0x0000AAFF
860  Poke32 this 0x400E4048 0x0000AAFF
870  REM IOMUXC_GPR16 Enable FLEXRAM_BANK_CFG in GPR16/17
880  s% = Peek32 this 0x400E4040
890  s% = s% | 4
900  Poke32 this 0x400E4040 s%
910  RETURN
1000 REM ==================== SUB: Set up M4 spin code ========================
1010 REM Setup some spin code into an area of D-TCM (0x2021FF00)
1020 REM Condensed vector table format taking up 2 words of memory:
1030 REM   - x00: SP (dummy), two back-to-back branch-to-self opcodes (b 0)
1040 REM   - x04: PC - points to address x00 (+1 Thumb)
1050 PRINT "Setting M4 spin code"
1060 Poke32 this 0x2021FF00 0xE7FEE7FE
1070 Poke32 this 0x2021FF04 0x2021FF01
1080 REM Set top/bottom 16 bits of RAM address into CM4 VTOR iomuxc_lpsr_GPR0/1
1090 Poke32 this 0x40C0C000 0xFF00
1100 Poke32 this 0x40C0C004 0x2021
1110 RETURN
1300 REM ==================== SUB: Setup CM7 VTOR =============================
1310 REM Upon VECTRESET, VTOR is loaded with the value from this register.
1320 REM If the address is invalid, a hard fault occurs after VECTRESET.
1330 REM These registers are set in preparation for a pre-flash driver VECTRESET
1340 REM requested by the stub.
1350 REM BootROM VTOR
1360 s% = 0x210000
1370 REM Set addr >> 7 into CM7 VTOR iomuxc_lpsr_GPR26 (RevB) or 0x400e404c (Rev A)
1380 v% = Peek32 this 0x40C84800
1390 IF v% & 0x00FFFFF0 == 0x1170A0 Then GOTO 1420
1400 Poke32 this 0x40C0C068 s% >> 7
1410 GOTO 1430
1420 Poke32 this 0x400E404C s% >> 7
1430 RETURN
1440 REM =======================================================================
1500 REM ====================== SUB: Disable M7 TCM ECC and OCRAM ECC ==========
1510 REM FlexRAM_CTRL - disable TCM ECC and OCRAM ECC
1520 Poke32 this 0x40028108 0x00000000
1530 REM MECC1/2 PIPE_ECC_EN - disable ECC
1540 Poke32 this 0x40014100 0x00000000
1550 Poke32 this 0x40018100 0x00000000
1560 RETURN

 MCUXpresso debug configuration,in the “connect script” item, select the above prepared .scp file:

6.jpg

Fig 6

The result after Debug is:

7.jpg

Fig 7

We can see, the code downloading and debugging all works now.

3.2 IAR IDE ECC script and testing

IAR project script path:

\MIMXRT1170-EVK-hello_world_demo_cm7\hello_world_demo_cm7\evkmimxrt1170

Prepare the file: evkmimxrt1170_connect_cm7_disableECC.mac

The content is:

 

/*
 * Copyright 2019-2021 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

__var rev;

initSysPll2()
{
    __var t;

    // ANADIG_PLL_PLL_528_CTRL
    t = __readMemory32(0x40C84240, "Memory");
    if (t & 0x800000)
    {
        // SysPll2 has been initialized
        t &= ~0x40000000;
        __writeMemory32(t, 0x40C84240, "Memory");
        return;
    }

    t = __readMemory32(0x40C84270, "Memory");
    t |= 0x80808080;
    __writeMemory32(t, 0x40C84270, "Memory");

    t = __readMemory32(0x40C84240, "Memory");
    t &= ~(0x802000);
    t |= 0x40000000;
    __writeMemory32(t, 0x40C84240, "Memory");
    
    // ANADIG_PLL_PLL_528_MFN
    __writeMemory32(0, 0x40C84280, "Memory");
    // ANADIG_PLL_PLL_528_MFI
    __writeMemory32(22, 0x40C84290, "Memory");
    // ANADIG_PLL_PLL_528_MFD
    __writeMemory32(0x0FFFFFFF, 0x40C842A0, "Memory");

    // ANADIG_PLL_PLL_528_CTRL
    __writeMemory32(0x40000008, 0x40C84240, "Memory");
    __delay(30);

    // ANADIG_PLL_PLL_528_CTRL
    t = __readMemory32(0x40C84240, "Memory");
    t |= 0x800000 | 0x800;
    __writeMemory32(t, 0x40C84240, "Memory");
    __delay(250);

    t = __readMemory32(0x40C84240, "Memory");
    t &= ~0x800;
    __writeMemory32(t, 0x40C84240, "Memory");

    do
    {
        t = __readMemory32(0x40C84240, "Memory");
    } while ((t & 0x20000000) == 0);

    t |= 0x2000;
    __writeMemory32(t, 0x40C84240, "Memory");

    t &= ~0x40000000;
    __writeMemory32(t, 0x40C84240, "Memory");
}


initSysPll2Pfd1()
{
    __var t, stable;
    t = __readMemory32(0x40C84270, "Memory");
    if (((t & 0x8000) != 0) || (((t & 0x3F00) >>  != 16))
    {
        stable = t & 0x4000;

        t |= 0x8000;
        __writeMemory32(t, 0x40C84270, "Memory");

        t = __readMemory32(0x40C84270, "Memory");
        t &= ~0x3F00;
        t |= 16 << 8;
        __writeMemory32(t, 0x40C84270, "Memory");

        t = __readMemory32(0x40C84250, "Memory");
        t ^= 0x4;
        __writeMemory32(t, 0x40C84250, "Memory");

        t = __readMemory32(0x40C84270, "Memory");
        t &= ~0x8000;
        __writeMemory32(t, 0x40C84270, "Memory");

        do
        {
            t = __readMemory32(0x40C84270, "Memory") & 0x4000;
        } while (t == stable);
    }
    else
    {
        t &= ~0x8000;
        __writeMemory32(t, 0x40C84270, "Memory");
    }
}

SDRAM_WaitIpCmdDone()
{
    __var reg;
    do
    {
        reg = __readMemory32(0x400D403C, "Memory");
        __delay(10);
    }while((reg & 0x3) == 0);

    __writeMemory32(0x00000003, 0x400D403C, "Memory");    // clear IPCMDERR and IPCMDDONE bits
}

setSemcClock()
{
    initSysPll2();
    initSysPll2Pfd1();
    // Set SEMC root clock to use sys pll2 pfd1 divided by 3: 198Mhz
    __writeMemory32(0x602, 0x40cc0200, "Memory");
}

initSDRAM()
{
    // Config IOMUX
    __writeMemory32(0x00000000, 0x400E8010, "Memory");
    __writeMemory32(0x00000000, 0x400E8014, "Memory");
    __writeMemory32(0x00000000, 0x400E8018, "Memory");
    __writeMemory32(0x00000000, 0x400E801C, "Memory");
    __writeMemory32(0x00000000, 0x400E8020, "Memory");
    __writeMemory32(0x00000000, 0x400E8024, "Memory");
    __writeMemory32(0x00000000, 0x400E8028, "Memory");
    __writeMemory32(0x00000000, 0x400E802C, "Memory");
    __writeMemory32(0x00000000, 0x400E8030, "Memory");
    __writeMemory32(0x00000000, 0x400E8034, "Memory");
    __writeMemory32(0x00000000, 0x400E8038, "Memory");
    __writeMemory32(0x00000000, 0x400E803C, "Memory");
    __writeMemory32(0x00000000, 0x400E8040, "Memory");
    __writeMemory32(0x00000000, 0x400E8044, "Memory");
    __writeMemory32(0x00000000, 0x400E8048, "Memory");
    __writeMemory32(0x00000000, 0x400E804C, "Memory");
    __writeMemory32(0x00000000, 0x400E8050, "Memory");
    __writeMemory32(0x00000000, 0x400E8054, "Memory");
    __writeMemory32(0x00000000, 0x400E8058, "Memory");
    __writeMemory32(0x00000000, 0x400E805C, "Memory");
    __writeMemory32(0x00000000, 0x400E8060, "Memory");
    __writeMemory32(0x00000000, 0x400E8064, "Memory");
    __writeMemory32(0x00000000, 0x400E8068, "Memory");
    __writeMemory32(0x00000000, 0x400E806C, "Memory");
    __writeMemory32(0x00000000, 0x400E8070, "Memory");
    __writeMemory32(0x00000000, 0x400E8074, "Memory");
    __writeMemory32(0x00000000, 0x400E8078, "Memory");
    __writeMemory32(0x00000000, 0x400E807C, "Memory");
    __writeMemory32(0x00000000, 0x400E8080, "Memory");
    __writeMemory32(0x00000000, 0x400E8084, "Memory");
    __writeMemory32(0x00000000, 0x400E8088, "Memory");
    __writeMemory32(0x00000000, 0x400E808C, "Memory");
    __writeMemory32(0x00000000, 0x400E8090, "Memory");
    __writeMemory32(0x00000000, 0x400E8094, "Memory");
    __writeMemory32(0x00000000, 0x400E8098, "Memory");
    __writeMemory32(0x00000000, 0x400E809C, "Memory");
    __writeMemory32(0x00000000, 0x400E80A0, "Memory");
    __writeMemory32(0x00000000, 0x400E80A4, "Memory");
    __writeMemory32(0x00000000, 0x400E80A8, "Memory");
    __writeMemory32(0x00000010, 0x400E80AC, "Memory"); // EMC_39, DQS PIN, enable SION
    __writeMemory32(0x00000000, 0x400E80B8, "Memory");
    __writeMemory32(0x00000000, 0x400E80BC, "Memory");
    __writeMemory32(0x00000000, 0x400E80C0, "Memory");
    __writeMemory32(0x00000000, 0x400E80C4, "Memory");
    __writeMemory32(0x00000000, 0x400E80C8, "Memory");
    __writeMemory32(0x00000000, 0x400E80CC, "Memory");
    __writeMemory32(0x00000000, 0x400E80D0, "Memory");
    __writeMemory32(0x00000000, 0x400E80D4, "Memory");
    __writeMemory32(0x00000000, 0x400E80D8, "Memory");
    __writeMemory32(0x00000000, 0x400E80DC, "Memory");
    __writeMemory32(0x00000000, 0x400E80E0, "Memory");
    __writeMemory32(0x00000000, 0x400E80E4, "Memory");
    __writeMemory32(0x00000000, 0x400E80E8, "Memory");
    __writeMemory32(0x00000000, 0x400E80EC, "Memory");
    __writeMemory32(0x00000000, 0x400E80F0, "Memory");
    __writeMemory32(0x00000000, 0x400E80F4, "Memory");
    __writeMemory32(0x00000000, 0x400E80F8, "Memory");
    __writeMemory32(0x00000000, 0x400E80FC, "Memory");

    // PAD ctrl
    // PDRV = 1b (normal); PULL = 10b (PD)
    __writeMemory32(0x00000008, 0x400E8254, "Memory");
    __writeMemory32(0x00000008, 0x400E8258, "Memory");
    __writeMemory32(0x00000008, 0x400E825C, "Memory");
    __writeMemory32(0x00000008, 0x400E8260, "Memory");
    __writeMemory32(0x00000008, 0x400E8264, "Memory");
    __writeMemory32(0x00000008, 0x400E8268, "Memory");
    __writeMemory32(0x00000008, 0x400E826C, "Memory");
    __writeMemory32(0x00000008, 0x400E8270, "Memory");
    __writeMemory32(0x00000008, 0x400E8274, "Memory");
    __writeMemory32(0x00000008, 0x400E8278, "Memory");
    __writeMemory32(0x00000008, 0x400E827C, "Memory");
    __writeMemory32(0x00000008, 0x400E8280, "Memory");
    __writeMemory32(0x00000008, 0x400E8284, "Memory");
    __writeMemory32(0x00000008, 0x400E8288, "Memory");
    __writeMemory32(0x00000008, 0x400E828C, "Memory");
    __writeMemory32(0x00000008, 0x400E8290, "Memory");
    __writeMemory32(0x00000008, 0x400E8294, "Memory");
    __writeMemory32(0x00000008, 0x400E8298, "Memory");
    __writeMemory32(0x00000008, 0x400E829C, "Memory");
    __writeMemory32(0x00000008, 0x400E82A0, "Memory");
    __writeMemory32(0x00000008, 0x400E82A4, "Memory");
    __writeMemory32(0x00000008, 0x400E82A8, "Memory");
    __writeMemory32(0x00000008, 0x400E82AC, "Memory");
    __writeMemory32(0x00000008, 0x400E82B0, "Memory");
    __writeMemory32(0x00000008, 0x400E82B4, "Memory");
    __writeMemory32(0x00000008, 0x400E82B8, "Memory");
    __writeMemory32(0x00000008, 0x400E82BC, "Memory");
    __writeMemory32(0x00000008, 0x400E82C0, "Memory");
    __writeMemory32(0x00000008, 0x400E82C4, "Memory");
    __writeMemory32(0x00000008, 0x400E82C8, "Memory");
    __writeMemory32(0x00000008, 0x400E82CC, "Memory");
    __writeMemory32(0x00000008, 0x400E82D0, "Memory");
    __writeMemory32(0x00000008, 0x400E82D4, "Memory");
    __writeMemory32(0x00000008, 0x400E82D8, "Memory");
    __writeMemory32(0x00000008, 0x400E82DC, "Memory");
    __writeMemory32(0x00000008, 0x400E82E0, "Memory");
    __writeMemory32(0x00000008, 0x400E82E4, "Memory");
    __writeMemory32(0x00000008, 0x400E82E8, "Memory");
    __writeMemory32(0x00000008, 0x400E82EC, "Memory");
    __writeMemory32(0x00000008, 0x400E82F0, "Memory");
    __writeMemory32(0x00000008, 0x400E82FC, "Memory");
    __writeMemory32(0x00000008, 0x400E8300, "Memory");
    __writeMemory32(0x00000008, 0x400E8304, "Memory");
    __writeMemory32(0x00000008, 0x400E8308, "Memory");
    __writeMemory32(0x00000008, 0x400E830C, "Memory");
    __writeMemory32(0x00000008, 0x400E8310, "Memory");
    __writeMemory32(0x00000008, 0x400E8314, "Memory");
    __writeMemory32(0x00000008, 0x400E8318, "Memory");
    __writeMemory32(0x00000008, 0x400E831C, "Memory");
    __writeMemory32(0x00000008, 0x400E8320, "Memory");
    __writeMemory32(0x00000008, 0x400E8324, "Memory");
    __writeMemory32(0x00000008, 0x400E8328, "Memory");
    __writeMemory32(0x00000008, 0x400E832C, "Memory");
    __writeMemory32(0x00000008, 0x400E8330, "Memory");
    __writeMemory32(0x00000008, 0x400E8334, "Memory");
    __writeMemory32(0x00000008, 0x400E8338, "Memory");
    __writeMemory32(0x00000008, 0x400E833C, "Memory");
    __writeMemory32(0x00000008, 0x400E8340, "Memory");

    // Config SDR Controller Registers/
    __writeMemory32(0x10000004, 0x400d4000, "Memory"); // MCR
    __writeMemory32(0x00000081, 0x400d4008, "Memory"); // BMCR0
    __writeMemory32(0x00000081, 0x400d400C, "Memory"); // BMCR1
    __writeMemory32(0x8000001D, 0x400d4010, "Memory"); // BR0, 64MB

    __writeMemory32(0x00000F32, 0x400d4040, "Memory"); // SDRAMCR0, 32bit
    __writeMemory32(0x00772A22, 0x400d4044, "Memory"); // SDRAMCR1
    __writeMemory32(0x00010A0D, 0x400d4048, "Memory"); // SDRAMCR2
    __writeMemory32(0x21210408, 0x400d404C, "Memory"); // SDRAMCR3

    __writeMemory32(0x80000000, 0x400d4090, "Memory"); // IPCR0
    __writeMemory32(0x00000002, 0x400d4094, "Memory"); // IPCR1
    __writeMemory32(0x00000000, 0x400d4098, "Memory"); // IPCR2

    __writeMemory32(0xA55A000F, 0x400d409C, "Memory"); // IPCMD, SD_CC_IPREA
    SDRAM_WaitIpCmdDone();
    __writeMemory32(0xA55A000C, 0x400d409C, "Memory"); // SD_CC_IAF
    SDRAM_WaitIpCmdDone();
    __writeMemory32(0xA55A000C, 0x400d409C, "Memory"); // SD_CC_IAF
    SDRAM_WaitIpCmdDone();
    __writeMemory32(0x00000033, 0x400d40A0, "Memory"); // IPTXDAT
    __writeMemory32(0xA55A000A, 0x400d409C, "Memory"); // SD_CC_IMS
    SDRAM_WaitIpCmdDone();

    __writeMemory32(0x00000017, 0x400d4150, "Memory"); // DCCR
    __writeMemory32(0x21210409, 0x400d404C, "Memory"); // enable sdram self refresh after initialization done.

    __message "SDRAM init done";
}

restoreFlexRAM()
{
    __var base;
    __var value;

    base = 0x400E4000;

    value = __readMemory32(base + 0x44, "Memory");
    value &= ~(0xFFFF);
    value |= 0xFFAA;
    __writeMemory32(value, base + 0x44, "Memory");
    value = __readMemory32(base + 0x48, "Memory");
    value &= ~(0xFFFF);
    value |= 0xFFAA;
    __writeMemory32(value, base + 0x48, "Memory");

    value = __readMemory32(base + 0x40, "Memory");
    value &= ~(0xFF << 8);
    value |= 0x7 | (0xaa << 8);
    __writeMemory32(value, base + 0x40, "Memory");
    __message "FlexRAM configuration is restored";
}

clearECC()
{
  __writeMemory32(0x00000000, 0x40014100, "Memory");
  __writeMemory32(0x00000000, 0x40018100, "Memory");
  __writeMemory32(0x00000000, 0x40028108, "Memory");
}

execUserPreload()
{
    restoreFlexRAM();
    setSemcClock();
    initSDRAM();
    clearECC();
}

 

Mainly add the above red code, which is used to clear the MECC and FlexRAM ECC enable bit.

Add the modified mac script:

8.jpg

Fig 8

Debug result is:

9.jpg

Fig 9

We can see, in the IAR also can do the code downloading and debugging, the script also works for the ECC enabled board.

3.3 MDK IDE ECC script and test result

  Open the project path:

\MIMXRT1170-EVK-hello_world_demo_cm7\hello_world_demo_cm7\evkmimxrt1170

Prepare the file:evkmimxrt1170_flexspi_nor_sdram.ini, the content is:

 

/*
 * Copyright 2019-2021 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

FUNC void restoreFlexRAM(void)
{
    unsigned int value;

    value = _RDWORD(0x400E4044);
    value &= ~(0xFFFF);
    value |= 0xFFAA;
    _WDWORD(0x400E4044, value);

    value = _RDWORD(0x400E4048);
    value &= ~(0xFFFF);
    value |= 0xFFAA;
    _WDWORD(0x400E4048, value);

    value = _RDWORD(0x400E4040);
    value &= ~(0xFF << 8);
    value |= 0x7 | (0xAA << 8);
    _WDWORD(0x400E4040, value);
}

FUNC void SDRAM_WaitIpCmdDone(void)
{
  unsigned long reg;
  do
  {
    reg = _RDWORD(0x400D403C);
  }while((reg & 0x3) == 0);
  
  _WDWORD(0x400D403C,0x00000003); // clear IPCMDERR and IPCMDDONE bits
}

FUNC void EnableOSC400M(void)
{
  unsigned int reg;
  // CTRL1: power down
  reg = _RDWORD(0x40C84050);
  reg &= ~0x1;
  _WDWORD(0x40C84050,reg);
  // CTRL2: enable clock
  reg = _RDWORD(0x40C84060);
  reg |= 0x1;
  _WDWORD(0x40C84060,reg);
}

FUNC void EnableOSC24M(void)
{
  unsigned int reg;
  reg = _RDWORD(0x40C84020);
  if(0 == (reg & 0x10))
  {
    reg = 0x14; // OSC_EN and LP_EN
    _WDWORD(0x40C84020,reg);
    reg = _RDWORD(0x40C84020);
    while (0 == (reg & 0x80000000));
  }
}

FUNC void EnablePllLdo(void)
{
  unsigned int reg;
  // CTRL_AI_CTRL
  _WDWORD(0x40C84820,0x00000000);
  // CTRL_AI_WDATA
  _WDWORD(0x40C84830,0x00000105);
  // PMU_LDO_PLL
  reg = _RDWORD(0x40C84500);
  reg |= 0x10000;
  _WDWORD(0x40C84500,reg);
  _Sleep_(100);
  
  // PMU_POWER_DETECT_CTRL
  _WDWORD(0x40C84580,0x00000100);
  _Sleep_(1);
  // PMU_REF_CTRL
  _WDWORD(0x40C84570,0x00000010);
}

FUNC void InitSysPll2Pfd1(void)
{
  unsigned int reg;
  unsigned int stable;
  // ANADIG_PLL_PLL_528_PFD
  reg = _RDWORD(0x40C84270);
  if (((reg & 0x8000) != 0) || (((reg & 0x3F00) >>  != 16))
  {
    stable = reg & 0x4000;

    reg |= 0x8000;
    _WDWORD(0x40C84270,reg);

    reg = _RDWORD(0x40C84270);
    reg &= ~0x3F00;
    reg |= 16 << 8;
    _WDWORD(0x40C84270,reg);

    reg = _RDWORD(0x40C84250);
    reg ^= 0x4;
    _WDWORD(0x40C84250,reg);

    reg = _RDWORD(0x40C84270);
    reg &= ~0x8000;
    _WDWORD(0x40C84270,reg);
    do
    {
        reg = _RDWORD(0x40C84270) & 0x4000;
    } while (reg == stable);
  }
  else
  {
    //syspll2 pfd1 has been initialized already
    reg &= ~0x8000;
    _WDWORD(0x40C84270,reg);
  }
}

FUNC void InitSysPll2(void)
{
  unsigned int reg;

  // ANADIG_PLL_PLL_528_CTRL
  reg = _RDWORD(0x40C84240);
  if (reg & 0x800000)
  {
      // SysPll2 has been initialized
      reg &= ~0x40000000;
      _WDWORD(0x40C84240, reg);
      return;
  }

  reg = _RDWORD(0x40C84270);
  reg |= 0x80808080;
  _WDWORD(0x40C84270, reg);

  reg = _RDWORD(0x40C84240);
  reg &= ~(0x802000);
  reg |= 0x40000000;
  _WDWORD(0x40C84240, reg);
  
  // ANADIG_PLL_PLL_528_MFN
  _WDWORD(0x40C84280, 0);
  // ANADIG_PLL_PLL_528_MFI
  _WDWORD(0x40C84290, 22);
  // ANADIG_PLL_PLL_528_MFD
  _WDWORD(0x40C842A0, 0x0FFFFFFF);

  // ANADIG_PLL_PLL_528_CTRL
  _WDWORD(0x40C84240, 0x8 | 0x40000000);
  _Sleep_(30);

  // ANADIG_PLL_PLL_528_CTRL
  reg = _RDWORD(0x40C84240);
  reg |= 0x800000 | 0x800;
  _WDWORD(0x40C84240, reg);
  _Sleep_(250);

  reg = _RDWORD(0x40C84240);
  reg &= ~0x800;
  _WDWORD(0x40C84240, reg);

  do
  {
      reg = _RDWORD(0x40C84240);
  } while ((reg & 0x20000000) == 0);

  reg |= 0x2000;
  _WDWORD(0x40C84240, reg);

  reg &= ~0x40000000;
  _WDWORD(0x40C84240, reg);
}

FUNC void SetSemcClock(void)
{
  //EnableOSC400M();
  EnablePllLdo();
  InitSysPll2();
  InitSysPll2Pfd1();
  
  // Set SEMC root clock
  // Use sys pll2 pfd1 divided by 3: 198Mhz
  _WDWORD(0x40CC0200,0x00000602);
}

FUNC void _clock_init(void)
{
  SetSemcClock();
}

FUNC void _sdr_Init(void)
{
  // Config IOMUX
  _WDWORD(0x400E8010, 0x00000000);
  _WDWORD(0x400E8014, 0x00000000);
  _WDWORD(0x400E8018, 0x00000000);
  _WDWORD(0x400E801C, 0x00000000);
  _WDWORD(0x400E8020, 0x00000000);
  _WDWORD(0x400E8024, 0x00000000);
  _WDWORD(0x400E8028, 0x00000000);
  _WDWORD(0x400E802C, 0x00000000);
  _WDWORD(0x400E8030, 0x00000000);
  _WDWORD(0x400E8034, 0x00000000);
  _WDWORD(0x400E8038, 0x00000000);
  _WDWORD(0x400E803C, 0x00000000);
  _WDWORD(0x400E8040, 0x00000000);
  _WDWORD(0x400E8044, 0x00000000);
  _WDWORD(0x400E8048, 0x00000000);
  _WDWORD(0x400E804C, 0x00000000);
  _WDWORD(0x400E8050, 0x00000000);
  _WDWORD(0x400E8054, 0x00000000);
  _WDWORD(0x400E8058, 0x00000000);
  _WDWORD(0x400E805C, 0x00000000);
  _WDWORD(0x400E8060, 0x00000000);
  _WDWORD(0x400E8064, 0x00000000);
  _WDWORD(0x400E8068, 0x00000000);
  _WDWORD(0x400E806C, 0x00000000);
  _WDWORD(0x400E8070, 0x00000000);
  _WDWORD(0x400E8074, 0x00000000);
  _WDWORD(0x400E8078, 0x00000000);
  _WDWORD(0x400E807C, 0x00000000);
  _WDWORD(0x400E8080, 0x00000000);
  _WDWORD(0x400E8084, 0x00000000);
  _WDWORD(0x400E8088, 0x00000000);
  _WDWORD(0x400E808C, 0x00000000);
  _WDWORD(0x400E8090, 0x00000000);
  _WDWORD(0x400E8094, 0x00000000);
  _WDWORD(0x400E8098, 0x00000000);
  _WDWORD(0x400E809C, 0x00000000);
  _WDWORD(0x400E80A0, 0x00000000);
  _WDWORD(0x400E80A4, 0x00000000);
  _WDWORD(0x400E80A8, 0x00000000);
  _WDWORD(0x400E80AC, 0x00000010); // EMC_39, DQS PIN, enable SION
  _WDWORD(0x400E80B8, 0x00000000);
  _WDWORD(0x400E80BC, 0x00000000);
  _WDWORD(0x400E80C0, 0x00000000);
  _WDWORD(0x400E80C4, 0x00000000);
  _WDWORD(0x400E80C8, 0x00000000);
  _WDWORD(0x400E80CC, 0x00000000);
  _WDWORD(0x400E80D0, 0x00000000);
  _WDWORD(0x400E80D4, 0x00000000);
  _WDWORD(0x400E80D8, 0x00000000);
  _WDWORD(0x400E80DC, 0x00000000);
  _WDWORD(0x400E80E0, 0x00000000);
  _WDWORD(0x400E80E4, 0x00000000);
  _WDWORD(0x400E80E8, 0x00000000);
  _WDWORD(0x400E80EC, 0x00000000);
  _WDWORD(0x400E80F0, 0x00000000);
  _WDWORD(0x400E80F4, 0x00000000);
  _WDWORD(0x400E80F8, 0x00000000);
  _WDWORD(0x400E80FC, 0x00000000);
  
  // PAD ctrl
  // PDRV = 1b (normal); PULL = 10b (PD)
  _WDWORD(0x400E8254, 0x00000008);
  _WDWORD(0x400E8258, 0x00000008);
  _WDWORD(0x400E825C, 0x00000008);
  _WDWORD(0x400E8260, 0x00000008);
  _WDWORD(0x400E8264, 0x00000008);
  _WDWORD(0x400E8268, 0x00000008);
  _WDWORD(0x400E826C, 0x00000008);
  _WDWORD(0x400E8270, 0x00000008);
  _WDWORD(0x400E8274, 0x00000008);
  _WDWORD(0x400E8278, 0x00000008);
  _WDWORD(0x400E827C, 0x00000008);
  _WDWORD(0x400E8280, 0x00000008);
  _WDWORD(0x400E8284, 0x00000008);
  _WDWORD(0x400E8288, 0x00000008);
  _WDWORD(0x400E828C, 0x00000008);
  _WDWORD(0x400E8290, 0x00000008);
  _WDWORD(0x400E8294, 0x00000008);
  _WDWORD(0x400E8298, 0x00000008);
  _WDWORD(0x400E829C, 0x00000008);
  _WDWORD(0x400E82A0, 0x00000008);
  _WDWORD(0x400E82A4, 0x00000008);
  _WDWORD(0x400E82A8, 0x00000008);
  _WDWORD(0x400E82AC, 0x00000008);
  _WDWORD(0x400E82B0, 0x00000008);
  _WDWORD(0x400E82B4, 0x00000008);
  _WDWORD(0x400E82B8, 0x00000008);
  _WDWORD(0x400E82BC, 0x00000008);
  _WDWORD(0x400E82C0, 0x00000008);
  _WDWORD(0x400E82C4, 0x00000008);
  _WDWORD(0x400E82C8, 0x00000008);
  _WDWORD(0x400E82CC, 0x00000008);
  _WDWORD(0x400E82D0, 0x00000008);
  _WDWORD(0x400E82D4, 0x00000008);
  _WDWORD(0x400E82D8, 0x00000008);
  _WDWORD(0x400E82DC, 0x00000008);
  _WDWORD(0x400E82E0, 0x00000008);
  _WDWORD(0x400E82E4, 0x00000008);
  _WDWORD(0x400E82E8, 0x00000008);
  _WDWORD(0x400E82EC, 0x00000008);
  _WDWORD(0x400E82F0, 0x00000008);
  _WDWORD(0x400E82FC, 0x00000008);
  _WDWORD(0x400E8300, 0x00000008);
  _WDWORD(0x400E8304, 0x00000008);
  _WDWORD(0x400E8308, 0x00000008);
  _WDWORD(0x400E830C, 0x00000008);
  _WDWORD(0x400E8310, 0x00000008);
  _WDWORD(0x400E8314, 0x00000008);
  _WDWORD(0x400E8318, 0x00000008);
  _WDWORD(0x400E831C, 0x00000008);
  _WDWORD(0x400E8320, 0x00000008);
  _WDWORD(0x400E8324, 0x00000008);
  _WDWORD(0x400E8328, 0x00000008);
  _WDWORD(0x400E832C, 0x00000008);
  _WDWORD(0x400E8330, 0x00000008);
  _WDWORD(0x400E8334, 0x00000008);
  _WDWORD(0x400E8338, 0x00000008);
  _WDWORD(0x400E833C, 0x00000008);
  _WDWORD(0x400E8340, 0x00000008);

  // Config SDR Controller Registers/
  _WDWORD(0x400d4000,0x10000004); // MCR
  _WDWORD(0x400d4008,0x00000081); // BMCR0
  _WDWORD(0x400d400C,0x00000081); // BMCR1
  _WDWORD(0x400d4010,0x8000001D); // BR0, 64MB
  
  _WDWORD(0x400d4040,0x00000F32); // SDRAMCR0, 32bit
  _WDWORD(0x400d4044,0x00772A22); // SDRAMCR1
  _WDWORD(0x400d4048,0x00010A0D); // SDRAMCR2
  _WDWORD(0x400d404C,0x21210408); // SDRAMCR3
                        
  _WDWORD(0x400d4090,0x80000000); // IPCR0
  _WDWORD(0x400d4094,0x00000002); // IPCR1
  _WDWORD(0x400d4098,0x00000000); // IPCR2

  
  _WDWORD(0x400d409C,0xA55A000F); // IPCMD, SD_CC_IPREA
  SDRAM_WaitIpCmdDone();
  _WDWORD(0x400d409C,0xA55A000C); // SD_CC_IAF
  SDRAM_WaitIpCmdDone();
  _WDWORD(0x400d409C,0xA55A000C); // SD_CC_IAF
  SDRAM_WaitIpCmdDone();
  _WDWORD(0x400d40A0,0x00000033); // IPTXDAT
  _WDWORD(0x400d409C,0xA55A000A); // SD_CC_IMS
  SDRAM_WaitIpCmdDone();
  _WDWORD(0x400d4150,0x00000017); // DCCR
  _WDWORD(0x400d404C,0x21210409 ); // enable sdram self refresh again after initialization done.
}

FUNC void Setup (void) {
  SP = _RDWORD(0x30002000);          // Setup Stack Pointer
  PC = _RDWORD(0x30002004);          // Setup Program Counter
  _WDWORD(0xE000ED08, 0x30002000);   // Setup Vector Table Offset Register
}

FUNC void DisableECC(){
  _WDWORD(0x40014100, 0x00000000);   
	_WDWORD(0x40018100, 0x00000000);
	_WDWORD(0x40028108, 0x00000000);
}
FUNC void OnResetExec (void)  {      // executes upon software RESET
  _clock_init();
  _sdr_Init();
	DisableECC();
  Setup();                           // Setup for Running
}

restoreFlexRAM();
_clock_init();
_sdr_Init();
DisableECC();

LOAD %L INCREMENTAL                  // Download

Setup();                             // Setup for Running

// g, main

 In the project, add the prepared script file:


10.jpg

Fig 10

Debug result is:

11.jpg

Fig 11

We can see, in MDK, debugging can also be successful using CMSIS DAP.

Information sharing: For MCUXPresso IDE, subsequent scripts will automatically add ECC support, the new version is MCUXpresso11.10.0. Scripts for other IDEs need to be added by themselves.

 

Attachments
No ratings
Version history
Last update:
‎06-05-2024 10:15 PM
Updated by: