|
| 1 | +/* |
| 2 | + * Copyright (c) 2018-2020, Nuvoton Technology Corporation |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + * |
| 6 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | + * you may not use this file except in compliance with the License. |
| 8 | + * You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + * See the License for the specific language governing permissions and |
| 16 | + * limitations under the License. |
| 17 | + */ |
| 18 | + |
| 19 | +#include "cmsis.h" |
| 20 | +#include "platform/mbed_mpu_mgmt.h" |
| 21 | +#include "platform/mbed_toolchain.h" |
| 22 | +#include "platform/mbed_wait_api.h" |
| 23 | + |
| 24 | +/* Override wait_ns to provide more accurate implementation |
| 25 | + * |
| 26 | + * NOTE1: NANO100 series doesn't support cache and so cannot provide zero-wait |
| 27 | + * state flash performance. |
| 28 | + * NOTE2: NANO100 series doesn't support MPU. The mbed_mpu_manager...() MPU functions |
| 29 | + * are dummy. |
| 30 | + */ |
| 31 | + |
| 32 | +// Cortex-M0+, M3, M4 and M23 take 5 cycles per iteration - SUBS = 1, 2xNOP = 2, BCS = 2 |
| 33 | +#define LOOP_SCALER 5000 |
| 34 | + |
| 35 | +MBED_ALIGN(16) |
| 36 | +static uint16_t delay_loop_code[] = { |
| 37 | + 0x1E40, // SUBS R0,R0,#1 |
| 38 | + 0xBF00, // NOP |
| 39 | + 0xBF00, // NOP |
| 40 | + 0xD2FB, // BCS .-3 (0x00 would be .+2, so 0xFB = -5 = .-3) |
| 41 | + 0x4770 // BX LR |
| 42 | +}; |
| 43 | + |
| 44 | +/* Take the address of the code, set LSB to indicate Thumb, and cast to void() function pointer */ |
| 45 | +#define delay_loop ((void(*)()) ((uintptr_t) delay_loop_code + 1)) |
| 46 | + |
| 47 | +void wait_ns(unsigned int ns) |
| 48 | +{ |
| 49 | + uint32_t cycles_per_us = SystemCoreClock / 1000000; |
| 50 | + // Note that this very calculation, plus call overhead, will take multiple |
| 51 | + // cycles. Could well be 100ns on its own... So round down here, startup is |
| 52 | + // worth at least one loop iteration. |
| 53 | + uint32_t count = (cycles_per_us * ns) / LOOP_SCALER; |
| 54 | + |
| 55 | + mbed_mpu_manager_lock_ram_execution(); |
| 56 | + delay_loop(count); |
| 57 | + mbed_mpu_manager_unlock_ram_execution(); |
| 58 | +} |
0 commit comments