2017-03-17 05:39 AM
Hi I'm trying program an external flash with the ST-Link Uility. I made a custom External Loader based on STM32F429ZI and the memory to program is a NOR flash S29GL128S (
http://www.cypress.com/file/177976/download
). When I try read from the external flash seems ok because I can see the content 0xFFFF inside the grid of ST-Link Utility. But when I try to program or erase sector/Chip I get errors. For example if I want program an hex I catch:12:55:11 : Device ID:0x419
12:55:11 : Device flash Size : 2MBytes
12:55:11 : Device family :STM32F42xxx/F43xxx
12:55:18 : [dcb430.hex] opened successfully.
12:55:18 : [dcb430.hex] checksum : 0x00C45668
12:55:24 : The elf loader Program function fails.
12:55:26 : The elf loader Program function fails.
12:55:26 : Memory-Loader error
12:55:26 : Error occured during program operation!
12:55:26 : Programming error @ 0x60000000!
The External Loader project has the Dev_Inf.c file with the definition based on memory flash datasheet:
struct StorageInfo const StorageInfo = {
'S29GL128S_STM3F429ZI', // Device Name + version number
NOR_FLASH, // Device Type
0x60000000, // Device Start Address
0x01000000, // Device Size in Bytes (16MBytes/128Mbits)
0x00000400, // Programming Page Size 1024 Bytes
0xFF, // Initial Content of Erased Memory
// Specify Size and Address of Sectors (view example below)
0x00000080, 0x00020000, // Sector Num : 128 ,Sector Size: 128KBytes
0x00000000, 0x00000000,
};
and
the Loader_Src.c has the implementation of Init, Read, Write, MassErase, SectorErase functions using the stm324x9i_eval_fmc_nor:Init function
int Init (void){
SystemInit();
NOR_Init();
return 1;
}
Read function Write function MassErase function SectorErase functionint Read (uint32_t Address, uint32_t Size, uint16_t* Buffer) {
uint32_t InternalAddr = Address - StartAddresse;
uint32_t ReadedData = 0;
uint32_t Counter = 0;
uint16_t TmpBuffer = 0x00000000;
if (InternalAddr%2 != 0)
{
NOR_ReadBuffer(&TmpBuffer, (InternalAddr - InternalAddr%2), 1);
for (Counter =0; (Counter<(InternalAddr%2))&&(Counter<Size); Counter++)
*((uint8_t*)Buffer+Counter) = *((uint8_t*)(&TmpBuffer)+InternalAddr%4+Counter);
ReadedData += Counter;
}
if (Size-ReadedData >= 2)
{
NOR_ReadBuffer((uint16_t*)((uint8_t*)Buffer+ReadedData), InternalAddr+ReadedData ,(Size-ReadedData)/2);
ReadedData += (((Size-ReadedData)/2)*2);
}
if (ReadedData < Size)
{
NOR_ReadBuffer(&TmpBuffer, InternalAddr+ReadedData ,1);
for (Counter =0; Counter<(Size-ReadedData); Counter++)
*((uint8_t*)Buffer+ReadedData+Counter) = *((uint8_t*)(&TmpBuffer)+Counter);
}
return 1;
}
Read function Write function MassErase function SectorErase functionint Write (uint32_t Address, uint32_t Size, uint16_t* Buffer)
{
uint32_t InternalAddr = Address - StartAddresse;
uint32_t WritedData = 0;
uint32_t Counter = 0;
uint16_t TmpBuffer = 0x00000000;
if (InternalAddr%2 != 0)
{
NOR_ReadBuffer (&TmpBuffer, (InternalAddr - InternalAddr%2),1);
for (Counter =0; (Counter<(2-InternalAddr%2))&&(Counter<Size); Counter++)
*((uint8_t*)(&TmpBuffer)+InternalAddr%2+Counter) = * ((uint8_t*)Buffer+Counter);
if (NOR_ProgramBuffer (&TmpBuffer, (InternalAddr - InternalAddr%2),1) != NOR_SUCCESS)
return 0;
WritedData += Counter;
}
if (Size-WritedData >= 2)
{
if (NOR_ProgramBuffer ((uint16_t*)((uint8_t*)Buffer+WritedData), InternalAddr+WritedData, ((Size-WritedData)/2))!=NOR_SUCCESS)
return 0;
WritedData += (((Size-WritedData)/2)*2);
}
if (WritedData < Size)
{
NOR_ReadBuffer (&TmpBuffer, InternalAddr+WritedData,1);
for (Counter =0; Counter<(Size-WritedData); Counter++)
*((uint8_t*)(&TmpBuffer)+Counter) = *((uint8_t*)Buffer+WritedData+Counter);
if (NOR_ProgramBuffer (&TmpBuffer, InternalAddr+WritedData,1)!=NOR_SUCCESS)
return 0;
}
return 1;
}
Read function Write function MassErase function SectorErase functionint MassErase (void)
{
if (NOR_EraseChip()==NOR_SUCCESS)
return 1;
else
return 0;
}
Read function Write function MassErase function SectorErase functionint SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
{
uint32_t BlockAddr;
EraseStartAddress = EraseStartAddress - EraseStartAddress%0x20000;
while (EraseEndAddress>=EraseStartAddress)
{
BlockAddr = EraseStartAddress - StartAddresse;
if (NOR_EraseBlock(BlockAddr)!=NOR_SUCCESS)
return 0;
EraseStartAddress+=0x20000;
}
return 1;
}
Any idea what could be wrong?
Best regards
#st-link-utility #custom-loaders2017-03-17 07:51 AM
For debugging I'd suggest you create a test framework using the functions, and run that in you IDE proving you can erase, write, read, etc.
2017-03-20 03:47 AM
Hi Clive One,
thank you for your suggest. After test it, it seems works fine when I'm debugging, but not when I use such as external loader.
The code I use for debugging isint main(void)
{
Fill_Buffer(aRxBuffer, BUFFER_SIZE, 0x2A50);
/* NOR memory initialization */
if (Init() == 1)
ok = 1;
else
ok = 0;
if (MassErase() == 1)
ok = 1;
else
ok = 0;
if (Read(0x60000000, 512, aTxBuffer) == 1)
ok = 1;
else
ok = 0;
if (Write(0x60000000, 512, aRxBuffer) == 1)
ok = 1;
else
ok = 0;
if (Read(0x60000000, 512, aTxBuffer) == 1)
ok = 1;
else
ok = 0;
if (SectorErase(0x60000000, 0x6001FFFF) == 1)
ok = 1;
else
ok = 0;
if (Read(0x60000000, 512, aTxBuffer) == 1)
ok = 1;
else
ok = 0;
while (1);
}
Any idea which could be the problem?
Best regards
2017-03-21 09:06 AM
S29GL128S has a 512-byte Programming Buffer
so
struct
StorageInfo
StorageInfo = {
..
0x00000200,
// Programming Page Size 512Bytes
2017-03-21 05:53 PM
>>Any idea which could be the problem?
You could output telemetry via a serial port, if you understand the command/function sequences that cause the failure you can either a) replicate them in your own test harness, and b) understand what the ST-LINK Utility is doing with the parameters/descriptors you have provided.
Double check the geometry is valid, per Guy's suggestion. This tends to be where things break if too much data is sent, or the erase impacts less memory than expected.
2017-03-29 06:48 AM
Hi lecordier.guy.001
Thank you for your fix
Best regards
2017-03-29 06:52 AM
Hi Clive,
I will test your suggestions
Thank you!
2017-03-30 01:15 AM
Hi Clive,
I'm wondering if the FSMC peripheral has a correct configuration.
Watching the nor flash's datasheet (
http://www.cypress.com/file/177976/download
in page 80) , for read operation, ADDSET = Tce-Toe = 65ns and DATAST = Toe + Toh = 25ns. For write operations, ADDSET = Tas = Tcs = 0ns and DATAST = Twp = 25ns. To use a diferent timing for each operation, I have a extended mode enabled and I think the correct working mode is C.What do you think about this configuration?