Always use the cmsis_6 version for DWT_LSR_Present_Msk and DWT_LSR_Access_Msk, the old ones are not going to be available anymore when Cortex-M is selected.. Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
		
			
				
	
	
		
			183 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021 Nordic Semiconductor ASA
 | |
|  * Copyright (c) 2020 STMicroelectronics
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @file
 | |
|  * @brief DWT utility functions for Cortex-M CPUs
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifndef ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_DWT_H_
 | |
| #define ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_DWT_H_
 | |
| 
 | |
| #ifdef _ASMLANGUAGE
 | |
| 
 | |
| /* nothing */
 | |
| 
 | |
| #else
 | |
| 
 | |
| #include <cmsis_core.h>
 | |
| #include <zephyr/sys/__assert.h>
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| #if defined(CONFIG_CORTEX_M_DWT)
 | |
| 
 | |
| /* Define DWT LSR masks which are currently not defined by the CMSIS V5.1.2.
 | |
|  * (LSR register is defined but not its bitfields).
 | |
|  * Reuse ITM LSR mask as it is the same offset than DWT LSR one.
 | |
|  * TODO: update these to use only CMSIS_6 when all of zephyr and modules have
 | |
|  * update to CMSIS_6.
 | |
|  */
 | |
| #if !defined DWT_LSR_Present_Msk
 | |
| #define DWT_LSR_Present_Msk ITM_LSR_PRESENT_Msk
 | |
| #endif
 | |
| 
 | |
| #if !defined DWT_LSR_Access_Msk
 | |
| #define DWT_LSR_Access_Msk ITM_LSR_ACCESS_Msk
 | |
| #endif
 | |
| 
 | |
| static inline void dwt_access(bool ena)
 | |
| {
 | |
| #if defined(CONFIG_CPU_CORTEX_M7)
 | |
| 	/*
 | |
| 	 * In case of Cortex M7, we need to check the optional presence of
 | |
| 	 * Lock Access Register (LAR) which is indicated in Lock Status
 | |
| 	 * Register (LSR). When present, a special access token must be written
 | |
| 	 * to unlock DWT registers.
 | |
| 	 */
 | |
| 	uint32_t lsr = DWT->LSR;
 | |
| 
 | |
| 	if ((lsr & DWT_LSR_Present_Msk) != 0) {
 | |
| 		if (ena) {
 | |
| 			if ((lsr & DWT_LSR_Access_Msk) != 0) {
 | |
| 				/* Access is locked. unlock it */
 | |
| 				DWT->LAR = 0xC5ACCE55;
 | |
| 			}
 | |
| 		} else {
 | |
| 			if ((lsr & DWT_LSR_Access_Msk) == 0) {
 | |
| 				/* Access is unlocked. Lock it */
 | |
| 				DWT->LAR = 0;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| #else  /* CONFIG_CPU_CORTEX_M7 */
 | |
| 	ARG_UNUSED(ena);
 | |
| #endif /* CONFIG_CPU_CORTEX_M7 */
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Enable DWT
 | |
|  *
 | |
|  * This routine enables the DWT unit.
 | |
|  *
 | |
|  * @return 0
 | |
|  */
 | |
| static inline int z_arm_dwt_init(void)
 | |
| {
 | |
| 	/* Enable tracing */
 | |
| 	CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
 | |
| 
 | |
| 	/* Unlock DWT access if any */
 | |
| 	dwt_access(true);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Initialize and Enable the DWT cycle counter
 | |
|  *
 | |
|  * This routine enables the cycle counter and initializes its value to zero.
 | |
|  *
 | |
|  * @return 0
 | |
|  */
 | |
| static inline int z_arm_dwt_init_cycle_counter(void)
 | |
| {
 | |
| 	/* Clear and enable the cycle counter */
 | |
| 	DWT->CYCCNT = 0;
 | |
| 	DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
 | |
| 
 | |
| 	/* Assert that the cycle counter is indeed implemented.
 | |
| 	 * The field is called NOCYCCNT. So 1 means there is no cycle counter.
 | |
| 	 */
 | |
| 	__ASSERT((DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk) == 0, "DWT implements no cycle counter. "
 | |
| 							   "Cannot be used for cycle counting\n");
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Return the current value of the cycle counter
 | |
|  *
 | |
|  * This routine returns the current value of the DWT Cycle Counter (DWT.CYCCNT)
 | |
|  *
 | |
|  * @return the cycle counter value
 | |
|  */
 | |
| static inline uint32_t z_arm_dwt_get_cycles(void)
 | |
| {
 | |
| 	return DWT->CYCCNT;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Reset and start the DWT cycle counter
 | |
|  *
 | |
|  * This routine starts the cycle counter and resets its value to zero.
 | |
|  */
 | |
| static inline void z_arm_dwt_cycle_count_start(void)
 | |
| {
 | |
| 	DWT->CYCCNT = 0;
 | |
| 	DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Enable the debug monitor handler
 | |
|  *
 | |
|  * This routine enables the DebugMonitor handler to service
 | |
|  * data watchpoint events coming from DWT. The routine sets
 | |
|  * the DebugMonitor exception priority to highest possible.
 | |
|  */
 | |
| static inline void z_arm_dwt_enable_debug_monitor(void)
 | |
| {
 | |
| 	/*
 | |
| 	 * In case the CPU is left in Debug mode, the behavior will be
 | |
| 	 * unpredictable if the DebugMonitor exception is triggered. We
 | |
| 	 * assert that the CPU is in normal mode.
 | |
| 	 */
 | |
| 	__ASSERT((CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0,
 | |
| 		 "Cannot enable DBM when CPU is in Debug mode\n");
 | |
| 
 | |
| #if defined(CONFIG_ARMV8_M_SE) && !defined(CONFIG_ARM_NONSECURE_FIRMWARE)
 | |
| 	/*
 | |
| 	 * By design, the DebugMonitor exception is only employed
 | |
| 	 * for null-pointer dereferencing detection, and enabling
 | |
| 	 * that feature is not supported in Non-Secure builds. So
 | |
| 	 * when enabling the DebugMonitor exception, assert that
 | |
| 	 * it is not targeting the Non Secure domain.
 | |
| 	 */
 | |
| 	__ASSERT((CoreDebug->DEMCR & DCB_DEMCR_SDME_Msk) != 0, "DebugMonitor targets Non-Secure\n");
 | |
| #endif
 | |
| 
 | |
| 	/* The DebugMonitor handler priority is set already
 | |
| 	 * to the highest value (_EXC_FAULT_PRIO) during
 | |
| 	 * system initialization.
 | |
| 	 */
 | |
| 
 | |
| 	/* Enable debug monitor exception triggered on debug events */
 | |
| 	CoreDebug->DEMCR |= CoreDebug_DEMCR_MON_EN_Msk;
 | |
| }
 | |
| 
 | |
| #endif /* CONFIG_CORTEX_M_DWT */
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #endif /* _ASMLANGUAGE */
 | |
| 
 | |
| #endif /* ZEPHYR_ARCH_ARM_INCLUDE_AARCH32_CORTEX_M_DWT_H_ */
 |