cancel
Showing results for 
Search instead for 
Did you mean: 

The custom made external loader, failed to make multiple Reads, (STM32CubeProgrammer returns error)

AJack.5
Associate II

I follow the guide to make an external loader and it works for the most part. I can erase sectors, write data. But I can only read data once. If I try make multiple Read, STM32CubeProgrammer returns error. See example below:

Example:

14:56:32 : Time elapsed during the read operation is: 00:00:00.007

14:56:35 : UPLOADING ...

14:56:35 : Size        : 1024 Bytes

14:56:35 : Address     : 0x90000000

14:56:35 : Read progress:

14:56:37 : Data read successfully

14:56:37 : Time elapsed during the read operation is: 00:00:02.314


_legacyfs_online_stmicro_images_0693W00000bjOrgQAE.png 

15:18:18 : UPLOADING ...

15:18:18 : Size        : 1024 Bytes

15:18:18 : Address     : 0x90010000

15:18:18 : Read progress:

15:18:26 : Error: Data read failed

It does not matter, which start address I use in the second read request. If I use Address: 0x90000000, in the second read I receive same error.


_legacyfs_online_stmicro_images_0693W00000bjOrlQAE.png 

I have tested the code in "non-extern-loader-mode", by change the linker file from linker.ld to STM32F767IITX_FLASH.ld.

The code in the main() is then executed. I am then able to enable memory mapped mode and make several read from different segments in the external flash.

Example:

Erase 16MB external flash

Write 16MB test data into external flash

Enable Memory Mapped Mode

Read data in memory mapped mode

0x90000000: 0x0

0x90000004: 0x1

0x90000008: 0x2

0x9000000c: 0x3

Read data from next 64kB Section

0x90010000: 0x3fff

0x90010004: 0x3ffe

0x90010008: 0x3ffd

0x9001000c: 0x3ffc


_legacyfs_online_stmicro_images_0693W00000bjOtSQAU.png 

When I execute code in "non-extern-loader-mode"

I am then able to use ST-Link and STM32CubeIde memory browser and view several memory sectors without any problem, so the driver seems to work as it should.


_legacyfs_online_stmicro_images_0693W00000bjOrbQAE.png 


_legacyfs_online_stmicro_images_0693W00000bjOuVQAU.png 

The file: Loader_Src.c

In the end of the function Init(), I invoke BSP_QSPI_EnableMemoryMappedMode(). This function is also invoked in the beginning of the function Verify().

What could be the problem in "external loader mode"? Read operation is managed directly by CubeProgrammer. Any Idea?

Thanks in advance!

Other information

Hardware

Flash = MT25QL128ABA

Processor: STM32F767IIT6

The customer board uses an external 12 MHz crystal, and this loader is configured to use this external crystal.

Development tools

STM32CubeIDE, Version: 1.12.0, Build: 14980_20230301_1550 (UTC)

STM32CubeProgrammer V2.13.0

More info

Datasheet MT25QL128ABA

External Loader demo project (Used as reference)

1 ACCEPTED SOLUTION

Accepted Solutions

You can't use IRQs in the loaders. You perhaps could if you dealt with the load address and vector table properly, but this does not.

Use POLLED mode for UART and QSPI operation.

Do not use SysTick or delays dependent on it. You can fane HAL_GetTick() via a 32-bit TIM or count based on DWT->CYCCNT operation.

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

View solution in original post

6 REPLIES 6
AJack.5
Associate II

I have noticed that if I do a disconnect and then connect, it is possible to read from extrnal flash memory one more time, without any problem. As long as I disconnect and then connect I can read over and over again.

In the Log panel, I have also increased the verbosity level to 3 so more information is shown. See below:

First read works fine (Does not matter how many lines i read, always work)

19:53:35:529 : Read progress:

 19:53:35:529 : Reading data...

 19:53:35:696 : r ap 0 @0x08000000 0x00000400 bytes Data 0x20080000

 19:53:35:696 : Data read successfully

 19:53:35:696 : Time elapsed during the read operation is: 00:00:00.143

 19:53:36:254 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:37:156 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:38:192 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:39:212 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:40:323 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:41:367 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:42:389 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:42:613 : UPLOADING ...

 19:53:42:613 :  Size         : 1024 Bytes

 19:53:42:613 :  Address      : @0x90000000

 19:53:42:613 : Read progress:

 19:53:42:613 : Reading data...

 19:53:42:710 : halt ap 0

 19:53:42:710 : w ap 0 reg 15 PC  (0x20000000) 

 19:53:42:710 : w ap 0 reg 17 MSP (0x20000500) 

 19:53:42:710 : w ap 0 reg 16 xPSR (0x01000000) 

 19:53:42:710 : w ap 0 @0x2004E500 : 0x00000200 bytes, Data 0x00000000...

 19:53:42:710 : w ap 0 @0x20000000 : 0x00000004 bytes, Data 0x0000BE00...

 19:53:45:275 : w ap 0 @0x20000004 : 0x0004E0C4 bytes, Data 0x00000000...

 19:53:45:276 : Init flashloader...

 19:53:45:309 : halt ap 0

 19:53:45:470 : w ap 0 reg 0 R0  0x00000000

 19:53:45:470 : w ap 0 reg 1 R1  0x00000000

 19:53:45:470 : w ap 0 reg 2 R2  0x00000000

 19:53:45:470 : w ap 0 reg 3 R3  0x00000000

 19:53:45:470 : w ap 0 reg 4 R4  0x00000000

 19:53:45:470 : w ap 0 reg 5 R5  0x00000000

 19:53:45:588 : w ap 0 reg 6 R6  0x00000000

 19:53:45:594 : w ap 0 reg 7 R7  0x00000000

 19:53:45:704 : w ap 0 reg 8 R8  0x00000000

 19:53:45:704 : w ap 0 reg 9 R9  0x00000000

 19:53:46:000 : w ap 0 reg 10 R10 0x00000000

 19:53:46:000 : w ap 0 reg 11 R11 0x00000000

 19:53:46:000 : w ap 0 reg 12 R12 0x00000000

 19:53:46:000 : w ap 0 reg 13 SP  0x00000000

 19:53:46:000 : w ap 0 reg 14 LR  0x20000001

 19:53:46:000 : w ap 0 reg 15 PC  0x20031205

 19:53:46:000 : w ap 0 reg 16 xPSR 0x01000000

 19:53:46:000 : w ap 0 reg 17 MSP 0x2004E4C4

 19:53:46:000 : w ap 0 reg 18 PSP 0x00000000

 19:53:46:000 : run ap 0

 19:53:46:000 : halt ap 0

 19:53:46:004 : r ap 0 reg 0 R0  0x00000001

 19:53:46:155 : r ap 0 @0x90000000 0x00000400 bytes Data 0x00000000

 19:53:46:155 : Data read successfully

 19:53:46:155 : Time elapsed during the read operation is: 00:00:03.549

 19:53:46:395 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:47:383 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:48:461 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:49:564 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:50:579 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:53:51:591 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

Second read always failed

 19:53:52:771 : UPLOADING ...

 19:53:52:771 :  Size         : 1024 Bytes

 19:53:52:771 :  Address      : 0x90010000

 19:53:52:771 : Read progress:

 19:53:52:771 : Reading data...

 19:53:52:945 : halt ap 0

 19:53:52:945 : w ap 0 reg 15 PC  (0x20000000) 

 19:53:52:945 : w ap 0 reg 17 MSP (0x20000500) 

 19:53:52:945 : w ap 0 reg 16 xPSR (0x01000000) 

 19:53:52:945 : w ap 0 @0x2004E500 : 0x00000200 bytes, Data 0x00000000...

 19:53:52:945 : w ap 0 @0x20000000 : 0x00000004 bytes, Data 0x0000BE00...

 19:53:55:496 : w ap 0 @0x20000004 : 0x0004E0C4 bytes, Data 0x00000000...

 19:53:55:496 : Init flashloader...

 19:53:55:570 : halt ap 0

 19:53:55:760 : w ap 0 reg 0 R0  0x00000000

 19:53:55:760 : w ap 0 reg 1 R1  0x00000000

 19:53:55:760 : w ap 0 reg 2 R2  0x00000000

 19:53:55:760 : w ap 0 reg 3 R3  0x00000000

 19:53:55:760 : w ap 0 reg 4 R4  0x00000000

 19:53:55:760 : w ap 0 reg 5 R5  0x00000000

 19:53:55:760 : w ap 0 reg 6 R6  0x00000000

 19:53:55:760 : w ap 0 reg 7 R7  0x00000000

 19:53:55:760 : w ap 0 reg 8 R8  0x00000000

 19:53:55:760 : w ap 0 reg 9 R9  0x00000000

 19:53:55:760 : w ap 0 reg 10 R10 0x00000000

 19:53:55:760 : w ap 0 reg 11 R11 0x00000000

 19:53:55:760 : w ap 0 reg 12 R12 0x00000000

 19:53:55:760 : w ap 0 reg 13 SP  0x00000000

 19:53:55:760 : w ap 0 reg 14 LR  0x20000001

 19:53:55:760 : w ap 0 reg 15 PC  0x20031205

 19:53:55:760 : w ap 0 reg 16 xPSR 0x01000000

 19:53:55:921 : w ap 0 reg 17 MSP 0x2004E4C4

 19:53:55:921 : w ap 0 reg 18 PSP 0x00000000

 19:53:55:921 : run ap 0

 19:54:00:001 : halt ap 0

 19:54:00:001 : Init function fail with timeout

 19:54:00:007 : r ap 0 reg 16 xPSR 0x21000036

 19:54:00:177 : halt ap 0

 19:54:00:177 : w ap 0 reg 15 PC  (0x20000000) 

 19:54:00:183 : w ap 0 reg 17 MSP (0x20000500) 

 19:54:00:185 : w ap 0 reg 16 xPSR (0x01000000) 

 19:54:00:289 : Error: Data read failed

 19:54:01:223 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:02:074 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:03:105 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:04:117 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:05:130 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:06:201 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:07:262 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:08:276 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

 19:54:09:291 : r ap 0 @0x1FF0EDBE 0x00000004 bytes Data 0xFFFF0093

I typed a long response, touched the mouse wrong and lost it. I preferred the old Jive forum that would auto-save draft messages..

Use UART output to instrument your loader.

Loader doesn't need to move memory into most complex modes.

Init() functional called too often, ST wants memory in Memory Mapped mode

You can't communicate with the memory in this mode, you need to ABORT, or Reset Peripheral and Memory Device.

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

>>> Use UART output to instrument your loader.

I using the UART (in IRQ mode), but there is no output when the error occurs, so it seems that the execution stop very abrupt.

>>> Init() functional called too often,

I am not sure what you mean. I thouth that STM32CubeProgrammer invoked the init() function, so I have no control of this invokation.

>>> ... ST wants memory in Memory Mapped mode

>>> You can't communicate with the memory in this mode, you need to ABORT, or Reset Peripheral >>> and Memory Device.

The function HAL_QSPI_Abort() is used in SectorErase() and Write(). The init() function seems to reinit processor each time it is invoked. Do you think I need to change the init() function?

int Init(void)
{
 
    *(uint32_t*)0xE000EDF0 = 0xA05F0000; //enable interrupts in debug
 
    SystemInit();
 
    /* ADAPTATION TO THE DEVICE
     *
     * change VTOR setting for H7 device
     * SCB->VTOR = 0x24000000 | 0x200;
     *
     * change VTOR setting for other devices
     * SCB->VTOR = 0x20000000 | 0x200;
     *
     * */
 
    SCB->VTOR = 0x20000000 | 0x200;
 
    HAL_Init();
 
    SystemClock_Config();
 
    MX_GPIO_Init();
    MX_USART2_UART_Init();
    DBSR_init();
    init_debug_uart();
    DBSR_clear_screen();
 
    __HAL_RCC_QSPI_FORCE_RESET();  //completely reset peripheral
    __HAL_RCC_QSPI_RELEASE_RESET();
 
    DBSR_printf("Enter flash MT25QL128 loader\n\r");
    DBSR_uart_send_msg();
 
    DBSR_printf("Enter func: Init\n\r");
    DBSR_uart_send_msg();
    DBSR_printf("BSP_QSPI_Init\n\r");
    DBSR_uart_send_msg();
 
 
    if (BSP_QSPI_Init() != HAL_OK)
    {
        HAL_SuspendTick();
        return LOADER_FAIL;
    }
 
    if (BSP_QSPI_EnableMemoryMappedMode() != HAL_OK)
    {
        HAL_SuspendTick();
        return LOADER_FAIL;
    }
 
    HAL_SuspendTick();
    return LOADER_OK;
}
int SectorErase(uint32_t EraseStartAddress, uint32_t EraseEndAddress)
{
 
    HAL_ResumeTick();
 
    if (HAL_QSPI_Abort(&hqspi) != HAL_OK)
    {
    	DBSR_printf("Error: SectorErase()\n\r");
    	DBSR_uart_send_msg();
 
        HAL_SuspendTick();
        return LOADER_FAIL;
    }
 
 
    if (BSP_QSPI_Erase_64kb_Sectors(EraseStartAddress, EraseEndAddress) != HAL_OK)
    {
    	DBSR_printf("Error: SectorErase() => BSP_QSPI_Erase()\n\r");
    	DBSR_uart_send_msg();
 
        HAL_SuspendTick();
        return LOADER_FAIL;
    }
 
    HAL_SuspendTick();
    return LOADER_OK;
}
 
 
int Write(uint32_t Address, uint32_t Size, uint8_t* buffer)
{
 
	DBSR_printf("\rEntering %s\n\r", __func__);
	DBSR_uart_send_msg();
 
	DBSR_printf("\tAddress = 0x%X\n\r", (unsigned int) Address);
	DBSR_uart_send_msg();
 
	DBSR_printf("\tSize = 0x%08X\n\r", (unsigned int) Size);
	DBSR_uart_send_msg();
 
    HAL_ResumeTick();
 
 
    if (HAL_QSPI_Abort(&hqspi) != HAL_OK)
    {
    	DBSR_printf("Error: Write() => HAL_QSPI_Abort()\n\r");
    	DBSR_uart_send_msg();
 
        HAL_SuspendTick();
        return LOADER_FAIL;
    }
 
 
    if (BSP_QSPI_Write((uint8_t*) buffer, (Address & (0x0fffffff)), Size) != QSPI_OK)
    {
    	DBSR_printf("Error: Write() => BSP_QSPI_Write()\n\r");
    	DBSR_uart_send_msg();
 
        HAL_SuspendTick();
        return LOADER_FAIL;
    }
 
    HAL_SuspendTick();
    return LOADER_OK;
}

You can't use IRQs in the loaders. You perhaps could if you dealt with the load address and vector table properly, but this does not.

Use POLLED mode for UART and QSPI operation.

Do not use SysTick or delays dependent on it. You can fane HAL_GetTick() via a 32-bit TIM or count based on DWT->CYCCNT operation.

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

Thank for the help Tesla DeLorean. I have now removed UART IRQ and used internal PLL instead of the external crystal, and I am now able to read, erase and write over and over again without any problems.

I have uploaded the new code below, that handle the external flash MT25QL128ABA.

Thanks @Community member​ for sharing the exact solution and the external flashloader. That may be helpful for other users.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.