【朝花夕拾】RT1170 使能ECC后CMSIS DAP+IDE debug

一,文档描述

本文旨在解决RT1170在使能ECC功能后,使用CMSIS DAP在三大IDE( MCUXpresso,IAR,MDK)不能debug的问题。使能ECC是通过烧录相关的fuse,并且使能了ROM preloading,也就是ROM会帮忙做RAM初始化,但是实际使用的时候,发现不同debugger在IDE上的表象也不一样,比如Segger JLINK就能直接实现debug,但是CMSIS DAP在结合三大IDE的时候,均会出现下载代码到RAM不能debug的问题。这里以MCUXpresso IDE为例,在MIMXRT1170-EVK板子上烧录了ECC相关fuse之后,如果工程是烧录到RAM,那么是能够直接debug,没问题。但是如果是烧录到flash的工程,就会出现flashloader的问题:
在这里插入图片描述

图 1

那么这个问题是因为flashloader的不匹配,还是需要额外其他操作呢?本文将会具体给出解决方案。

二,RT1170 ECC基础使能以及问题解决

2.1 RT1170 ECC 基础

ECC即Error Correcting Code, 可以实现内存的错误检查和纠正。那么RT1170有哪些ECC呢?分别为:MECC64, XECC, FlexRAM ECC

  • MECC64
    MECC64支持1位纠错,和2位检错,无法纠错,主要保护片内的OCRAM1,2。 MECC1保护OCRAM1, MECC2 保护OCRAM2。 OCRAM1 ECC, OCRAM2 ECC用于存放ECC校验值。如果ECC64未使能,可用作普通OCRAM。每 64bits 数据计算出一个8bit的 ECC 校验值(8bits),ECC 算法是 Hsiao Hamming。
  • XECC
    XECC即External ECC controller,用于为外部存储空间提供ECC功能。XECC支持1位纠错,和2位检错。外部内存包含XECC_FLEXSPI1,XECC_FLEXSPI2,XECC+SEMC. XECC每4bit可以计算出一个4bit的ECC校验值,XECC校验值是紧跟在原始值后面,比如一个32位数据,每4位生成一个4位的ECC校验值,32位原始数据需要生成32bit的ECC校验数据,一共需要64bit的空间。算法:Hsiao Hamming algorithm
  • FlexRAM ECC
    FlexRAM ECC用于保护FlexRAM的ITCM,DTCM以及OCRAM。支持1bit纠错,2bit检错。每DTCM 4byte,或者ITCM/OCRAM 8bytes计算出一个7/8bit 的ECC校验值,ECC校验值放到ECC RAM中。

2.2 RT1170 ECC 使能

本文使能ECC的方法是直接使能相关fuse bit。

  • MECC_ENABLE (0x840[2]) = 1
  • XECC_ENABLE (0x840[3]) = 1
  • ROM preloading (0x950[0]) = 1
  • FLEXRAMECC_ENABLE (0x840[15]) = 1
    更多软件配置情况,可以参考官方的应用笔记AN13204:
    https://www.nxp.com/docs/en/application-note/AN13204.pdf
    如下是烧过相关fuse之后的情况,烧fuse可以进入serial download模式,使用MCUbootutility烧录:
    在这里插入图片描述

图 2

2.3 ECC debug问题解决方法

经过多种方法的测试,比如在脚本中初始化RAM,因为通过ECC的特性,需要先刷一次RAM,但是发现通用直接刷RAM的代码速度太慢,导致下载超时问题,然后再改成使用DMA搬运数据到RAM,保证RAM是被刷过一次的情况,但是结果还是不行,所以刷RAM并不是解决debug问题的根本方式。最后机缘巧合,在连接脚本中先关闭ECC,尤其是FlexRAM ECC,发现这个时候就能够调用烧录算法去做外部flash的操作了。这样可以成功下载代码,然后复位,让ROM自行打开ECC功能。
对于RAM工程能够工作的原因,是因为下载RAM的过程就是一个刷RAM的过程,所以RAM代码才能直接工作。
对于Flash代码的debugger烧录和仿真,还是需要先行关闭ECC模块,主要FlexRAM ECC模块,当然,我们这边为了保险起见,可以直接关闭所有的MECC和FlexRAM ECC寄存器使能位,让flashloader先工作起来,直接控制寄存器地址:
0x40014100=0;0x40018100=0;0x40028108=0;

  • 0x40014100 PIPE_ECC_EN[ECC_EN],控制MECC1
  • 0x40018100 PIPE_ECC_EN[ECC_EN],控制MECC2
    在这里插入图片描述

图 3

  • 0x40028108 FLEXRAM_CTRL ECC_EN,控制FlexRAM ECC
    在这里插入图片描述

图 4
根据实际测试的情况,关闭FlexRAM ECC有效,问题应该是出在使用的flashloader存放的区域是FlexRAM的DTCM,查看烧录算法Flashloader的区域情况如下:
在这里插入图片描述

图5

三,三大IDE相关脚本准备与测试

下面直接开门见山,给出能解决CMSIS DAP结合三大IDE下载问题的修改脚本。

3.1 MCUXpresso IDE

脚本在IDE中的路径:
C:\nxp\MCUXpressoIDE_11.9.0_2144\ide\LinkServer\binaries\Scripts
准备RT1170_connect_M7_wake_M4_ecc.scp,并且拷贝到上面的路径中,内容如下:

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,在connect script中选择刚刚准备好的.scp文件:
在这里插入图片描述

图 6
Debug之后的结果如下:

在这里插入图片描述

图 7
可以看到,代码以及能够成功下载。

3.2 IAR IDE ECC 脚本

IAR工程的脚本路径:
\MIMXRT1170-EVK-hello_world_demo_cm7\hello_world_demo_cm7\evkmimxrt1170
准备脚本文件:evkmimxrt1170_connect_cm7_disableECC.mac
内容如下:

/*
 * 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) >> 8) != 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();
}


主要添加代码如上述的clearECC(),清除ECC使能标志。
加载修改后的mac脚本:
在这里插入图片描述

图 8
Debug结果如下:
在这里插入图片描述

图 9
可以看到,在IAR中也能成功下载并且debug。
3.3 MDK IDE ECC脚本
打开工程路径:
\MIMXRT1170-EVK-hello_world_demo_cm7\hello_world_demo_cm7\evkmimxrt1170
准备文件:evkmimxrt1170_flexspi_nor_sdram.ini,内容如下:

/*
 * 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) >> 8) != 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

在工程中选择准备好的脚本文件:
在这里插入图片描述

图 10
Debug结果如下:
在这里插入图片描述

图 11
可以看到,在MDK中,使用CMSIS DAP 也可以成功debug。
信息分享:对于MCUXPresso IDE,后续的脚本会自动添加ECC的支持,版本为MCUXpresso111.10.0。其他IDE的脚本需要自行添加。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值