Skip to main content
Associate III
March 17, 2017
Question

Programming an external flash

Posted on March 17, 2017 at 13:39

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 function

int 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 function

int 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 function

int MassErase (void)

{

if (NOR_EraseChip()==NOR_SUCCESS)

   return 1;

else

   return 0;

}

Read function Write function MassErase function SectorErase function

int 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-loaders
This topic has been closed for replies.

7 replies

Tesla DeLorean
Guru
March 17, 2017
Posted on March 17, 2017 at 15:51

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.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
NickjmasAuthor
Associate III
March 20, 2017
Posted on March 20, 2017 at 10:47

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 is

int 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

Tesla DeLorean
Guru
March 22, 2017
Posted on March 22, 2017 at 00:53

>>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.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Lecordier.Guy
Associate III
March 21, 2017
Posted on March 21, 2017 at 17:06

S29GL128S has a 512-byte Programming Buffer

so

struct

StorageInfo

StorageInfo = {

..

0x00000200,

// Programming Page Size 512Bytes

NickjmasAuthor
Associate III
March 29, 2017
Posted on March 29, 2017 at 13:48

Hi lecordier.guy.001

Thank you for your fix 

Best regards