MPC5674 Data written to flash not going to correct address

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

MPC5674 Data written to flash not going to correct address

1,191 Views
Bloodhound
Contributor I

Hi All,

 

I have a strange issue, using an MPC5674 in VLE mode, when I write data to the 4Mb internal flash (not external flash) where I am intending it to be written is not where it is getting written.

 

Actual Address in red

000B8000 000B8004 000B8008 000B800C 000B8010 000B8014 000B8018 000B801C << Actual address in Flash

000B8010 000B8014 000B8008 000B800C FFFFFFFF FFFFFFFF 000B8018 000B801C << Data should have been written to this address

 

So what I set up was I just had a loop that incremented the write to address by 8 in total, wrote 2 x 4 bytes as per the rules of this flash and this is what I've ended up with.

Essentially all it is doing to writing the address value to the actual address in flash I am writing to. Eg, load address 0xB8000 and write that value to 0xB8000, then load address 0xB8004 and write that value to 0xB8004 and so on.

The first one, I was writing to address 0xB8000, but what was actually written was 0xB8010 meaning that data should have been written to 0xB8010, but it ended up at address 0xB8000 in the flash.

Then on the 0xB8010 and 0xB8014 in the flash there was nothing written at all (it should have contained the values 0xB8010 and 0xB8014) that is a mystery too.

 

This was the test code I ran (if it makes more sense than my description) - r8 was preloaded with 0xB8000.

 

e_li  r11,0
add   r11,r11,r8             ; Get address to write to
e_stw r11,0(r8)              ; Write address value to flash
e_addir8,r8,4                ; Increment write address for next pass
e_li  r11,0
add   r11,r11,r8             ; Get address to write to
e_stw r11,0(r8)              ; Write address value to flash
e_addir8,r8,4                ; Increment write address for next pass

 

This problem only happens on addresses above 0xA0000, eg if I write to address 0x90010 then the data is written to 0x90010, above 0xA0000 if I write to 0xA0010 the data ends up at 0xA0000.

Can anyone please give me a hint as to why the address I am telling the CPU to write to is not where the data ends up once above 0xA0000.

 

Thanks.

Labels (1)
0 Kudos
6 Replies

922 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi,

I can't understand from your description what's going on. I would need to see whole function that was used to program the flash. I found this piece of working code in my repository for MPC5674F:

/* unlock M0 in flash array B */

    FLASH_B.LMLR.R = 0xA1A11111;

    FLASH_B.LMLR.R = 0x001203FF;    

  FLASH_B.SLMLR.R = 0xC3C33333;

  FLASH_B.SLMLR.R = 0x001203FF;

 

 

      /* erase M0 */

  FLASH_B.MCR.B.ERS = 1;

  FLASH_B.LMSR.R = 0x00010000;    /* select M0 only */

  *(unsigned int *)0x000C0000 = 0xFFFFFFFF;    /* interlock write */

 

  FLASH_B.MCR.B.EHV = 1;    /* start erase */

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.ERS = 0;

 

  /* program some data */

  FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0000 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C0004 = 0xBBBBBBBB;    /* interlock write */

 

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

 

 

  FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0008 = 0xCCCCCCCC;    /* interlock write */

  *(unsigned int *)0x000C000C = 0xDDDDDDDD;    /* interlock write */

 

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

 

 

  FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0010 = 0xEEEEEEEE;    /* interlock write */

  *(unsigned int *)0x000C0014 = 0x11111111;    /* interlock write */

 

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

0 Kudos

922 Views
Bloodhound
Contributor I

Thanks for the response Lukas, sorry for the explanation being a bit confusing, I'll try again.

Writing to the flash is no problem, I have that working just like you did above with the interlock writes, setting the EHV bit etc.

My problem is once I start to write data above the address 0xA0000 things are going bad.

Lets assume I have a RAM buffer that contains the 32 bit values 0, 1, 2 , 4, 5, 6, 7, 8 that I want to write to the Flash.

If I write that buffers contents to Flash address 0x80000 the data is written to the flash memory like this (yes this works).

0x80000 = 00000001

0x80004 = 00000002

0x80008 = 00000003

0x8000C = 00000004

0x80010 = 00000005

0x80014 = 00000006

0x80018 = 00000007

0x8001C = 00000008

But once I start to write to any address above 0xA0000 then the buffers data is not getting written to the flash in the correct order

0xA0000 = 00000005

0xA0004 = 00000006

0xA0008 = 00000003

0xA000C = 00000004

0xA0010 = FFFFFFFF (nothing written)

0xA0014 = FFFFFFFF (nothing written)

0xA0018 = 00000007

0xA001C = 00000008

So relating that back to your example, here is what would be happening for me when I read back what was actually written to the Flash.

Your System....

*(unsigned int *)0x000C0000 = 0xAAAAAAAA;/* interlock write */
*(unsigned int *)0x000C0004 = 0xBBBBBBBB;/* interlock write */
*(unsigned int *)0x000C0008 = 0xCCCCCCCC;/* interlock write */
*(unsigned int *)0x000C000C = 0xDDDDDDDD;/* interlock write */
*(unsigned int *)0x000C0010 = 0xEEEEEEEE;/* interlock write */
*(unsigned int *)0x000C0014 = 0x11111111;

/* interlock write */

My system....

*(unsigned int *)0x000C0000 = 0xEEEEEEEE;/* interlock write */
*(unsigned int *)0x000C0004 = 0x11111111;/* interlock write */
*(unsigned int *)0x000C0008 = 0xCCCCCCCC;/* interlock write */
*(unsigned int *)0x000C000C = 0xDDDDDDDD;/* interlock write */
*(unsigned int *)0x000C0010 = 0xFFFFFFFF;/* interlock write */
*(unsigned int *)0x000C0014 = 0xFFFFFFFF;/* interlock write */

So the 0xEEEEEEEE you are writing to 0x000C0010 on my system ends up getting written to 0x000C0000 even though I am telling the CPU to write 0xEEEEEEEE to 0x000C0010.

My routine is very basic, just read from the RAM buffer and write back to Flash, looping until done...obviously I'm not showing all the interlock code as that is working because data is getting written.

; r8 = Address to write to in Flash

; r11 & r16 used to get data from buffer and write to flash

; r31 = RAM Buffer to get data from

; e_lwz   r11,0(r31)   ; Get data from Write buffer

; e_lwz   r16,4(r31)   ; Get data from Write buffer + 4

; e_stw   r11,0(r8)    ; Write data to flash

; e_stw   r16,4(r8)    ; Write data to flash + 4

Regards.

0 Kudos

922 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Copied from RM:

"The user can program the values in any or all of four words within a page in a single program sequence."

That means you can't program more than four words at once. You have to start next programming sequence.

  FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0000 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C0004 = 0xBBBBBBBB;    /* interlock write */

  *(unsigned int *)0x000C0008 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C000C = 0xBBBBBBBB;    /* interlock write */

  //no more data can be written!!! 

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

If you need to program next data, repeat the sequence above like this:

  FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0010 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C0014 = 0xBBBBBBBB;    /* interlock write */

  *(unsigned int *)0x000C0018 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C001C = 0xBBBBBBBB;    /* interlock write */

  //no more data can be written!!! 

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

0 Kudos

922 Views
Bloodhound
Contributor I

Yes I understand that, I am in fact only ever writing 64 bits at a time. I just had your example laid out like that to help explain what is going on with the data not being written to the target address.

So I am actually doing this (note I am programming in VLE assembler, not C, but that is ok I can follow your code fine). Note all this is in a loop that writes 64bits at a time, if more data is needed to be written then it will loop back with the address of the buffer and write to flash incremented by 8.

FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0000 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C0004 = 0xBBBBBBBB;    /* interlock write */

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0008 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C000C = 0xBBBBBBBB;    /* interlock write */

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

   FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0010 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C0014 = 0xBBBBBBBB;    /* interlock write */

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

   FLASH_B.MCR.B.PGM = 1;

  *(unsigned int *)0x000C0018 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C001C = 0xBBBBBBBB;    /* interlock write */

  FLASH_B.MCR.B.EHV = 1;   

  while(FLASH_B.MCR.B.DONE == 0){};    /* wait for done */

  FLASH_B.MCR.B.EHV = 0;

  FLASH_B.MCR.B.PGM = 0;

But this is my problem, when I do this....

  *(unsigned int *)0x000C0010 = 0xAAAAAAAA;    /* interlock write */

  *(unsigned int *)0x000C0014 = 0xBBBBBBBB;    /* interlock write */

The 0xAAAAAAAA is getting written to 0x000C0000, not 0x000C0010

The 0xBBBBBBBB is getting written to 0x000C0004, not 0x000C0014

But this only happens when the address is above 0xA0000, below that the data is going to the correct address.

I am absolutely sure the 'write to' pointer is at the write address, it seems the CPU (or MMU) is adjusting the address to where it finally gets written.

Regards,

0 Kudos

922 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Do you have more MCUs? Are you facing the problem on all of them? Or is it related to one device only? I'm still not sure if it is related to HW or SW.

The only thing that comes into my mind is:

http://www.freescale.com/files/32bit/doc/app_note/AN4521.pdf

Take a look at chapter 4.2.

Mentioned SSD flash drivers can be downloaded here:

http://www.freescale.com/lgfiles/Qorivva/MPC5674F_C90FL_SSD_DRV.exe

0 Kudos

922 Views
Bloodhound
Contributor I

The devices are fine, but I will have a close look at the SSD drivers you linked to, thanks.

0 Kudos