LPC804 write flash single word

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

LPC804 write flash single word

ソリューションへジャンプ
2,069件の閲覧回数
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 解決策
2,037件の閲覧回数
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 返答(返信)
2,038件の閲覧回数
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 件の賞賛
返信
2,012件の閲覧回数
ErichStyger
Specialist I

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 件の賞賛
返信
2,003件の閲覧回数
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 件の賞賛
返信
2,041件の閲覧回数
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 件の賞賛
返信
2,032件の閲覧回数
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 件の賞賛
返信