LPC804 write flash single word

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

LPC804 write flash single word

跳至解决方案
1,648 次查看
phatpaul
Contributor III

My nonvolatile storage driver needs to write 4 bytes at a time to an already erased sector (i.e. memory contents starts at 0xFFFFFFFF 0x0 before being written to once). When an entire sector is used up, then a garbage-collection routine erases the entire sector and it can begin to be written again.

When I called IAP_CopyRamToFlash() with size of 4 bytes, I got the error COUNT_ERROR (Byte count is not 64 | 128 | 256 | 512 | 1024).

I'm disappointed to find that the minimum write size for IAP flash is 64 bytes, not 4 bytes as I expected (and is possible with Kinetis).

It seems to be a shame if I have to buffer 64-bytes in RAM to read-modify-write just 4-bytes at a time.

Is it possible to workaround this limitation by loading the 64-byte buffer with all 0xFFFFFFFF 0x0 except for the word that I want to program at that time?  Will the other words be unaffected by the write and retain their value?

Is there an example of doing this?

EDIT: There's a similar unanswered question here: https://community.nxp.com/t5/LPC-Microcontrollers/LPC804-FLASH-write-disturbance/m-p/1020218

EDIT: Looks like the erased state of the flash is '0', not 0xFF.  I found a KB for LPC55xx (but not for LPC8xx) which confirms it: https://community.nxp.com/t5/LPC-Microcontrollers-Knowledge/LPC55xx-Erased-Memory-State-0-or-1/ta-p/...  That's going to cause more difficulty in porting my nonvolatile storage driver, but my question still stands. 

标记 (2)
0 项奖励
1 解答
1,616 次查看
phatpaul
Contributor III

I made a simple test program to test my theory.  If it works it should result in the page containing 00000000 11111111 22222222 333333333 ...

// Test overwrite page assuming erased state is 0x0
    for (int woff = 0; woff < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; woff++)
    {
        memset(&s_PageBuf[0], 0, sizeof(s_PageBuf));
        s_PageBuf[woff] = 0x11111111 * woff;
        PRINTF("\r\nWrite page %d:", s_IapFlashPage);
        for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; i++)
        {
            PRINTF(" %X", s_PageBuf[i]);
        }
        /* write a page */
        IAP_PrepareSectorForWrite(DEMO_IAP_FLASH_SECTOR, DEMO_IAP_FLASH_SECTOR);
        IAP_CopyRamToFlash(s_IapFlashPage * FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, &s_PageBuf[0],
                           FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
        PRINTF("\r\nRead page %d:", s_IapFlashPage);
        uint32_t *read_ptr = (s_IapFlashPage)*FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
        for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; i++)
        {
            PRINTF(" %X", *read_ptr++);
        }
    }

 

Unfortunately, it doesn't do that.  It seems like the driver is doing an erase of the page before programming.  (So why do they tell us we have to do an explicit erase before programming anyway?)

Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 11111111 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 11111111 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 22222222 0 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 22222222 0 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 33333333 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 33333333 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 44444444 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 44444444 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 55555555 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 55555555 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 66666666 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 66666666 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 77777777 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 77777777 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 88888888 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 88888888 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 99999999 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 99999999 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 AAAAAAAA 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 AAAAAAAA 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 BBBBBBBB 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 BBBBBBBB 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 CCCCCCCC 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 CCCCCCCC 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0  0 DDDDDDDD 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 DDDDDDDD 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 EEEEEEEE 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 EEEEEEEE 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FFFFFFFF
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FFFFFFFF

 

I found some example code from @ErichStyger which shows how to buffer the page and do a read-modify-write.  https://github.com/ErichStyger/McuOnEclipseLibrary/blob/master/lib/minIni/McuFlash.c#L213  So I guess that's what I have to do.

 

 

在原帖中查看解决方案

0 项奖励
5 回复数
1,617 次查看
phatpaul
Contributor III

I made a simple test program to test my theory.  If it works it should result in the page containing 00000000 11111111 22222222 333333333 ...

// Test overwrite page assuming erased state is 0x0
    for (int woff = 0; woff < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; woff++)
    {
        memset(&s_PageBuf[0], 0, sizeof(s_PageBuf));
        s_PageBuf[woff] = 0x11111111 * woff;
        PRINTF("\r\nWrite page %d:", s_IapFlashPage);
        for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; i++)
        {
            PRINTF(" %X", s_PageBuf[i]);
        }
        /* write a page */
        IAP_PrepareSectorForWrite(DEMO_IAP_FLASH_SECTOR, DEMO_IAP_FLASH_SECTOR);
        IAP_CopyRamToFlash(s_IapFlashPage * FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, &s_PageBuf[0],
                           FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
        PRINTF("\r\nRead page %d:", s_IapFlashPage);
        uint32_t *read_ptr = (s_IapFlashPage)*FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
        for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; i++)
        {
            PRINTF(" %X", *read_ptr++);
        }
    }

 

Unfortunately, it doesn't do that.  It seems like the driver is doing an erase of the page before programming.  (So why do they tell us we have to do an explicit erase before programming anyway?)

Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 11111111 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 11111111 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 22222222 0 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 22222222 0 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 33333333 0 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 33333333 0 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 44444444 0 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 44444444 0 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 55555555 0 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 55555555 0 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 66666666 0 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 66666666 0 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 77777777 0 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 77777777 0 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 88888888 0 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 88888888 0 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 99999999 0 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 99999999 0 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 AAAAAAAA 0 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 AAAAAAAA 0 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 BBBBBBBB 0 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 BBBBBBBB 0 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 CCCCCCCC 0 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 CCCCCCCC 0 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0  0 DDDDDDDD 0 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 DDDDDDDD 0 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 EEEEEEEE 0
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 EEEEEEEE 0
Write page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FFFFFFFF
Read page 224: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FFFFFFFF

 

I found some example code from @ErichStyger which shows how to buffer the page and do a read-modify-write.  https://github.com/ErichStyger/McuOnEclipseLibrary/blob/master/lib/minIni/McuFlash.c#L213  So I guess that's what I have to do.

 

 

0 项奖励
1,591 次查看
ErichStyger
Senior Contributor V

Hi @phatpaul ,

I just added support for the LPC804 to the McuFlash module. I quickly tested it with the MinINI (see https://mcuoneclipse.com/2021/12/19/key-value-pairs-in-flash-memory-file-system-less-minini/ ) which uses the flash, you can find the project here:

https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/LPC804/LPC804_Blinky

I did not do much testing, but it seems to work fine.

I hope this helps,

Erich

0 项奖励
1,582 次查看
phatpaul
Contributor III

@ErichStyger Thanks so much for all of your example code!  (I hope NXP is paying you something to provide the support we need

0 项奖励
1,620 次查看
phatpaul
Contributor III

What happened to the reply I just posted??  I saw it posted then it disappeared.  This forum is so frustrating!

EDIT: Well my missing post just re-appeared a day later, after I retyped it and posted my answer.  So this thread may read a bit out-of-order.  Is it a moderator delay?

0 项奖励
1,611 次查看
phatpaul
Contributor III

I tested my theory by with an example program that tries to write successive words while leaving the others alone. 

I added this to the end of the iap_flash.c in example project "lpcxpresso804_iap_flash":

 

    for (int woff = 0; woff < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; woff++)
    {
        memset(&s_PageBuf[0], 0, sizeof(s_PageBuf));
        s_PageBuf[woff] = 0x11111111 * woff;
        PRINTF("\r\nWriting flash sector %d:", DEMO_IAP_FLASH_SECTOR);
        for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; i++)
        {
            PRINTF(" %8X", s_PageBuf[i]);
        }
        /* write a page */
        IAP_PrepareSectorForWrite(DEMO_IAP_FLASH_SECTOR, DEMO_IAP_FLASH_SECTOR);
        IAP_CopyRamToFlash(s_IapFlashPage * FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, &s_PageBuf[0],
                           FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES, SystemCoreClock);
        PRINTF("\r\nReading flash sector %d:", DEMO_IAP_FLASH_SECTOR);
        uint32_t *read_ptr = (s_IapFlashPage)*FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES;
        for (i = 0; i < FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES / 4; i++)
        {
            PRINTF(" %8X", *read_ptr++);
        }
    }

 

I expected the result to be 00000000 11111111 22222222 33333333 444444444 ....

Unfortunately it doesn't work as it appears that the chip is actually erasing the page each time.  So what's the point of telling us to do an explicit erase before writing then?  I wonder if that will actually do 2 erases?

 

Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0        0        0        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0        0        0        0
Writing flash sector 14:        0 11111111        0        0        0        0        0        0        0        0        0        0        0        0        0        0
Reading flash sector 14:        0 11111111        0        0        0        0        0        0        0        0        0        0        0        0        0        0
Writing flash sector 14:        0        0 22222222        0        0        0        0        0        0        0        0        0        0        0        0        0
Reading flash sector 14:        0        0 22222222        0        0        0        0        0        0        0        0        0        0        0        0        00
Writing flash sector 14:        0        0        0 33333333        0        0        0        0        0        0        0        0        0        0        0        0
Reading flash sector 14:        0        0        0 33333333        0        0        0        0        0        0        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0 44444444        0        0        0        0        0        0        0        0        0        0        0
Reading flash sector 14:        0        0        0        0 44444444        0        0        0        0        0        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0 55555555        0        0        0        0        0        0        0        0        0        0
Reading flash sector 14:        0        0        0        0        0 55555555        0        0        0        0        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0 66666666        0        0        0        0        0        0        0        0         0
Reading flash sector 14:        0        0        0        0        0        0 66666666        0        0        0        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0 77777777        0        0        0        0        0        0        0        0
Reading flash sector 14:        0        0        0        0        0        0        0 77777777        0        0        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0 88888888        0        0        0        0        0        0        0
Reading flash sector 14:         0        0        0        0        0        0         0        0 88888888        0        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0 99999999        0        0        0        0        0        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0 99999999        0        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0 AAAAAAAA        0        0        0        0        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0 AAAAAAAA        0        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0        0 BBBBBBBB        0        0        0        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0        0 BBBBBBBB        0        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0 CCCCCCCC        0        0        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0 CCCCCCCC        0        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0 DDDDDDDD        0        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0 DDDDDDDD        0        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0        0 EEEEEEEE        0
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0        0 EEEEEEEE        0
Writing flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0        0        0 FFFFFFFF
Reading flash sector 14:        0        0        0        0        0        0        0        0        0        0        0        0        0        0        0 FFFFFFFF

 

 

0 项奖励