Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
mbed_wait_api_no_rtos.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "cmsis.h" 00019 #include "platform/mbed_toolchain.h" 00020 #include "platform/mbed_wait_api.h" 00021 00022 #include "hal/lp_ticker_api.h" 00023 #include "hal/us_ticker_api.h" 00024 #include "hal/ticker_api.h" 00025 00026 // This implementation of the wait functions will be compiled only 00027 // if the RTOS is not present. 00028 #ifndef MBED_CONF_RTOS_PRESENT 00029 00030 void wait(float s) 00031 { 00032 wait_ms(s * 1000.0f); 00033 } 00034 00035 void wait_ms(int ms) 00036 { 00037 #if DEVICE_LPTICKER 00038 const ticker_data_t *const ticker = get_lp_ticker_data(); 00039 uint32_t start = ticker_read(ticker); 00040 while ((ticker_read(ticker) - start) < (uint32_t)(ms * 1000)); 00041 #else 00042 wait_us(ms * 1000); 00043 #endif 00044 } 00045 00046 #endif // #ifndef MBED_CONF_RTOS_PRESENT 00047 00048 // This wait_us is used by both RTOS and non-RTOS builds 00049 /* The actual time delay may be 1 less usec */ 00050 00051 #if DEVICE_USTICKER 00052 00053 #if defined US_TICKER_PERIOD_NUM 00054 /* Real definition for binary compatibility with binaries not using the new macro */ 00055 void (wait_us)(int us) 00056 { 00057 wait_us(us); 00058 } 00059 00060 /* External definition for the inline function */ 00061 extern void _wait_us_inline(unsigned int us); 00062 00063 void _wait_us_ticks(uint32_t ticks) 00064 { 00065 const uint32_t start = us_ticker_read(); 00066 while (((us_ticker_read() - start) & US_TICKER_MASK) < ticks); 00067 } 00068 00069 void _wait_us_generic(unsigned int us) 00070 #else 00071 void wait_us(int us) 00072 #endif 00073 { 00074 // Generic version using full ticker, allowing for initialization, scaling and widening of timer 00075 const ticker_data_t *const ticker = get_us_ticker_data(); 00076 const uint32_t start = ticker_read(ticker); 00077 while ((ticker_read(ticker) - start) < (uint32_t)us); 00078 } 00079 00080 #else // DEVICE_USTICKER 00081 00082 // fallback to wait_ns for targets without usticker 00083 void wait_us(int us) 00084 { 00085 while (us > 1024) { 00086 us -= 1024; 00087 wait_ns(1024000); 00088 } 00089 if (us > 0) { 00090 wait_ns(us * 1000); 00091 } 00092 } 00093 00094 #endif // DEVICE_USTICKER 00095 00096 // This wait_ns is used by both RTOS and non-RTOS builds 00097 00098 #ifdef __CORTEX_M 00099 #if (__CORTEX_M == 0 && !defined __CM0PLUS_REV) || __CORTEX_M == 1 00100 // Cortex-M0 and Cortex-M1 take 6 cycles per iteration - SUBS = 1, 2xNOP = 2, BCS = 3 00101 #define LOOP_SCALER 6000 00102 #elif (__CORTEX_M == 0 && defined __CM0PLUS_REV) || __CORTEX_M == 3 || __CORTEX_M == 4 || \ 00103 __CORTEX_M == 23 00104 // Cortex-M0+, M3, M4 and M23 take 5 cycles per iteration - SUBS = 1, 2xNOP = 2, BCS = 2 00105 #define LOOP_SCALER 5000 00106 #elif __CORTEX_M == 33 00107 // Cortex-M33 can dual issue for 3 cycles per iteration (SUB,NOP) = 1, (NOP,BCS) = 2 00108 #define LOOP_SCALER 3000 00109 #elif __CORTEX_M == 7 00110 // Cortex-M7 manages to dual-issue for 2 cycles per iteration (SUB,NOP) = 1, (NOP,BCS) = 1 00111 // (The NOPs were added to stabilise this - with just the SUB and BCS, it seems that the 00112 // M7 sometimes takes 1 cycle, sometimes 2, possibly depending on alignment) 00113 #define LOOP_SCALER 2000 00114 #endif 00115 #elif defined __CORTEX_A 00116 #if __CORTEX_A == 9 00117 // Cortex-A9 can dual issue for 3 cycles per iteration (SUB,NOP) = 1, (NOP,BCS) = 2 00118 #define LOOP_SCALER 3000 00119 #endif 00120 #endif 00121 00122 /* We only define the function if we've identified the CPU. If we haven't, 00123 * rather than a compile-time error, leave it undefined, rather than faulting 00124 * with an immediate #error. This leaves the door open to non-ARM 00125 * builds with or people providing substitutes for other CPUs, and only if 00126 * needed. 00127 */ 00128 #ifdef LOOP_SCALER 00129 00130 /* Timing seems to depend on alignment, and toolchains do not support aligning 00131 * functions well. So sidestep that by hand-assembling the code. Also avoids 00132 * the hassle of handling multiple toolchains with different assembler 00133 * syntax. 00134 */ 00135 MBED_ALIGN(16) 00136 static const uint16_t delay_loop_code[] = { 00137 0x1E40, // SUBS R0,R0,#1 00138 0xBF00, // NOP 00139 0xBF00, // NOP 00140 0xD2FB, // BCS .-3 (0x00 would be .+2, so 0xFB = -5 = .-3) 00141 0x4770 // BX LR 00142 }; 00143 00144 /* Take the address of the code, set LSB to indicate Thumb, and cast to void() function pointer */ 00145 #define delay_loop ((void(*)()) ((uintptr_t) delay_loop_code + 1)) 00146 00147 /* Some targets may not provide zero-wait-state flash performance. Export this function 00148 * to be overridable for targets to provide more accurate implementation like locating 00149 * 'delay_loop_code' in SRAM. */ 00150 MBED_WEAK void wait_ns(unsigned int ns) 00151 { 00152 uint32_t cycles_per_us = SystemCoreClock / 1000000; 00153 // Note that this very calculation, plus call overhead, will take multiple 00154 // cycles. Could well be 100ns on its own... So round down here, startup is 00155 // worth at least one loop iteration. 00156 uint32_t count = (cycles_per_us * ns) / LOOP_SCALER; 00157 00158 delay_loop(count); 00159 } 00160 #endif // LOOP_SCALER
Generated on Tue Jul 12 2022 13:54:34 by
