mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	 38d54b4b62
			
		
	
	38d54b4b62
	
	
	
		
			
			Need to ensure that the cacheline being written back will not be accessed during the write back process.
		
			
				
	
	
		
			133 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  */
 | |
| 
 | |
| #include "sdkconfig.h"
 | |
| #include "esp_bit_defs.h"
 | |
| #include "soc/extmem_reg.h"
 | |
| 
 | |
| /**
 | |
|   * @brief Write back the cache items of DCache, enable cache freeze during writeback.
 | |
|   *        Operation will be done CACHE_LINE_SIZE aligned.
 | |
|   *        If the region is not in DCache addr room, nothing will be done.
 | |
|   *        Please do not call this function in your SDK application.
 | |
|   * @param  uint32_t addr: start address to write back
 | |
|   * @param  uint32_t items: cache lines to invalidate, items * cache_line_size should
 | |
|   *         not exceed the bus address size(4MB)
 | |
|   *
 | |
|   * void cache_writeback_items_freeze(uint32_t addr, uint32_t items)
 | |
| */
 | |
| 
 | |
| /*******************************************************************************
 | |
| 
 | |
| This function is a cache write-back function that works around the following
 | |
| hardware errata on the ESP32-S3:
 | |
| 
 | |
| - Core X manually triggers (via the EXTMEM_DCACHE_SYNC_CTRL_REG register) the
 | |
| write-back of one or more cache lines.
 | |
| - While the write-back is in progress, there are two scenarios that may cause
 | |
| cache hit error.
 | |
|     - Core X enters the interrupt handler and access the same cache line
 | |
|       being written back.
 | |
|     - Core Y access the same cache line being written back.
 | |
| 
 | |
| To workaround this errata, the following steps must be taken when manually
 | |
| triggering a cache write-back:
 | |
| 
 | |
| - Core X must disable interrupts so that it cannot be preempted
 | |
| - Core X must freeze the cache (via the EXTMEM_DCACHE_FREEZE_REG register) to
 | |
| prevent Core Y from accessing the same cache lines that are about to be written
 | |
| back.
 | |
| - Core X now triggers the cache write-back. During the write-back...
 | |
|     - If Core Y attempts the access any address in the cache region, Core Y will
 | |
|     busy wait until the cache is unfrozen.
 | |
|     - Core X must ensure that it does not access any address in the cache region,
 | |
|     otherwise Core X will busy wait thus causing a deadlock.
 | |
| - After the write-back is complete, Core X unfreezes the cache, and reenables
 | |
| interrupts.
 | |
| 
 | |
| Notes:
 | |
| 
 | |
| - Please do not modify this function, it must strictly follow the current execution
 | |
| sequence, otherwise it may cause unexpected errors.
 | |
| - This function is written in assmebly to ensure that the function itself never
 | |
| accesses any cache address while the cache is frozen. Unexpected cache access
 | |
| could occur if...
 | |
|     - the function triggers an window overflow onto a stack placed in PSRAM.
 | |
|     Thus, we only use two window panes (a0 to a8) in this function and trigger
 | |
|     all window overflows before freezing the cache.
 | |
|     - the function accesses literals/read-only variables placed in Flash.
 | |
| 
 | |
| *******************************************************************************/
 | |
| 
 | |
|     .align  4
 | |
|     /*
 | |
|     Create dedicated literal pool for this function. Mostly used to store out
 | |
|     of range movi transformations.
 | |
|     */
 | |
|     .literal_position
 | |
|     .global cache_writeback_items_freeze
 | |
|     .type   cache_writeback_items_freeze, @function
 | |
| cache_writeback_items_freeze:
 | |
|     entry   sp, 32
 | |
| 
 | |
|     /* REG_WRITE(EXTMEM_DCACHE_SYNC_ADDR_REG, addr); */
 | |
|     movi a4, EXTMEM_DCACHE_SYNC_ADDR_REG
 | |
|     s32i a2, a4, 0
 | |
|     /* REG_WRITE(EXTMEM_DCACHE_SYNC_SIZE_REG, items); */
 | |
|     movi a4, EXTMEM_DCACHE_SYNC_SIZE_REG
 | |
|     s32i a3, a4, 0
 | |
|     memw    /* About to freeze the cache. Ensure all previous memory R/W are completed */
 | |
| 
 | |
|     movi a2, EXTMEM_DCACHE_FREEZE_REG
 | |
|     movi a3, EXTMEM_DCACHE_SYNC_CTRL_REG
 | |
| 
 | |
|     /*
 | |
|     REG_CLR_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_MODE);
 | |
|     REG_SET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_ENA);
 | |
|     */
 | |
|     l32i a4, a2, 0  /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
 | |
|     movi a5, ~(EXTMEM_DCACHE_FREEZE_MODE_M)
 | |
|     and a4, a4, a5
 | |
|     movi a5, EXTMEM_DCACHE_FREEZE_ENA_M
 | |
|     or a4, a4, a5
 | |
|     s32i a4, a2, 0  /* *(EXTMEM_DCACHE_FREEZE_REG) = a4 */
 | |
| 
 | |
|     /* while (!REG_GET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_DONE)); */
 | |
|     movi a5, EXTMEM_DCACHE_FREEZE_DONE_M
 | |
| _wait_freeze_done:
 | |
|     l32i a4, a2, 0  /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
 | |
|     memw
 | |
|     bnone a4, a5, _wait_freeze_done
 | |
| 
 | |
|     /* REG_SET_BIT(EXTMEM_DCACHE_SYNC_CTRL_REG, EXTMEM_DCACHE_WRITEBACK_ENA); */
 | |
|     l32i a4, a3, 0  /* a4 = *(EXTMEM_DCACHE_SYNC_CTRL_REG) */
 | |
|     movi a5, EXTMEM_DCACHE_WRITEBACK_ENA_M
 | |
|     or a4, a4, a5
 | |
|     s32i a4, a3, 0  /* *(EXTMEM_DCACHE_SYNC_CTRL_REG) = a4 */
 | |
| 
 | |
|     /* while(!REG_GET_BIT(EXTMEM_DCACHE_SYNC_CTRL_REG, EXTMEM_DCACHE_SYNC_DONE)); */
 | |
|     movi a5, EXTMEM_DCACHE_SYNC_DONE_M
 | |
| _wait_writeback_done:
 | |
|     l32i a4, a3, 0  /* a4 = *(EXTMEM_DCACHE_SYNC_CTRL_REG) */
 | |
|     memw
 | |
|     bnone a4, a5, _wait_writeback_done
 | |
| 
 | |
|     /* REG_CLR_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_ENA); */
 | |
|     l32i a4, a2, 0  /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
 | |
|     movi a5, ~(EXTMEM_DCACHE_FREEZE_ENA_M)
 | |
|     and a4, a4, a5
 | |
|     s32i a4, a2, 0  /* *(EXTMEM_DCACHE_FREEZE_REG) = a4 */
 | |
| 
 | |
|     /* while (REG_GET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_DONE)); */
 | |
|     movi a5, EXTMEM_DCACHE_FREEZE_DONE_M
 | |
| _wait_unfreeze_done:
 | |
|     l32i a4, a2, 0  /* a4 = *(EXTMEM_DCACHE_FREEZE_REG) */
 | |
|     memw
 | |
|     bany a4, a5, _wait_unfreeze_done
 | |
| 
 | |
|     retw
 | |
|     .size   cache_writeback_items_freeze, . - cache_writeback_items_freeze
 |