NXP系列容易混淆的问题

MXRT1052,CFX,下载算法

Views:  times Updated on May 29, 2023 Posted by elmagnifico on February 17, 2023

Foreword

我开发的过程中也遇到了一堆堆的问题,看了好几个文档,没有一个说清楚的,所以自己总结一下,防止后人被坑

默认MIMXRT1xxxx系列都有一个EVK的板子,一般情况下这个板子默认都带有DAP,官方推荐的调试下载也都是基于DAP-Link来说的。

DAP-Link开源,免费,对于厂商来说当然是愿意选择的,不用给J-Link付费,那可太好了。

但是DAP-Link不好的地方在于,它具有单一性,不通用,你有N家的板子就得有N个不同的DAP-Link,对于开发者来说,那当然很讨厌啊。

J-Link通用,但是NXP默认支持的都不是J-Link,MCUXPresso IDE 默认的也不是J-Link,甚至它的很多设置,看似是通用的,实则是只有DAP可以使用。

比如工程配置中的Flash驱动选择和他的算法,只有DAP才生效,用JLink,完全不起作用。可以看到很多教程都是教你用DAP,配好就能烧写,就能调试,而如果用J-Link,直接就不能用。

J-Link解决方案

新版J-Link驱动直接兼容所有QSPI芯片,没必要第三方了

这里就要推一下痞子衡做的工具了,还是非常好用的

https://github.com/JayHeng/RT-UFL

RT-UFL,这个是给J-Link写的下载算法,添加到J-Link驱动以后,J-Link就直接支持各种NXP芯片适配的各种Flash下载了。再也不会被卡了。

RT-UFL安装教程看这里,其实很简单,直接解压放进去就行了

https://www.cnblogs.com/henjay724/p/14942574.html

MCUXPresso IDE下使用看这里,主要就是给J-Link设置一下芯片型号就行了。

https://www.cnblogs.com/henjay724/p/15430619.html

关键点就只有一个,Device 这里手动输入,默认选项中根本没有具体的算法

HyperFlash与QspiFlash

这里也是容易弄错的地方,QSPI、OctalFlash、HyperFlash、EcoXipFlash等,他们都是不同类型的Flash,不同的Flash在烧写编程的细节上会略有不同,所以烧写的时候会针对性的做区分。

目前常用的一般就是Hyper和QSPI,其他的类型比较少见。现在只是基于类型来说,比较笼统,具体到烧写阶段的时候,一般需要烧写器(J-Link)做区分,比如Hyper的有一种算法,QSPI有一种算法

所以一般会根据实际使用的类型,选择算法,算法的Size可以往大选,但是不能往小选

也有教程教你怎么自己写一个烧写算法,从而完成对不同种类的Flash进行烧写。

这个算法文件在Keil是.FLM后缀,在MCUXPresso IDE中是.cfx后缀,一般来说QSPI就能通用到所有QSPI类型的Flash上了,同理Hyper也是。在MCUXPresso IDE中基本也是这样的,EVK算是特例了(其实也能支持的)

FlashConfig

上面是具体的某类Flash,这里再谈的就是某个Flash了,同类的Flash 在初始化阶段会略有不通,寄存器可能不一样,大小也有可能不同。

如果这里写错的话,会导致烧写正确,但是无法debug,芯片也跑不起来。

#if defined(HYPERFLASH_BOOT)    
const flexspi_nor_config_t hyperflash_config =
{
    .memConfig =
    {
        .tag = FLEXSPI_CFG_BLK_TAG,
        .version = FLEXSPI_CFG_BLK_VERSION,
        .readSampleClkSrc = kFlexSPIReadSampleClk_ExternalInputFromDqsPad,
        .csHoldTime = 3u,
        .csSetupTime = 3u,
        .columnAddressWidth = 3u,
        // Enable DDR mode, Wordaddassable, Safe configuration, Differential clock
        .controllerMiscOption = (1u << kFlexSpiMiscOffset_DdrModeEnable) |
                                (1u << kFlexSpiMiscOffset_WordAddressableEnable) |
                                (1u << kFlexSpiMiscOffset_SafeConfigFreqEnable) |
                                (1u << kFlexSpiMiscOffset_DiffClkEnable),
        .sflashPadType = kSerialFlash_8Pads,
        .serialClkFreq = kFlexSpiSerialClk_133MHz,
        .sflashA1Size = 64u * 1024u * 1024u,
        .dataValidTime = {16u, 16u},
        .lookupTable =
            {
                // Read LUTs
                FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0xA0, RADDR_DDR, FLEXSPI_8PAD, 0x18),
                FLEXSPI_LUT_SEQ(CADDR_DDR, FLEXSPI_8PAD, 0x10, DUMMY_DDR, FLEXSPI_8PAD, 0x06),
                FLEXSPI_LUT_SEQ(READ_DDR, FLEXSPI_8PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0),
            },
    },
    .pageSize = 512u,
    .sectorSize = 256u * 1024u,
    .blockSize = 256u * 1024u,
    .isUniformBlockSize = true,
};

#else
const flexspi_nor_config_t Qspiflash_config =
{
    .memConfig =
    {
        .tag = FLEXSPI_CFG_BLK_TAG,
        .version = FLEXSPI_CFG_BLK_VERSION,
        .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally,
        .csHoldTime = 3u,
        .csSetupTime = 3u,
        .deviceModeCfgEnable = true,
        .deviceModeType = 1,//Quad Enable command
        .deviceModeSeq.seqNum = 1,
        .deviceModeSeq.seqId = 4,				
        .deviceModeArg = 0x000200,//Set QE
        .deviceType = kFlexSpiDeviceType_SerialNOR,
        .sflashPadType = kSerialFlash_4Pads,
        .serialClkFreq = kFlexSpiSerialClk_100MHz,//80MHz for Winbond, 100MHz for GD, 133MHz for ISSI
        .sflashA1Size = 4u * 1024u * 1024u,//4MBytes
        .dataValidTime = {16u, 16u},
        .lookupTable =
        {
           //Quad Input/output read sequence
           [0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
           [1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),
           [2] = FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0),
           //Read Status
           [1*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
           //Write Enable
           [3*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, 0, 0),
           //Write status
           [4*4] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01, WRITE_SDR, FLEXSPI_1PAD, 0x2),
	 },
    },
    .pageSize = 256u,
    .sectorSize = 4u * 1024u,
};

#endif

SES动态分配FlexRam

先说动态分配FlexRam会导致一些莫名其妙的现象,猜测和内部的ram有关系


/* Reset Handler */

    .thumb_func
    .align 2
    .globl   Reset_Handler
    .weak    Reset_Handler
    .type    Reset_Handler, %function

Reset_Handler:
    .equ __iomux_gpr14_adr, 0x400AC038
    .equ __iomux_gpr16_adr, 0x400AC040
    .equ __iomux_gpr17_adr, 0x400AC044


    .equ __flexram_itcm_size, 0x7       
    .equ __flexram_dtcm_size, 0x8       
    .equ __flexram_bank_cfg, 0x55555FAA

    /*.equ __flexram_bank_cfg,0xAAAA5555*/
    /*.equ __flexram_itcm_size, 0x0       /*   0KB*/
    /*.equ __flexram_dtcm_size, 0x9        /* 256KB*/
    /* adjust sram */
    CPSID I                
#define FLEXRAM_CFG_ENABLE
#ifdef FLEXRAM_CFG_ENABLE
    /*分配Bank,并且激活Bank配置*/
    LDR R0,=__iomux_gpr17_adr
    LDR R1,=__flexram_bank_cfg
    STR R1,[R0]
    LDR R0,=__iomux_gpr16_adr
    LDR R1,[R0]
    ORR R1,R1,#4
    STR R1,[R0]
//#define FLEXRAM_ITCM_ZERO_SIZE
#ifdef FLEXRAM_ITCM_ZERO_SIZE
    /*禁掉ITCM*/
    LDR R0,=__iomux_gpr16_adr
    LDR R1,[R0]
    AND R1,R1,#0xFFFFFFFE
    STR R1,[R0]
#endif

#ifdef FLEXRAM_DTCM_ZERO_SIZE
    /*禁掉DTCM*/
    LDR R0,=__iomux_gpr16_adr
    LDR R1,[R0]
    AND R1,R1,#0xFFFFFFFD
    STR R1,[R0]
#endif

    /*调整TCM容量*/
    LDR R0,=__iomux_gpr14_adr
    LDR R1,[R0]
    MOVT R1,#0x0000
    MOV R2,#__flexram_itcm_size
    MOV R3,#__flexram_dtcm_size
    LSL R2,R2,#16
    LSL R3,R3,#20
    ORR R1,R2,R3
    STR R1,[R0]
#endif

    /* reset handle */
    .equ    VTOR, 0xE000ED08
    ldr     r0, =VTOR
    ldr     r1, =__isr_vector
    str     r1, [r0]
    ldr     r2, [r1]
    msr     msp, r2
#ifndef __NO_SYSTEM_INIT
    ldr   r0,=SystemInit
    blx   r0
#endif

这里遇到的问题是官方文档里没有解释的,在SES中全都会出现问题

OC RAM必须在IOMUXC_GPR_GPR17的最高位处有一块,否则会出现无法烧写、debug的情况

ITCM 必须有一块64K大小的,否则也会出现无法烧写、debug的情况

然后仔细观察Fuse中一些默认的分配方式,怀疑和这个也有关系,如果ODI没有任何顺序问题,那为什么不是OODDII呢,而是这种奇奇怪怪的分布形式

image-20230315092647223

如果使用其他IDE可以正常烧写,唯独SES无法正常处理(还有一种可能是痞子衡写的烧写算法有问题,默认使用了ITCM,导致实际无法正常工作

1062和1052互相替换

经过对比,两个芯片引脚是一模一样的,1062只是多了一个CAN,多了一个以太网的口,其他硬件和外设基本是一模一样的。

如果要替换,基本可以pin2pin,直接换片子就行了。

至于工程上,只是需要把烧写目标换一下,代码等各种宏定义甚至可以不用改动就能正常工作了。

Summary

未完待续

Quote

https://blog.csdn.net/l3142600073/article/details/89551508

https://www.cnblogs.com/henjay724/p/15028189.html

https://github.com/SphinxEVK/openMV_on_RT1064

https://community.nxp.com/t5/i-MX-RT/RT1050-QSPI-flash-change-to-Winbond-W25Q32JV-3-3V/m-p/904541/highlight/true