RT600/685: Invalidating AHB FlexSPI Cache/RX Buffers after writing to Flash

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

RT600/685: Invalidating AHB FlexSPI Cache/RX Buffers after writing to Flash

1,569 Views
sidgup
Contributor I

Hi all,

I wanted to know what is the right way to invalidate the FlexSPI cache/RX buffers on an RT600? I am using the UM11147 Rev 1.4 as reference.

Problem:

I am observing that after writing to flash when I dereference the memory mapped address to read back what was written to flash the value returned is the old value.

For example, if the memory mapped 0x8dd000c contains "test", and after disabling write protection, erasing the page, writing "dead" to it and then dereferencing 0x8dd000c still shows "test". However after rebooting and checking the address I see "dead". It also works fine if I use memcpy, but not directly dereferencing the memory mapped address.

What was attempted to fix this problem, and DID NOT work:

To fix this issue, I attempted the following:

  • Clearing AHBCR.CACHABLEEN (0x4013400c bit3)
  • Clearing AHBCR.PREFETCHEN (0x4013400c bit5)
  • Invalidating using CCR (0x40033800 bit 24,25,26,27 and 31), similar to 
    CACHE64_CleanInvalidateCache in fsl_cache.c

Temporary workaround:

The only fix worked was resetting the AHB controller (setting MCR0.SWRESET or 0x40134000 bit0), but resetting the controller each time I write to flash does not seem like the right solution.

Thanks,
Sid

Labels (1)
0 Kudos
9 Replies

1,455 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
Yes, it can be said.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,534 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
I was wondering if you can upload the demo code that can replicate the phenomenon you mentioned above.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,528 Views
sidgup
Contributor I

Hi @jeremyzhou ,

I am developing code using zephyr v2.3.0 using NXPs hal module for rt6xx. I haven't compile tested this code, but in essence this is what I am doing:

 

uint8_t *my_data_in_flash = 0x8dd0000; /* or some sector aligned start address */
uint8_t *my_data;
uint8_t *check_my_data;

/* other initialization things */

memcpy(my_data, my_data_in_flash, MY_DATA_SIZE);

/* some computation on my data */

if (flash_write_protection_set(flash_dev, false)) {
	return -EIO;
}

flash_erase(flash_dev,
			(uint32_t)my_data_in_flash - DT_INST_0_SOC_NV_FLASH_BASE_ADDRESS,
			DT_INST_0_SOC_NV_FLASH_ERASE_BLOCK_SIZE);

if (flash_write(flash_dev,
				(uint32_t)my_data_in_flash - DT_INST_0_SOC_NV_FLASH_BASE_ADDRESS,
				my_data,
				MY_DATA_SIZE)) {
	return -EIO;
}

flash_write_protection_set(flash_dev, true);

/* This does not work */

for (int i = 0; i < MY_DATA_SIZE; i++) {
	if (my_data_in_flash[i] != my_data[i]) {
		printk("Failed to write data to flash\n");
		return -EIO;
	}
}

/* This works */

flash_read(flash_dev,
			(uint32_t)my_data_in_flash - DT_INST_0_SOC_NV_FLASH_BASE_ADDRESS,
			check_my_data,
			MY_DATA_SIZE);

for (int i = 0; i < MY_DATA_SIZE; i++) {
	if (check_my_data[i] != my_data[i]) {
		printk("Failed to write data to flash\n");
		return -EIO;
	}
}

 

 

0 Kudos

1,517 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
After going through your code, firstly, it didn't dynamically allocate an area for the pointer value: my_data, next, you can try to add the below code at the beginning or declare an array in the non-cache area to replace the my_data to store the readback data.
/* Disable DCache */
SCB_DisableDCache();

Lastly, I'd like to suggest you refer to the application note to learn how to cache maintenance and data coherency
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,510 Views
sidgup
Contributor I

Hi @jeremyzhou,

Thanks for the update! Sorry if it wasn't clear but I didn't feel it was necessary to add the memory allocation steps to the sample code so I put it as a part of the:

 

/* other initialization things */

 

As for the the suggestion for the DCache, I believe the M33 on the RT600 does not have a DCache. The FlexSPI uses the RX and TX buffers as cache which are not being invalidated using NXPs hal for rt6xx which implements CACHE64_InvalidateCache() as below:

 

/*!
 * brief Invalidates the cache.
 *
 */
void CACHE64_InvalidateCache(CACHE64_CTRL_Type *base)
{
    /* Invalidate all lines in both ways and initiate the cache command. */
    base->CCR |= CACHE64_CTRL_CCR_INVW0_MASK | CACHE64_CTRL_CCR_INVW1_MASK | CACHE64_CTRL_CCR_GO_MASK;

    /* Wait until the cache command completes. */
    while (base->CCR & CACHE64_CTRL_CCR_GO_MASK)
    {
    }

    /* As a precaution clear the bits to avoid inadvertently re-running this command. */
    base->CCR &= ~(CACHE64_CTRL_CCR_INVW0_MASK | CACHE64_CTRL_CCR_INVW1_MASK);
}

 

https://github.com/zephyrproject-rtos/hal_nxp/blob/master/mcux/mcux-sdk/drivers/cache/cache64/fsl_ca...

0 Kudos

1,502 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
After checking the architecture of the CM33 core, it actually doesn't have the cache area, meanwhile, I review your question again, you use the pointer to write the string "test", and it can write successful even though the IDE's value window still illustrate the previous value, is my understanding right?
If yes, the phenomenon should be related to IDE, not the MCU itself.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

1,498 Views
sidgup
Contributor I

Hi @jeremyzhou,

No I do not use an IDE. I am printing the contents of flash onto the serial console I have running over uart.

I see different values when I dereference the values directly, i.e., *(uint8_t *)0x8dd0000 vs doing a memcpy()/flash_read() of the same address. Please take a closer look at the sample code I posted.

Thanks,
Sid

 

0 Kudos

1,466 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
In my opinion, I'd like to suggest you flexspi_nor_flash_page_program API to implement write data, further, software reset also be called in this flexspi_nor_flash_page_program API, it won't reset the PC or MCU as the API is already relocated to RAM before.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

 

0 Kudos

1,458 Views
sidgup
Contributor I

Hi @jeremyzhou,

So to conclude, the workaround that I mentioned in my original post is the final solution, and I should implement an API to do a software reset of the AHB controller each time I write to flash?

Thanks,
Sid

0 Kudos