/* ################################################################### ** This component module is generated by Processor Expert. Do not modify it. ** Filename : McuWait.h ** Project : FRDM-K64F_Generator ** Processor : MK64FN1M0VLL12 ** Component : Wait ** Version : Component 01.091, Driver 01.00, CPU db: 3.00.000 ** Compiler : GNU C Compiler ** Date/Time : 2021-11-25, 06:25, # CodeGen: 749 ** Abstract : ** Implements busy waiting routines. ** Settings : ** Component name : McuWait ** Manual Clock Values : Disabled ** Delay100usFunction : Delay100US ** RTOS : Enabled ** RTOS : McuRTOS ** Watchdog : Disabled ** Contents : ** Wait10Cycles - void McuWait_Wait10Cycles(void); ** Wait100Cycles - void McuWait_Wait100Cycles(void); ** WaitCycles - void McuWait_WaitCycles(uint32_t cycles); ** WaitLongCycles - void McuWait_WaitLongCycles(uint32_t cycles); ** Waitms - void McuWait_Waitms(uint32_t ms); ** Waitus - void McuWait_Waitus(uint32_t us); ** Waitns - void McuWait_Waitns(uint32_t ns); ** WaitOSms - void McuWait_WaitOSms(void); ** Init - void McuWait_Init(void); ** Deinit - void McuWait_Deinit(void); ** ** * Copyright (c) 2013-2021, Erich Styger ** * Web: https://mcuoneclipse.com ** * SourceForge: https://sourceforge.net/projects/mcuoneclipse ** * Git: https://github.com/ErichStyger/McuOnEclipse_PEx ** * All rights reserved. ** * ** * Redistribution and use in source and binary forms, with or without modification, ** * are permitted provided that the following conditions are met: ** * ** * - Redistributions of source code must retain the above copyright notice, this list ** * of conditions and the following disclaimer. ** * ** * - Redistributions in binary form must reproduce the above copyright notice, this ** * list of conditions and the following disclaimer in the documentation and/or ** * other materials provided with the distribution. ** * ** * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ** * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ** * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ** * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ###################################################################*/ /*! ** @file McuWait.h ** @version 01.00 ** @brief ** Implements busy waiting routines. */ /*! ** @addtogroup McuWait_module McuWait module documentation ** @{ */ /* MODULE McuWait. */ #include "McuWait.h" /* ** =================================================================== ** Method : Wait10Cycles (component Wait) ** ** Description : ** Wait for 10 CPU cycles. ** Parameters : None ** Returns : Nothing ** =================================================================== */ #ifdef __GNUC__ #if McuLib_CONFIG_CPU_IS_RISC_V || McuLib_CONFIG_CPU_IS_ESP32 /* naked is ignored for RISC-V or ESP32 gcc */ #ifdef __cplusplus /* gcc 4.7.3 in C++ mode does not like no_instrument_function: error: can't set 'no_instrument_function' attribute after definition */ #else __attribute__((no_instrument_function)) #endif #else #ifdef __cplusplus /* gcc 4.7.3 in C++ mode does not like no_instrument_function: error: can't set 'no_instrument_function' attribute after definition */ __attribute__((naked)) #else __attribute__((naked, no_instrument_function)) #endif #endif #endif void McuWait_Wait10Cycles(void) { /* This function will wait 10 CPU cycles (including call overhead). */ /*lint -save -e522 function lacks side effect. */ #if McuLib_CONFIG_CPU_IS_ARM_CORTEX_M /* NOTE: Cortex-M0 and M4 have 1 cycle for a NOP */ #if McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_GNU __asm ( /* bl Wait10Cycles() to here: [4] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "bx lr \n\t" /* [3] */ ); #elif McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_IAR /* bl Wai10Cycles() to here: [4] */ __asm("nop"); /* [1] */ __asm("nop"); /* [1] */ __asm("nop"); /* [1] */ __asm("bx lr"); /* [3] */ #elif McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_KEIL __asm { nop /* [1] */ nop /* [1] */ nop /* [1] */ /*bx lr*/ /* [3] */ } #else __asm { nop /* [1] */ nop /* [1] */ nop /* [1] */ bx lr /* [3] */ } #endif #elif McuLib_CONFIG_CPU_IS_RISC_V __asm ( /* assuming [4] for overhead */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ ); #endif /*lint -restore */ } /* ** =================================================================== ** Method : Wait100Cycles (component Wait) ** ** Description : ** Wait for 100 CPU cycles. ** Parameters : None ** Returns : Nothing ** =================================================================== */ #if McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_IAR /* Implemented in assembly file, as IAR does not support labels in HLI */ #else #ifdef __GNUC__ #if McuLib_CONFIG_CPU_IS_RISC_V || McuLib_CONFIG_CPU_IS_ESP32 /* naked is ignored for RISC-V or ESP32 gcc */ #ifdef __cplusplus /* gcc 4.7.3 in C++ mode does not like no_instrument_function: error: can't set 'no_instrument_function' attribute after definition */ #else __attribute__((no_instrument_function)) #endif #else #ifdef __cplusplus /* gcc 4.7.3 in C++ mode does not like no_instrument_function: error: can't set 'no_instrument_function' attribute after definition */ __attribute__((naked)) #else __attribute__((naked, no_instrument_function)) #endif #endif #endif void McuWait_Wait100Cycles(void) { /* This function will spend 100 CPU cycles (including call overhead). */ /*lint -save -e522 function lacks side effect. */ #if McuLib_CONFIG_CPU_IS_ARM_CORTEX_M #if McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_GNU __asm ( /* bl to here: [4] */ "push {r0} \n\t" /* [2] */ "movs r0, #0 \n\t" /* [1] */ "loopWait100Cycles: \n\t" "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "add r0,#1 \n\t" /* [1] */ "cmp r0,#9 \n\t" /* [1] */ "bls loopWait100Cycles \n\t" /* [3] taken, [1] not taken */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "nop \n\t" /* [1] */ "pop {r0} \n\t" /* [2] */ "bx lr \n\t" /* [3] */ ); #elif McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_IAR /* need to implement in assembly, as IAR does not support labels in HLI */ #elif McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_KEIL /* bl to here: [4] */ movs r0, #0 /* [1] */ loop nop /* [1] */ nop /* [1] */ nop /* [1] */ nop /* [1] */ nop /* [1] */ adds r0,r0,#1 /* [1] */ cmp r0,#9 /* [1] */ bls loop /* [3] taken, [1] not taken */ nop /* [1] */ bx lr /* [3] */ #else __asm { /* bl Wai10Cycles() to here: [4] */ movs r0, #0 /* [1] */ loop: nop /* [1] */ nop /* [1] */ nop /* [1] */ nop /* [1] */ nop /* [1] */ add r0,#1 /* [1] */ cmp r0,#9 /* [1] */ bls loop /* [3] taken, [1] not taken */ nop /* [1] */ bx lr /* [3] */ } #endif #elif McuLib_CONFIG_CPU_IS_RISC_V __asm ( /* assuming [10] for overhead */ " li a5,20 \n\t" "LoopWait100Cycles: \n\t" " addi a5,a5,-1 \n\t" " bgtz a5, LoopWait100Cycles \n\t" ); #endif /*lint -restore */ } #endif /* McuLib_CONFIG_COMPILER==McuLib_CONFIG_COMPILER_IAR */ /* ** =================================================================== ** Method : WaitCycles (component Wait) ** ** Description : ** Wait for a specified number of CPU cycles. ** Parameters : ** NAME - DESCRIPTION ** cycles - The number of cycles to wait. ** Returns : Nothing ** =================================================================== */ void McuWait_WaitCycles(uint32_t cycles) { /*lint -save -e522 function lacks side effect. */ #if McuWait_CONFIG_USE_CYCLE_COUNTER uint32_t counter = cycles; counter += McuArmTools_GetCycleCounter(); while(McuArmTools_GetCycleCounter()= 100u) { McuWait_Wait100Cycles(); cycles -= 100u; } while(cycles >= 10u) { McuWait_Wait10Cycles(); cycles -= 10u; } #endif /*lint -restore */ } /* ** =================================================================== ** Method : WaitLongCycles (component Wait) ** ** Description : ** Wait for a specified number of CPU cycles (32bit data type). ** Parameters : ** NAME - DESCRIPTION ** cycles - The number of cycles to wait. ** Returns : Nothing ** =================================================================== */ void McuWait_WaitLongCycles(uint32_t cycles) { #if McuWait_CONFIG_USE_CYCLE_COUNTER uint32_t counter = cycles; counter += McuArmTools_GetCycleCounter(); while(McuArmTools_GetCycleCounter()60000) { McuWait_WaitCycles(60000); cycles -= 60000; } McuWait_WaitCycles(cycles); /*lint -restore */ #endif } /* ** =================================================================== ** Method : Waitms (component Wait) ** ** Description : ** Wait for a specified time in milliseconds. ** Parameters : ** NAME - DESCRIPTION ** ms - How many milliseconds the function has to ** wait ** Returns : Nothing ** =================================================================== */ void McuWait_Waitms(uint32_t ms) { /*lint -save -e522 function lacks side effect. */ uint32_t msCycles; /* cycles for 1 ms */ /* static clock/speed configuration */ msCycles = McuWait_NofCyclesMs(1, McuWait_INSTR_CLOCK_HZ); while(ms>0) { McuWait_WaitLongCycles(msCycles); ms--; } /*lint -restore */ } /* ** =================================================================== ** Method : Waitus (component Wait) ** ** Description : ** Wait for a specified time in microseconds. ** Parameters : ** NAME - DESCRIPTION ** us - How many microseconds the function has to ** wait ** Returns : Nothing ** =================================================================== */ /* implemented as macro version. See header file. */ /* ** =================================================================== ** Method : Waitns (component Wait) ** ** Description : ** Wait for a specified time in nano seconds. ** Parameters : ** NAME - DESCRIPTION ** ns - How many ns the function has to wait ** Returns : Nothing ** =================================================================== */ /* implemented as macro version. See header file. */ /* ** =================================================================== ** Method : WaitOSms (component Wait) ** ** Description : ** If an RTOS is enabled, this routine will use a non-blocking ** wait method. Otherwise it will do a busy/blocking wait. ** Parameters : None ** Returns : Nothing ** =================================================================== */ /* void McuWait_WaitOSms(void) { Method is implemented as macro in the header file } */ /* ** =================================================================== ** Method : Init (component Wait) ** ** Description : ** Driver initialization routine. ** Parameters : None ** Returns : Nothing ** =================================================================== */ void McuWait_Init(void) { #if McuWait_CONFIG_USE_CYCLE_COUNTER /* init cycle counter */ McuArmTools_InitCycleCounter(); McuArmTools_ResetCycleCounter(); McuArmTools_EnableCycleCounter(); #endif } /* ** =================================================================== ** Method : Deinit (component Wait) ** ** Description : ** Driver de-initialization routine ** Parameters : None ** Returns : Nothing ** =================================================================== */ void McuWait_Deinit(void) { #if McuWait_CONFIG_USE_CYCLE_COUNTER /* disable hardware cycle counter */ McuArmTools_DisableCycleCounter(); #endif } /* END McuWait. */ /*! ** @} */