cancel
Showing results for 
Search instead for 
Did you mean: 

CubeProgrammer fails to erase multiple external sectors

CButz.1
Associate III

We are currently trying to build a external loader for our application.

Our System consists of a STM32H743 and a STM32F427ZIT.

For the initial upload of the firmware the DFU interface of the H7 should be used and via a external loader application loaded to the F4 via SPI1 (of the F4) bootloader.

We successfully built a external loader with Init, Read, Write, SectorErase and MassErase.

All these functions work when used via the STM32CubeProgrammer application.

However the SectorErase completes successfully only for one section, if multiple external sections are to be erased cubeprogrammer fails "Error: Sector erase operation has failed at least for one of the existing specified sectors.Please verify flash memory protection."

We have debug output of our own external loader:

eg.:

Debug Start for SPI external Loader
Init with SPI bootloader status: 1
SectorErase with StartAdr: 0x8040000 and EndAd: 0x8040000
SectorErase success StartAdr: 0x8060000 and EndAd: 0x8040000

This output is generated when trying to erase sector 2 (True sectors of F4 are combined to only homogenous sectors of size 0x20000). (Note 0x8060000 is only generated because of += sectorsize, see code bellow)

The same Output is generated if we try to erase sector 2 and 3, therefore our loader never receives the second SectorErase.

The erase of the first sector succeeds.

Sector 3 is erasable when its the only one selected, but not when multiple are selected. This holds true for all combinations of sectors.

I have 3 log files attached, two success when sector 2/3 is selected as the only one. And one fail with sector 2&3 selected.

Here is my implementation of SectorErase in Loader_Src.c:

 

 

int SectorErase(uint32_t EraseStartAddress, uint32_t EraseEndAddress) {
	EraseStartAddress &= ~(0xF0000000);
	EraseStartAddress |= 0x08000000;
	EraseEndAddress &= ~(0xF0000000);
	EraseEndAddress |= 0x08000000;

    __set_PRIMASK(0); //enable interrupts

    snprintf((char *)debugTemp,128, "SectorErase with StartAdr: 0x%X and EndAd: 0x%X\n\r" ,EraseStartAddress, EraseEndAddress);
	HAL_UART_Transmit(&huart7, debugTemp, strlen((char*)debugTemp), 100);

    uint32_t sector;
    uint32_t sectorSize;
    uint8_t realNbSectors = 0;

    while(EraseStartAddress <= EraseEndAddress){
    	sector = flashGetSector(EraseStartAddress, &sectorSize, &realNbSectors);
    	if(BL_EraseMemory_Command(realNbSectors - 1, sector) != HAL_OK){
    	    snprintf((char *)debugTemp,128, "SectorErase failed StartAdr: 0x%X and EndAd: 0x%X\n\r" ,EraseStartAddress, EraseEndAddress);
    		HAL_UART_Transmit(&huart7, debugTemp, strlen((char*)debugTemp), 100);
            __set_PRIMASK(1); //disable interrupts
            return LOADER_FAIL;
    	}
    	EraseStartAddress += sectorSize;
    }
	snprintf((char *)debugTemp,128, "SectorErase success StartAdr: 0x%X and EndAd: 0x%X\n\r" ,EraseStartAddress, EraseEndAddress);
	HAL_UART_Transmit(&huart7, debugTemp, strlen((char*)debugTemp), 100);

    __set_PRIMASK(1); //disable interrupts
    return LOADER_OK;
}

 

 

 However I think the problem is somehow at the cubeprogrammer side, as the output of UART suggests.

1 ACCEPTED SOLUTION

Accepted Solutions
CButz.1
Associate III

I found a solution, yet i dont fully understand the reason why its happening.

The following can be observed:

When connected via Programmer and calling sector 1 erase and after that sector 2 erase, the external loader executes the following functions

Init -> SectorErase 1 -> (Pause for user input) -> Init -> SectorErase 2

This succeeds.

However the sequence for SectorErase 1&2 is the same (without pause)

Init -> SectorErase 1 -> Init -> SectorErase 2

Yet the external loader failed in the second Init call, it needed HAL_SPI_DeInit(&hspi1); before MX_SPI1_Init();, same for UART, thats why i suspected the cubeprogrammer never calls sectorErase 2.

I did change to SPI_FLASH however it had no impact on this issue.

View solution in original post

4 REPLIES 4

The Internal memory is at 0x08000000

QSPI is typically at 0x90000000, but the basis passed to the memory device is zero based, the 0x90000000 is the decode address within the ARM's address space.

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

There is no QSPI involved in this process. We have a STM32H7 on which the external loader gets executed. This external loader then communicates with a STM32F4 in bootloader mode via SPI.

In the Dev_Inf.c I define the Start Address as 0x70000000 and in the actual implementation of SectorErase function which gets called by CubeProgrammer the address is then converted to the correct 0x0800000 address. This works fine, but as stated successive calls dont work on the CubeProgrammer side as the external loader application on the STM32H7 never gets the second command for the SectorErase

Dev_Inf.c:

 

/*
 * Dev_Inf.c
 *
 */
#include "Dev_Inf.h"
#include "main.h"

/* This structure contains information used by ST-LINK Utility to program and erase the device */
#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo  =  {
#else
struct StorageInfo const StorageInfo = {
#endif
    "_M4SPI_v01",                  // Device Name + version number
	MCU_FLASH,                           // Device Type
    0x70000000,                          // Device Start Address
	0x00200000,                 		 // Device Size in Bytes
	0x100,            			         // Programming Page Size
    0xFF,                                // Initial Content of Erased Memory

    // Specify Size and Address of Sectors (view example below)
    {   {
			16,  				// Sector Numbers,
			(uint32_t) 0x20000 	//Sector Size
		},
        { 0x00000000, 0x00000000 }
    }

 

 

I'd probably go with SPI_FLASH as the type, this allows for Read() and Write() to furnish functionality rather than ever being memory mapped.

Signalling the other device adds some complexity, but should work, and should be sufficiently timely that the programmer won't timeout on you. STM32 Cube Programmer doesn't provide a means to quantified time to completion.

External Loader typically don't need to use interrupts, but can if construct and map the Vector Table. Generally you don't want to leave interrupts running outside the entry/exit of the individual functions as you'll effectively crash the processor, or latch up the NVIC nesting levels.

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

I found a solution, yet i dont fully understand the reason why its happening.

The following can be observed:

When connected via Programmer and calling sector 1 erase and after that sector 2 erase, the external loader executes the following functions

Init -> SectorErase 1 -> (Pause for user input) -> Init -> SectorErase 2

This succeeds.

However the sequence for SectorErase 1&2 is the same (without pause)

Init -> SectorErase 1 -> Init -> SectorErase 2

Yet the external loader failed in the second Init call, it needed HAL_SPI_DeInit(&hspi1); before MX_SPI1_Init();, same for UART, thats why i suspected the cubeprogrammer never calls sectorErase 2.

I did change to SPI_FLASH however it had no impact on this issue.