[SOLVED] Issue with custom External Loader for IS25LP256D on STM32F746 - update to V2.5.0 & deinit qspi in Init()
I've made a custom external loader for IS25LP256D on STM32F746. It works well in general except for one problem. Verify doesn't stop when "Verify Programming" is checked. Memory-mapped mode works well, which means reading is good. Erase() and Write() work well too.
Could someone please help me with this issue? I've attached the STM32 CubeProgrammer log.
#include "Loader_Src.h"
#include "quadspi.h"
#include "qflash.h"
#include <string.h>
/* Private variables ---------------------------------------------------------*/
extern QSPI_HandleTypeDef hqspi;
void Error_Handler(void) {
}
int Init (uint8_t configureMemoryMappedMode)
{
SystemInit();
HAL_Init();
SystemClock_Config();
/* Initialize QuadSPI ------------------------------------------------------ */
MX_QUADSPI_Init();
spiResetMemory();
spiEnableQEOnFlash();
spiSetDummyCyclesOnFlash();
if(!configureMemoryMappedMode)
{
if(spiEnterMemoryMappedMode() != 0)
{
return 0;
}
}
return 1;
}
KeepInCompilation int SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
{
uint32_t BlockAddr;
EraseStartAddress = EraseStartAddress - (EraseStartAddress % 0x10000);
spiEnterIndirectMode();
while(EraseEndAddress >= EraseStartAddress)
{
BlockAddr = EraseStartAddress & 0x0FFFFFFF;
if(spiErase64k(BlockAddr) != 0)
{
return 0;
}
EraseStartAddress += 0x10000;
}
return 1;
}
KeepInCompilation int Write(uint32_t Address, uint32_t Size, uint8_t* buffer)
{
uint32_t offset;
offset = Address & 0x0FFFFFFF;
spiEnterIndirectMode();
if(spiWrite(offset, buffer, Size) == 0)
return 1;
else
return 0;
}
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
return HAL_OK;
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 216;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Activate the Over-Drive mode
*/
if (HAL_PWREx_EnableOverDrive() != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
{
Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART5;
PeriphClkInitStruct.Uart5ClockSelection = RCC_UART5CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
uint32_t CheckSum(uint32_t StartAddress, uint32_t Size, uint32_t InitVal)
{
uint8_t missalignementAddress = StartAddress%4;
uint8_t missalignementSize = Size ;
int cnt;
uint32_t Val;
StartAddress-=StartAddress%4;
Size += (Size%4==0)?0:4-(Size%4);
for(cnt=0; cnt<Size ; cnt+=4)
{
Val = *(uint32_t*)StartAddress;
if(missalignementAddress)
{
switch (missalignementAddress & 0xF)
{
case 1:
InitVal += (uint8_t) (Val>>8 & 0xff);
InitVal += (uint8_t) (Val>>16 & 0xff);
InitVal += (uint8_t) (Val>>24 & 0xff);
missalignementAddress-=1;
break;
case 2:
InitVal += (uint8_t) (Val>>16 & 0xff);
InitVal += (uint8_t) (Val>>24 & 0xff);
missalignementAddress-=2;
break;
case 3:
InitVal += (uint8_t) (Val>>24 & 0xff);
missalignementAddress-=3;
break;
}
}
else if((Size-missalignementSize)%4 && (Size-cnt) <=4)
{
switch ((Size-missalignementSize) & 0xF)
{
case 1:
InitVal += (uint8_t) Val;
InitVal += (uint8_t) (Val>>8 & 0xff);
InitVal += (uint8_t) (Val>>16 & 0xff);
missalignementSize-=1;
break;
case 2:
InitVal += (uint8_t) Val;
InitVal += (uint8_t) (Val>>8 & 0xff);
missalignementSize-=2;
break;
case 3:
InitVal += (uint8_t) Val;
missalignementSize-=3;
break;
}
}
else
{
InitVal += (uint8_t) Val;
InitVal += (uint8_t) (Val>>8 & 0xff);
InitVal += (uint8_t) (Val>>16 & 0xff);
InitVal += (uint8_t) (Val>>24 & 0xff);
}
StartAddress+=4;
}
return (InitVal);
}
KeepInCompilation uint64_t Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size, uint32_t missalignement)
{
uint32_t InitVal = 0;
uint32_t VerifiedData = 0;
uint64_t checksum;
Size*=4;
#if 0
spiResetMemory();
spiEnableQEOnFlash();
spiSetDummyCyclesOnFlash();
#endif
if(spiEnterMemoryMappedMode() != 0)
return 0;
checksum = CheckSum((uint32_t)MemoryAddr + (missalignement & 0xf), Size - ((missalignement >> 16) & 0xF), InitVal);
while (Size>VerifiedData)
{
if ( *(uint8_t*)MemoryAddr++ != *((uint8_t*)RAMBufferAddr + VerifiedData))
return ((checksum<<32) + (MemoryAddr + VerifiedData));
VerifiedData++;
}
return (checksum<<32);
}
int MassErase(void)
{
spiEnterIndirectMode();
spiEraseChip();
return 1;
}After programming, the contents look good. I've run TouchGFX app with IS25LP256D, which contains images, fonts and texts. It is about 11MB in total. If the external image is not written in place, TouchGFX will cause a hard fault. But after programming external flash, it runs well.
Log generated the following messages until I pressed the stop button. Without verification my external loader has no problem.
20:50:01:397 : Init flashloader...
20:50:01:406 : halt ap 0
20:50:01:406 : w ap 0 reg 0 0x00000000
20:50:01:406 : w ap 0 reg 1 0x00000000
20:50:01:406 : w ap 0 reg 2 0x00000000
20:50:01:406 : w ap 0 reg 3 0x00000000
20:50:01:406 : w ap 0 reg 4 0x00000000
20:50:01:406 : w ap 0 reg 5 0x00000000
20:50:01:406 : w ap 0 reg 6 0x00000000
20:50:01:406 : w ap 0 reg 7 0x00000000
20:50:01:406 : w ap 0 reg 8 0x00000000
20:50:01:406 : w ap 0 reg 9 0x00000000
20:50:01:406 : w ap 0 reg 10 0x00000000
20:50:01:406 : w ap 0 reg 11 0x00000000
20:50:01:406 : w ap 0 reg 12 0x00000000
20:50:01:406 : w ap 0 reg 13 0x00000000
20:50:01:406 : w ap 0 reg 14 0x20000001
20:50:01:406 : w ap 0 reg 15 0x2000063B
20:50:01:406 : w ap 0 reg 16 0x01000000
20:50:01:406 : w ap 0 reg 17 0x2000E7D8
20:50:01:406 : w ap 0 reg 18 0x00000000
20:50:01:407 : run ap 0
20:50:01:407 : halt ap 0
20:50:01:407 : r ap 0 reg 0 0x00000001
20:50:01:475 : r ap 0 @0x90000000 0x00000400 bytes
20:50:01:476 : Reading data...
20:50:01:476 : reset ap 0
20:50:01:476 : run ap 0
20:50:01:476 : halt ap 0 Status = 0
20:50:01:476 : w ap 0 reg 15 (0x20000000)
20:50:01:476 : w ap 0 reg 17 (0x20000500)
20:50:01:476 : w ap 0 reg 16 (0x01000000)
20:50:01:476 : w ap 0 @0x2000E800 0x00000200 bytes
20:50:01:476 : w ap 0 @0x20000000 0x00000004 bytes
20:50:01:768 : w ap 0 @0x20000004 0x0000E3D8 bytes
20:50:01:768 : Init flashloader...
20:50:01:775 : halt ap 0
20:50:01:775 : w ap 0 reg 0 0x00000000
20:50:01:775 : w ap 0 reg 1 0x00000000
20:50:01:775 : w ap 0 reg 2 0x00000000
20:50:01:775 : w ap 0 reg 3 0x00000000
20:50:01:775 : w ap 0 reg 4 0x00000000
20:50:01:775 : w ap 0 reg 5 0x00000000
20:50:01:775 : w ap 0 reg 6 0x00000000
20:50:01:775 : w ap 0 reg 7 0x00000000
20:50:01:775 : w ap 0 reg 8 0x00000000
20:50:01:775 : w ap 0 reg 9 0x00000000
20:50:01:775 : w ap 0 reg 10 0x00000000
20:50:01:775 : w ap 0 reg 11 0x00000000
20:50:01:775 : w ap 0 reg 12 0x00000000
20:50:01:775 : w ap 0 reg 13 0x00000000
20:50:01:775 : w ap 0 reg 14 0x20000001
20:50:01:775 : w ap 0 reg 15 0x2000063B
20:50:01:775 : w ap 0 reg 16 0x01000000
20:50:01:775 : w ap 0 reg 17 0x2000E7D8
20:50:01:775 : w ap 0 reg 18 0x00000000
20:50:01:775 : run ap 0
20:50:01:835 : halt ap 0
20:50:01:835 : r ap 0 reg 0 0x00000001
20:50:01:835 : r ap 0 @0x90000000 0x00000400 bytes
20:50:01:835 : Reading data...
20:50:01:835 : reset ap 0
20:50:01:835 : run ap 0
20:50:01:852 : halt ap 0 Status = 0
20:50:01:852 : w ap 0 reg 15 (0x20000000)
20:50:01:852 : w ap 0 reg 17 (0x20000500)
20:50:01:852 : w ap 0 reg 16 (0x01000000)
20:50:01:853 : w ap 0 @0x2000E800 0x00000200 bytes
20:50:01:853 : w ap 0 @0x20000000 0x00000004 bytes
20:50:02:031 : aborting on going operation...
20:50:02:146 : w ap 0 @0x20000004 0x0000E3D8 bytes
20:50:02:146 : Operation canceled
20:50:02:165 : Error: Failed to read memory at address 0x90000000 during verification
20:50:02:165 : Error: Download verification failed
20:50:02:216 : RUNNING Program ...
20:50:02:216 : Address: : 0x08020000
20:50:02:267 : Application is running
20:50:02:274 : Start operation achieved successfully