MPC5777C C55FMC reading a page causes programming to fail

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MPC5777C C55FMC reading a page causes programming to fail

Jump to solution
3,155 Views
ajmerijaimin
Contributor III

I'm using C55FMC to program partition-9 block-30 which is at 0x00F8_0000 location. For testing purposes, I write a sequence counter from 0x0000_0000 to 0x0000_FFFF as uint32_t value in each location. The write (erase + program) operation works fine. Data persists even after reset. The problem starts when I attempt to read the location 0x00F8_0000 before starting the write operation.

I try reading one location 0x00F8_0000 by de-referencing it for a uint32_t value. The contents of first page (0x00F8_0000 : 0x00F8_000C) is all 0xFFFF_FFFFs. I read it because I need to retrieve previously written data.

Please refer the main.c file from the attachment. Here I have just put the snippet of main function.

HW_init();

// this read causes the problem, if commented it's all good
bytes_read = read_flash((uint32_t *)TARGET_ADDRESS, gReadBuffer, READ_BUFFER_SIZE);

unlock_block(TARGET_SECTOR);

erase_block(TARGET_SECTOR, (uint32_t *)TARGET_ADDRESS);

while (counter < 0x10000)
{
	// fill 512 bytes with sequence counter
	for (uint32_t i=0; i<WRITE_BUFFER_SIZE; i++)
	{
		gWriteBuffer[i] = counter;
		counter++;
	}
	
	// write 512 bytes to flash
	if ((counter % WRITE_BUFFER_SIZE) == 0)
	{
		write_flash(TARGET_SECTOR, (uint32_t *)TARGET_ADDRESS + offset, gWriteBuffer, WRITE_BUFFER_SIZE);
		offset += WRITE_BUFFER_SIZE;
	}
}

 

I cannot make out what's going wrong when I read before writing to flash. It works fine if I don't read it. Need help. 

Please find the following attachments for your reference.
1. Screenshot of the memory dump.
2. 0x00F80000 memory dump as text file.
3. main.c file.
4. C55FMC registers dumps.

0 Kudos
Reply
1 Solution
2,987 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi,

I found out that this project forces stack to cache memory to achieve highest possible performance. That's the reason why invalidation or disabling of whole cache cause the troubles.

If I simply force the stack (R1) to normal RAM and disable the data cache, I can see it's working as expected. So, the cache is the source of issues. If you want to keep the cache enabled and keep the stack in cache, the easiest way should be to configure required flash area as cache inhibited. This can be done by MMU configuration.

https://community.nxp.com/t5/MPC5xxx-Knowledge-Base/MMU-Assist-Register-CONFIGURATOR/ta-p/1110436

Regards,

Lukas

 

View solution in original post

8 Replies
3,106 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi,

I can see the "0xFF area" corresponds to size of one cache line which is 32 bytes. Is the cache memory enabled? If yes, is it invalidated appropriately after reset? Could you try to disable the cache for test?

Regards,

Lukas

3,081 Views
ajmerijaimin
Contributor III

While I was searching for disabling cache and invalidating cache I came across a thread which informs to refer optimizations.c file. It contains the code. The project is "Example_XPC567XRKIT-PinToggleStationery-V0_7".

https://community.nxp.com/t5/MPC5xxx/MPC5777C-e200z759-DCache-Invalidation-L1CSR0-Access/m-p/664124

Below is the snipped that I'm using. This time just to test first, I commented read to test if erase+program works. It doesn't work anymore. The erase and program operations are not working now. It crashes somewhere with an MCSR reg value as 0x0008_800C.

 

 

 

static asm void turn_cache_off() {
	mfspr r3, l1csr0
	clrrwi r3, r3, 1
	msync    
	se_isync    
	mtspr l1csr0, r3
	se_isync   
	
	// invalidate cache

cfg_DCACHE:

    /*--------------------------------------------#
    # Invalidate - Set CINV                      #
    # bit in L1CSR0 Register                     #
    #--------------------------------------------*/
    e_lis   r5, 0x0000
    e_ori   r5, r5, 0x0002
    msync
    se_isync
    mtspr l1csr0,r5

    /*-------------------------------------------#
    # Mask out CINV and CABT to see if           #
    # invalidation is complete (i.e. CINV=0,     #
    # CABT=0)                                    #
    #-------------------------------------------*/
label_DCINV_check:
    /*-------------------------------------------#
    # Load Registers with Masks:                 #
    # Load CINV mask into R8                     #
    # Load CABT mask into R7                     #
    # Load CABT clear mask into R11              #
    #-------------------------------------------*/
    e_lis   r8, 0x0000
    e_ori   r8, r8, 0x0002
    e_lis   r7, 0x0000
    e_ori   r7, r7, 0x0004
    e_lis   r11, 0xFFFF
    e_or2i  r11,0xFFFB
CHECK_DCINV:

    /*-------------------------------------------#
    # Read l1csr0 register, store in r9      #
    #-------------------------------------------*/
    mfspr r9, l1csr0
    /*-------------------------------------------#
    # check for an ABORT of the cache invalidate #
    # operation                                  #
    #-------------------------------------------*/
    and.  r10, r7, r9
    se_beq   D_NO_ABORT
    /*-------------------------------------------#
    # If abort detected, clear CABT bit and      #
    # re-run invalidation                        #
    #-------------------------------------------*/
    and.  r10, r11, r9
    msync
    se_isync
    mtspr l1csr0, r10
    e_b     cfg_DCACHE

D_NO_ABORT:
    /*-------------------------------------------#
    # Check that invalidation has completed -    #
    # (CINV=0). Branch if invalidation not       #
    # complete.                                  #
    #-------------------------------------------*/
    and.  r10, r8, r9
    se_bne CHECK_DCINV

    /*-------------------------------------------#
    # Enable cache by performing a               #
    # read/modify/write of the CE bit in the     #
    # l1csr0 register                        #
    #-------------------------------------------*/
    mfspr r5, l1csr0
    e_ori  r5, r5, 0x0000
    e_ori   r5, r5, 0x0001    /* Store l1csr0 value to R5 (CE=1) */
    msync
    se_isync
    mtspr l1csr0, r5        /* Write R5 to SPR_L1CSR0 register */

    se_blrl
}

void main (void)
{    
    // code: same as before

    HW_init();
    turn_cache_off();
    //bytes_read = read_flash((uint32_t *)TARGET_ADDRESS, gReadBuffer, READ_BUFFER_SIZE);

    // code: same as before
}

 

 

 

 

Tags (2)
0 Kudos
Reply
3,031 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi,

could you please provide whole project writing 0xF8_0000 which doesn't work?

Thanks,

Lukas

0 Kudos
Reply
3,025 Views
ajmerijaimin
Contributor III

I have shared my project.

1. Disable and invalidate cache before read_flash() doesn't work.
2. But if I do so after read_flash() then it works. I don't know if this is right.

When I go ahead with option (2). The control doesn't return back after calling write_flash() in main. I see an illegal instruction exception while returning. But it works if I call program_block() instead. 

0 Kudos
Reply
3,016 Views
ajmerijaimin
Contributor III

Please find my further analysis.

Actually after disabling the cache. Nested function calls cause this exception. Not sure why. But it happens only after disabling and invalidating the data cache. If I do not disable and invalidate cache it works, otherwise causes an illegal instruction exception.

Below is the snippet without flash memory operations. It never returns after test_function() call exception occurs.

 

uint32_t test_function2()
{
    for(uint32_t i=0; i<0xFFFF; i++);
    return 0xA2A2A2A2;
}

uint32_t test_function()
{
    for(uint32_t i=0; i<0xFFFF; i++);
    return test_function2();
}

void main()
{
    HW_init();

    // disable and invalidate data cache
    turn_cache_off();

    /* on return se_blr instruction causes exception as
     * LR becomes 0 for some reason */
    test_function();
}

 

0 Kudos
Reply
2,999 Views
ajmerijaimin
Contributor III

We tried to Way Data Disable instead of disabling and invalidating cache. This solved the nested function calls issue which I described above.

This works without any exception including flash read:

static asm void disable_way()
{
	mfspr r3, l1csr0
	e_ori   r3, r3, 0x0F000000
	msync    
	se_isync    
	mtspr l1csr0, r3
	se_isync 
}

static asm void enable_way()
{
	mfspr r5, l1csr0
	e_andi   r5, r5, 0xF0FFFFFF
	msync    
	se_isync    
	mtspr l1csr0, r5
	se_isync   
}

void main (void)
{
    uint32_t offset = 0;

	HW_init();

    disable_way();
    read_block((uint32_t*)TARGET_ADDRESS, gReadBuffer, RD_BUF_SIZE);
    enable_way();

    unlock_block(TARGET_PARTITION_BIT);
    erase_block((uint32_t*)TARGET_ADDRESS, TARGET_PARTITION_BIT);

    while(counter < 0x10000)
    {
        // fill 512 bytes with sequence counter
		for (uint32_t i=0; i<WT_BUF_SIZE; i++)
		{
			gWriteBuffer[i] = counter;
			counter++;
		}

        // write 512 bytes to flash
		if ((counter % WT_BUF_SIZE) == 0)
        {
            offset += write_flash((uint32_t*)(TARGET_ADDRESS + offset), gWriteBuffer, WT_BUF_SIZE);
        }
    }
	
	while(1);
}
0 Kudos
Reply
2,988 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi,

I found out that this project forces stack to cache memory to achieve highest possible performance. That's the reason why invalidation or disabling of whole cache cause the troubles.

If I simply force the stack (R1) to normal RAM and disable the data cache, I can see it's working as expected. So, the cache is the source of issues. If you want to keep the cache enabled and keep the stack in cache, the easiest way should be to configure required flash area as cache inhibited. This can be done by MMU configuration.

https://community.nxp.com/t5/MPC5xxx-Knowledge-Base/MMU-Assist-Register-CONFIGURATOR/ta-p/1110436

Regards,

Lukas

 

3,103 Views
ajmerijaimin
Contributor III

hi @lukaszadrapa 

I'm not sure how to disable cache if it's enabled. I don't know about invalidating cache either. Could you help me with this?

From the startup code init.s file I can see that cache is enabled. I'm using the Pin Toggle example as template.

Tags (1)
0 Kudos
Reply