cancel
Showing results for 
Search instead for 
Did you mean: 

Programming an external flash

Nickjmas
Associate III
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
7 REPLIES 7
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
Up vote any posts that you find helpful, it shows what's working..
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

Lecordier.Guy
Associate III
Posted on March 21, 2017 at 17:06

S29GL128S has a 512-byte Programming Buffer

so

struct

StorageInfo

StorageInfo = {

..

0x00000200,

// Programming Page Size 512Bytes

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
Up vote any posts that you find helpful, it shows what's working..
Posted on March 29, 2017 at 13:48

Hi lecordier.guy.001

Thank you for your fix 

Best regards

Posted on March 29, 2017 at 13:52

Hi Clive,

I will test your suggestions

Thank you!

Posted on March 30, 2017 at 08:15

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?