2023-05-04 07:54 AM - edited 2023-11-20 06:27 AM
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
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.
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
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.
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)
Solved! Go to Solution.
2023-05-08 08:07 AM
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.
2023-05-08 01:11 AM
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
2023-05-08 06:31 AM
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.
2023-05-08 07:15 AM
>>> 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;
}
2023-05-08 08:07 AM
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.
2023-05-09 07:36 AM
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.
2023-05-12 02:32 AM
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.