cancel
Showing results for 
Search instead for 
Did you mean: 

C55 Flash Driver FlashProgram and FlashErase IVOR1

Yalin Gurcan
Associate II

Hi all,

I am using the C55 Flash Drivers on the SPC570S40E1 mcu. When trying to write data from RAM to any of the low blocks, I get a Machine Check Interrupt after I call the function FlashProgram. The same thing happens with FlashErase as well. However, if I look at the memory locations, I can see that the data is correctly written (or erased) even though I get the machine check interrupt.

Funny thing is, I can program and erase the 8KB High blocks no problem, but all low blocks create this issue.

The code is like this

#include "flash_ctrl.h"
 
uint32_t flash_init(void)
{
    pgmCtxData.pReqCompletionFn = FlashProgram;
    bcCtxData.pReqCompletionFn = BlankCheck;
    pvCtxData.pReqCompletionFn = ProgramVerify;
    returnCode = FlashInit( &ssdConfig );
    return returnCode;
}
 
uint32_t utest_lock(void)
{
    returnCode = GetLock(&ssdConfig, C55_BLOCK_UTEST, &blkLockState);
    if (!(blkLockState & 0x00000001))
        returnCode = SetLock(&ssdConfig, C55_BLOCK_UTEST, LOCK_ALL_BLOCKS);
    return returnCode;
}
 
uint32_t unblock_address_space(void)
{
    returnCode = SetLock(&ssdConfig, C55_BLOCK_LOW, UNLOCK_ALL_BLOCKS);
    returnCode = SetLock(&ssdConfig, C55_BLOCK_LARGE_FIRST, UNLOCK_ALL_BLOCKS);
    returnCode = SetLock(&ssdConfig, C55_BLOCK_HIGH, UNLOCK_ALL_BLOCKS);
    return returnCode;
}
 
uint32_t erase_block(MEM_BLOCK eraseBlock)
{
	switch(eraseBlock){
		case LOW_BLOCK1_16K:
			lowBlockSelect = 0x00000002UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK2_16K:
			lowBlockSelect = 0x00000004UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK3_16K:
			lowBlockSelect = 0x00000008UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK4_16K:
			lowBlockSelect = 0x00000010UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 3;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK5_32K:
			lowBlockSelect = 0x00000020UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK6_32K:
			lowBlockSelect = 0x00000040UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK7_64K:
			lowBlockSelect = 0x00000080UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LOW_BLOCK8_64K:
			lowBlockSelect = 0x00000100UL;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LARGE_BLOCK9_128K:
			lowBlockSelect = 0;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 1;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case LARGE_BLOCK10_128K:
			lowBlockSelect = 0;
			midBlockSelect = 0;
			highBlockSelect = 0;
			nLargeBlockSelect.firstLargeBlockSelect = 2;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case HIGH_BLOCK0_8K:
			lowBlockSelect = 0;
			midBlockSelect = 0;
			highBlockSelect = 0x00000001UL;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case HIGH_BLOCK1_8K:
			lowBlockSelect = 0;
			midBlockSelect = 0;
			highBlockSelect = 0x00000002UL;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case HIGH_BLOCK2_8K:
			lowBlockSelect = 0;
			midBlockSelect = 0;
			highBlockSelect = 0x00000004UL;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
		case HIGH_BLOCK3_8K:
			lowBlockSelect = 0;
			midBlockSelect = 0;
			highBlockSelect = 0x00000008;
			nLargeBlockSelect.firstLargeBlockSelect = 0;
			nLargeBlockSelect.secondLargeBlockSelect = 0;
			break;
	}
    returnCode = FlashErase( &ssdConfig, C55_ERASE_MAIN, lowBlockSelect, midBlockSelect, highBlockSelect, nLargeBlockSelect );
    if (returnCode == C55_OK)
        while (C55_INPROGRESS == FlashCheckStatus(&ssdConfig, C55_MODE_OP_ERASE, &opResult,&dummyCtxData)) {}
    return returnCode;
}
 
uint32_t blank_check(uint32_t dest, uint32_t size)
{
    returnCode = BlankCheck(&ssdConfig, dest, size, &failAddress, &failData, &bcCtxData);
    if (returnCode == C55_OK)
        while (C55_INPROGRESS == FlashCheckStatus(&ssdConfig, C55_MODE_OP_BLANK_CHECK, &opResult,&bcCtxData)) {};
    return returnCode;
}
 
uint32_t program_and_verify(uint32_t dest, uint32_t buffer, uint32_t size)
{
    returnCode = FlashProgram(&ssdConfig, TRUE, dest, size, buffer, &pgmCtxData);
    if (returnCode == C55_OK)
    {
        while (C55_INPROGRESS == FlashCheckStatus(&ssdConfig, C55_MODE_OP_PROGRAM, &opResult, &pgmCtxData)) {};
    }
    returnCode = ProgramVerify( &ssdConfig, dest, size, (UINT32) buffer, &failAddress, &failData, &failSource, &pvCtxData);
    if (returnCode == C55_OK)
    {
        while (C55_INPROGRESS == FlashCheckStatus(&ssdConfig, C55_MODE_OP_PROGRAM_VERIFY, &opResult, &pvCtxData)) {};
    }
    return returnCode;
}

And the ssdConfig I write as

SSD_CONFIG ssdConfig = {
    C55_REG_BASE,         /* C55 control register base */
    MAIN_ARRAY_BASE,      /* base of main array */
    {0, 4, 2, 2},          /* blocks info of low address space */
    {0, 0, 0, 0},          /* blocks info of mid address space */
    {4, 0, 0, 0},          /* blocks info of high address space */
    2,                    /* number of blocks in 256K address space */
    UTEST_ARRAY_BASE,     /* base of UTEST array */
    FALSE,                 /* interface flag indicate main or alternate interface */
    C55_PROGRAMMABLE_SIZE,/* programmable size */
    TRUE                 /* debug mode selection */
};

I call the flash_init(), utest_lock(), unblock_address_space() functions before erasing/writing with no issues.

Thanks in advance

3 REPLIES 3
david tomsa
Associate III

Hi,

could you show us the definition of FlashProgram? This function should executed from Ram. It looks like an read while write problem.

Yalin Gurcan
Associate II

Hi David,

FlashProgram function is provided in the C55 Flash Driver. I don't have access to the codes, only the binaries.

https://www.st.com/content/ccc/resource/technical/document/user_manual/81/e1/4a/30/71/f3/49/11/DM00079532.pdf/files/DM00079532.pdf/jcr:content/translations/en.DM00079532.pdf

procolo
Senior

Hello,

you cannot erase/program in the same partition code is running.

SPC570S40E1 has only two partitions: one for code (LOW and 128K blocks) and one for dataflash (HIGH).

If your code is running on flash , you can only erase/program data flash. If you want to erase/program code space , your code must be run from ram.

Regards