Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:58

0001 /*
0002  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2021 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_common.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.common_arm"
0014 #endif
0015 
0016 #ifndef __GIC_PRIO_BITS
0017 #if defined(ENABLE_RAM_VECTOR_TABLE)
0018 uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
0019 {
0020 #ifdef __VECTOR_TABLE
0021 #undef __VECTOR_TABLE
0022 #endif
0023 
0024 /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
0025 #if defined(__CC_ARM) || defined(__ARMCC_VERSION)
0026     extern uint32_t Image$$VECTOR_ROM$$Base[];
0027     extern uint32_t Image$$VECTOR_RAM$$Base[];
0028     extern uint32_t Image$$RW_m_data$$Base[];
0029 
0030 #define __VECTOR_TABLE          Image$$VECTOR_ROM$$Base
0031 #define __VECTOR_RAM            Image$$VECTOR_RAM$$Base
0032 #define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
0033 #elif defined(__ICCARM__)
0034     extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
0035     extern uint32_t __VECTOR_TABLE[];
0036     extern uint32_t __VECTOR_RAM[];
0037 #elif defined(__GNUC__)
0038     extern uint32_t __VECTOR_TABLE[];
0039     extern uint32_t __VECTOR_RAM[];
0040     extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
0041     uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
0042 #endif /* defined(__CC_ARM) || defined(__ARMCC_VERSION) */
0043     uint32_t n;
0044     uint32_t ret;
0045     uint32_t irqMaskValue;
0046 
0047     irqMaskValue = DisableGlobalIRQ();
0048     if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
0049     {
0050         /* Copy the vector table from ROM to RAM */
0051         for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
0052         {
0053             __VECTOR_RAM[n] = __VECTOR_TABLE[n];
0054         }
0055         /* Point the VTOR to the position of vector table */
0056         SCB->VTOR = (uint32_t)__VECTOR_RAM;
0057     }
0058 
0059     ret = __VECTOR_RAM[(int32_t)irq + 16];
0060     /* make sure the __VECTOR_RAM is noncachable */
0061     __VECTOR_RAM[(int32_t)irq + 16] = irqHandler;
0062 
0063     EnableGlobalIRQ(irqMaskValue);
0064 
0065     return ret;
0066 }
0067 #endif /* ENABLE_RAM_VECTOR_TABLE. */
0068 #endif /* __GIC_PRIO_BITS. */
0069 
0070 #if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
0071 
0072 /*
0073  * When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
0074  * powerlib should be used instead of these functions.
0075  */
0076 #if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
0077 
0078 /*
0079  * When the SYSCON STARTER registers are discontinuous, these functions are
0080  * implemented in fsl_power.c.
0081  */
0082 #if !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS)
0083 
0084 void EnableDeepSleepIRQ(IRQn_Type interrupt)
0085 {
0086     uint32_t intNumber = (uint32_t)interrupt;
0087 
0088     uint32_t index = 0;
0089 
0090     while (intNumber >= 32u)
0091     {
0092         index++;
0093         intNumber -= 32u;
0094     }
0095 
0096     SYSCON->STARTERSET[index] = 1UL << intNumber;
0097     (void)EnableIRQ(interrupt); /* also enable interrupt at NVIC */
0098 }
0099 
0100 void DisableDeepSleepIRQ(IRQn_Type interrupt)
0101 {
0102     uint32_t intNumber = (uint32_t)interrupt;
0103 
0104     (void)DisableIRQ(interrupt); /* also disable interrupt at NVIC */
0105     uint32_t index = 0;
0106 
0107     while (intNumber >= 32u)
0108     {
0109         index++;
0110         intNumber -= 32u;
0111     }
0112 
0113     SYSCON->STARTERCLR[index] = 1UL << intNumber;
0114 }
0115 #endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
0116 #endif /* FSL_FEATURE_POWERLIB_EXTEND */
0117 #endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
0118 
0119 #if defined(DWT)
0120 /* Use WDT. */
0121 void MSDK_EnableCpuCycleCounter(void)
0122 {
0123     /* Make sure the DWT trace fucntion is enabled. */
0124     if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR))
0125     {
0126         CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
0127     }
0128 
0129     /* CYCCNT not supported on this device. */
0130     assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk));
0131 
0132     /* Read CYCCNT directly if CYCCENT has already been enabled, otherwise enable CYCCENT first. */
0133     if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL))
0134     {
0135         DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
0136     }
0137 }
0138 
0139 uint32_t MSDK_GetCpuCycleCount(void)
0140 {
0141     return DWT->CYCCNT;
0142 }
0143 #endif /* defined(DWT) */
0144 
0145 #if !(defined(SDK_DELAY_USE_DWT) && defined(DWT))
0146 /* Use software loop. */
0147 #if defined(__CC_ARM) /* This macro is arm v5 specific */
0148 /* clang-format off */
0149 __ASM static void DelayLoop(uint32_t count)
0150 {
0151 loop
0152     SUBS R0, R0, #1
0153     CMP  R0, #0
0154     BNE  loop
0155     BX   LR
0156 }
0157 #elif defined(__ARM_ARCH_8A__) /* This macro is ARMv8-A specific */
0158 static void DelayLoop(uint32_t count)
0159 {
0160     __ASM volatile("    MOV    X0, %0" : : "r"(count));
0161     __ASM volatile(
0162         "loop:                          \n"
0163         "    SUB    X0, X0, #1          \n"
0164         "    CMP    X0, #0              \n"
0165 
0166         "    BNE    loop                \n"
0167         :
0168         :
0169         : "r0");
0170 }
0171 /* clang-format on */
0172 #elif defined(__ARMCC_VERSION) || defined(__ICCARM__) || defined(__GNUC__)
0173 /* Cortex-M0 has a smaller instruction set, SUBS isn't supported in thumb-16 mode reported from __GNUC__ compiler,
0174  * use SUB and CMP here for compatibility */
0175 static void DelayLoop(uint32_t count)
0176 {
0177     __ASM volatile("    MOV    R0, %0" : : "r"(count));
0178     __ASM volatile(
0179         "loop:                          \n"
0180 #if defined(__GNUC__) && !defined(__ARMCC_VERSION)
0181         "    SUB    R0, R0, #1          \n"
0182 #else
0183         "    SUBS   R0, R0, #1          \n"
0184 #endif
0185         "    CMP    R0, #0              \n"
0186 
0187         "    BNE    loop                \n"
0188         :
0189         :
0190         : "r0");
0191 }
0192 #endif /* defined(__CC_ARM) */
0193 #endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
0194 
0195 /*!
0196  * @brief Delay at least for some time.
0197  *  Please note that, if not uses DWT, this API will use while loop for delay, different run-time environments have
0198  *  effect on the delay time. If precise delay is needed, please enable DWT delay. The two parmeters delayTime_us and
0199  *  coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delayTime_us only supports
0200  *  up to 4294967 in current code. If long time delay is needed, please implement a new delay function.
0201  *
0202  * @param delayTime_us  Delay time in unit of microsecond.
0203  * @param coreClock_Hz  Core clock frequency with Hz.
0204  */
0205 void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz)
0206 {
0207     uint64_t count;
0208 
0209     if (delayTime_us > 0U)
0210     {
0211         count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
0212 
0213         assert(count <= UINT32_MAX);
0214 
0215 #if defined(SDK_DELAY_USE_DWT) && defined(DWT) /* Use DWT for better accuracy */
0216 
0217         MSDK_EnableCpuCycleCounter();
0218         /* Calculate the count ticks. */
0219         count += MSDK_GetCpuCycleCount();
0220 
0221         if (count > UINT32_MAX)
0222         {
0223             count -= UINT32_MAX;
0224             /* Wait for cyccnt overflow. */
0225             while (count < MSDK_GetCpuCycleCount())
0226             {
0227             }
0228         }
0229 
0230         /* Wait for cyccnt reach count value. */
0231         while (count > MSDK_GetCpuCycleCount())
0232         {
0233         }
0234 #else
0235         /* Divide value may be different in various environment to ensure delay is precise.
0236          * Every loop count includes three instructions, due to Cortex-M7 sometimes executes
0237          * two instructions in one period, through test here set divide 1.5. Other M cores use
0238          * divide 4. By the way, divide 1.5 or 4 could let the count lose precision, but it does
0239          * not matter because other instructions outside while loop is enough to fill the time.
0240          */
0241 #if (__CORTEX_M == 7)
0242         count = count / 3U * 2U;
0243 #else
0244         count = count / 4U;
0245 #endif
0246         DelayLoop((uint32_t)count);
0247 #endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
0248     }
0249 }