cancel
Showing results for 
Search instead for 
Did you mean: 

How to create CubeProg stldr loader file for QSPI external memory?

JNguyen
Senior
 
23 REPLIES 23
JNguyen
Senior

Attached are major files of my CubeProg project with STM32H750, MT25QL256 (32MB). CubeProg can read QSPI OK, not write/sector-erase correctly. I'd appreciate if someone review and provide feedback.

Generally speaking, Interrupts and VTOR shouldn't be in use at all.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I perhaps would avoid putting it into QUAD mode all the time, as this then expects commands to be sent differently (ie not 1_LINE mode)

Use the commands implementing 1-4-4 mode for instruction/address/data.

Don't make assumptions about mapped/un-mapped mode, the application calls Init() repeatedly switching modes.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I went back to check. I don't have any 4_LINES instructionmode. Only 4_LINES mode I have is in code for the commands (0x38 and 0x6B) which require 1-4-4 or 1-1-4. For mapped/un-mapped mode, that is what I was concerned about, since I don't know how CubeProg behavors. So I added QSPI_AutoPollingMemReady() in Read, Write, SectorErase, Verify functions (in Loader_Src.c). That actually got rid lot of errors, and got me to this point.

JNguyen
Senior

I finally got this to work. In addition items I mentioned above, below items are also needed. They are not documented any where, so it took me long time to get it resolved. They are not guarantied to be correct solution for you if you use a different CPU. I hope this help you to save time. At least you know which areas to experiment.

1)  memory location 0x24000004 must be used in stm32_flash.ld. STM32H750 has other 3 RAM areas, 0x20000000, 0x30000000, 0x38000000. None of these 3 works.

/* Specify the memory areas */

MEMORY

{ RAM (xrw)     : ORIGIN = 0x24000004, LENGTH = 512K }

2) Adding *(uint32_t*)0xE000EDF0=0xA05F0000; in LoaderSrc.c to enables IRQs in debug state.

int Init(uint8_t memMappedMode) {

       uint8_t status=0xFF;

        *(uint32_t*)0xE000EDF0=0xA05F0000;   // enables IRQs in debug state.

        status=MCU_Init(memMappedMode);

       if (status == 0)

              return 1;

        return 0;

}

The alternative is to be able to mark time accurately *without* using interrupts.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
egoltzman
Senior

Hello,

I'm in the middle of building an external loader for a target board based on L496 & QSPI, the same as used in the L496G-Disco board but the QSPI on my target sits under different lines then the disco.

I started by building an running successfully a loader based on the example from the CubeProgrammer install dir for the disco board, after I had this I thought moving it to the target will be as simple as change the lines but this did not worked and I have problem to activate the write.

After digging in this issue I saw this discussion and my main concern now is who makes the HAL ticks tick?

I saw that Clive mention more then once that interrupt should not be used, if so then how HAL_IncTick is pushed if not from SysTick_Handler?

Using the QSPI HAL API needs this as I see in the code:

HAL_StatusTypeDef HAL_QSPI_Command(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout)
{
  HAL_StatusTypeDef status;
  uint32_t tickstart = HAL_GetTick();

I see from reading and review JNguy code and comments that he use interrupts, but the HAL_Delay is commented out, why?

I believe my problem with the QSPI write on the target is a timing issue and thus this interrupt issue is relevant.

I'll be happy and thankful for any kind of input or suggestion on that.

Thanks and happy new year!

>>I saw that Clive mention more then once that interrupt should not be used, if so then how HAL_IncTick is pushed if not from SysTick_Handler?

There is obviously more than one way to skin the cat... Your mind is trapped in a box of it's own creation.

The CPU has a cycle counter, and TIM2 can be used as a free running maximal 32-bit counter, both methods can determine the elapsed time between calls to HAL_GetTick()

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

You can see below my question about the time tick, I added TIM2 to make the ticks and my stldr is still not functioning.

I try to follow the code you put here and I'm not sure I fully understand the structure of your external loader project, how come you have a main? I thought there should only be Init, Write, SectorErase,MassErase &Verify?

Can you please send the project itself? Is this a CubeIDE one?

Thanks

OK, I did this with TIM2 but it did not change the state and the loader on the target is still not working properly.

I have a situation where I have a working loader project that is built for the L496Disco board that have on it the same MX25R6435F 8M QSPI as I have on my target, but after I only change the QSPI lines to the ones that fits the target board the loader is not working properly when I try to write.

I have this phenomena:

  • I'm starting from an erased flash
  • I'm trying to write "12345" at address 0 from the CubeProgrammer GUI
  • I get this "CCCDEFCD" on this address after I try to write and a popup error message say "Memory edition verification failed"

When I erase a sector it is look like the job is being done properly.

Two things are different in my target in compare to the disco board, I'm working with 1.8V and the I have an external crystal of 16M, but I'm not setting the clock to use it in the loader project.

Any idea what could be the problem?

Thanks