Any iMXRT examples that boot out of FlexSPI, but run from SDRAM?

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

Any iMXRT examples that boot out of FlexSPI, but run from SDRAM?

Jump to solution
1,641 Views
EdSutter
Senior Contributor II

I'm working with the ARMGCC version of the SDK (using MIMXRT1060-EVK currently).  I've built several different examples and small applications that boot from (and run out of) FlexSPI-NOR-flash.  I'd like to be able to boot out of FlexSPI-nor, then have the application transfer itself to SDRAM and run from there.  Are there any examples of that in the SDK?

I'm guessing it's just a matter of massaging the .ld file and making sure that Reset_Handler copies text space to the correct location in SDRAM, prior to jumping to the relocated _start;  but that's easier said than done...

Before I trek this path, has anyone done this already?

Labels (2)
0 Kudos
1 Solution
1,493 Views
mjbcswitzerland
Specialist V

Ed

Or have a second SPI connected Flash chip for the other storage needs.

I have all applications running in ITC so they use the QSPI flash for parameter and file systems without any problems with sharing with code. In fact I avoid SDRAM since it doesn't allow code to be protected and I never had a program so large that external memory was needed.

The only time I need to run from QSPI flash and program it at the same time is when the boot loader needs to update programs, in which case just the involved routines are executed from ITC.

Regards

Mark

[uTasker project developer for Kinetis and i.MX RT]

View solution in original post

4 Replies
1,493 Views
mjbcswitzerland
Specialist V

Hi Ed

Below is the solution used in the uTasker project. The SDRAM needs either to be configured via DCD or else by initialisation code before the copy/jump. It shows decrypting from encrypted code in SPI flash or plain text, depending on the image.
The image needs just to be linked to the SRDAM address that it will run at.

static void jump_to_application(unsigned long app_link_location)
{
    asm(" mov r1, #0");                                                  // cortex-M7 assembler code
    asm(" msr control, r1");                                             // disable potential FPU access flag so that subsequent exceptions do not save FPU registers
    asm(" ldr sp, [r0,#0]");                                             // load the stack pointer value from the program's reset vector
    asm(" ldr pc, [r0,#4]");                                             // load the program counter value from the program's reset vector to cause operation to continue from there
}


static void fnCopyApplicationToRAM(iMX_BOOT_HEADER *ptrHeader, unsigned long ulCodeLength)
{
    if ((ptrHeader->usMagicNumber & 0x8000) != 0) {                      // if AES256 encrypted
        unsigned long ulBuffer[512];                                     // long word aligned buffer
        unsigned long ulCopyLength = sizeof(ulBuffer);
        const unsigned char *ptrInput = (const void *)(ptrHeader + 1);
        unsigned char *ptrDestination = (unsigned char *)(SDRAM_START_ADDRESS);
        fnPrepareDecrypt();                                              // prepare the decrpt key and prime the initial vector
        while (ulCodeLength != 0) {
            if (ulCodeLength < sizeof(ulBuffer)) {
                ulCopyLength = ulCodeLength;                             // final block that may be smaller that the buffer size
            }
            uMemcpy(ulBuffer, ptrInput, ulCopyLength);                   // copy the encrypted input block into the decryption buffer
            fnAES_Cipher(AES_COMMAND_AES_DECRYPT, (const unsigned char *)ulBuffer, (unsigned char *)ulBuffer, ulCopyLength); // decrypt the buffer content
            uMemcpy(ptrDestination, (const void *)ulBuffer, ulCopyLength); // copy the decrypted code to program RAM
            ulCodeLength -= ulCopyLength;
            ptrDestination += ulCopyLength;
            ptrInput += ulCopyLength;
        }
    }
    else {
        uMemcpy((void *)(SDRAM_START_ADDRESS), (const void *)(ptrHeader + 1), ulCodeLength); // copy the unencrypted code
    }
}


// Load and start an application stored in QSPI
//
extern void start_application(unsigned long app_link_location)
{
    iMX_BOOT_HEADER *ptrHeader = (iMX_BOOT_HEADER *)app_link_location;
    unsigned long ulCodeLength = fnCheckValidApplication(ptrHeader);   // check the authentication of code in the SPI flash
    if (ulCodeLength != 0) {                                           // if the code image is valid
        jump_to_application(SDRAM_START_ADDRESS);                      // and finally jump to the new code
    }
}

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

1,493 Views
EdSutter
Senior Contributor II

Thanks Mark, I'm still trying to decide how I want to pursue this.  My real goal is just to be able to modify FlexSPI-nor-flash at runtime.  Since I can't execute from the flash while operating on it, the only two approaches AFAIK would be to relocate the entire application to SDRAM or just relocate the flash operations.  Not sure which way to go yet.

0 Kudos
1,494 Views
mjbcswitzerland
Specialist V

Ed

Or have a second SPI connected Flash chip for the other storage needs.

I have all applications running in ITC so they use the QSPI flash for parameter and file systems without any problems with sharing with code. In fact I avoid SDRAM since it doesn't allow code to be protected and I never had a program so large that external memory was needed.

The only time I need to run from QSPI flash and program it at the same time is when the boot loader needs to update programs, in which case just the involved routines are executed from ITC.

Regards

Mark

[uTasker project developer for Kinetis and i.MX RT]

1,493 Views
EdSutter
Senior Contributor II

Yea, actually my previous reply wasn't accurate... Didn't really mean SDRAM, just not FlexSPI.  I did have SDRAM in mind initially, but actually it would make more sense to run out of internal ram.

Tx

0 Kudos