Skip to main content
Explorer
March 17, 2017
Question

Programming an external flash

  • March 17, 2017
  • 2 replies
  • 1491 views
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.

    2 replies

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

    NickjmasAuthor
    Explorer
    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

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

    Visitor II
    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
    Explorer
    March 29, 2017
    Posted on March 29, 2017 at 13:48

    Hi lecordier.guy.001

    Thank you for your fix 

    Best regards