diff options
| -rw-r--r-- | tmk_core/chibios.mk | 3 | ||||
| -rw-r--r-- | tmk_core/common/chibios/_wait.c | 89 | ||||
| -rw-r--r-- | tmk_core/common/chibios/_wait.h | 24 | ||||
| -rw-r--r-- | tmk_core/common/chibios/wait.c | 90 |
4 files changed, 127 insertions, 79 deletions
diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 7962516a0..18839710b 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk | |||
| @@ -211,7 +211,8 @@ CHIBISRC = $(STARTUPSRC) \ | |||
| 211 | $(BOARDSRC) \ | 211 | $(BOARDSRC) \ |
| 212 | $(STREAMSSRC) \ | 212 | $(STREAMSSRC) \ |
| 213 | $(CHIBIOS)/os/various/syscalls.c \ | 213 | $(CHIBIOS)/os/various/syscalls.c \ |
| 214 | $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c | 214 | $(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \ |
| 215 | $(PLATFORM_COMMON_DIR)/wait.c | ||
| 215 | 216 | ||
| 216 | # Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise. | 217 | # Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise. |
| 217 | QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) | 218 | QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM) |
diff --git a/tmk_core/common/chibios/_wait.c b/tmk_core/common/chibios/_wait.c new file mode 100644 index 000000000..1fbea2dd5 --- /dev/null +++ b/tmk_core/common/chibios/_wait.c | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 3 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __OPTIMIZE__ | ||
| 18 | # pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" | ||
| 22 | |||
| 23 | __attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ | ||
| 24 | /* The argument n must be a constant expression. | ||
| 25 | * That way, compiler optimization will remove unnecessary code. */ | ||
| 26 | if (n < 1) { | ||
| 27 | return; | ||
| 28 | } | ||
| 29 | if (n > 8) { | ||
| 30 | unsigned int n8 = n / 8; | ||
| 31 | n = n - n8 * 8; | ||
| 32 | switch (n8) { | ||
| 33 | case 16: | ||
| 34 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 35 | case 15: | ||
| 36 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 37 | case 14: | ||
| 38 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 39 | case 13: | ||
| 40 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 41 | case 12: | ||
| 42 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 43 | case 11: | ||
| 44 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 45 | case 10: | ||
| 46 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 47 | case 9: | ||
| 48 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 49 | case 8: | ||
| 50 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 51 | case 7: | ||
| 52 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 53 | case 6: | ||
| 54 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 55 | case 5: | ||
| 56 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 57 | case 4: | ||
| 58 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 59 | case 3: | ||
| 60 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 61 | case 2: | ||
| 62 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 63 | case 1: | ||
| 64 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 65 | case 0: | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | switch (n) { | ||
| 70 | case 8: | ||
| 71 | asm volatile("nop" ::: "memory"); | ||
| 72 | case 7: | ||
| 73 | asm volatile("nop" ::: "memory"); | ||
| 74 | case 6: | ||
| 75 | asm volatile("nop" ::: "memory"); | ||
| 76 | case 5: | ||
| 77 | asm volatile("nop" ::: "memory"); | ||
| 78 | case 4: | ||
| 79 | asm volatile("nop" ::: "memory"); | ||
| 80 | case 3: | ||
| 81 | asm volatile("nop" ::: "memory"); | ||
| 82 | case 2: | ||
| 83 | asm volatile("nop" ::: "memory"); | ||
| 84 | case 1: | ||
| 85 | asm volatile("nop" ::: "memory"); | ||
| 86 | case 0: | ||
| 87 | break; | ||
| 88 | } | ||
| 89 | } | ||
diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h index 5bface53e..4a5172536 100644 --- a/tmk_core/common/chibios/_wait.h +++ b/tmk_core/common/chibios/_wait.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #pragma once | 16 | #pragma once |
| 17 | 17 | ||
| 18 | #include <ch.h> | 18 | #include <ch.h> |
| 19 | #include <hal.h> | ||
| 19 | 20 | ||
| 20 | /* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ | 21 | /* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ |
| 21 | #define wait_ms(ms) \ | 22 | #define wait_ms(ms) \ |
| @@ -26,14 +27,19 @@ | |||
| 26 | chThdSleepMicroseconds(1); \ | 27 | chThdSleepMicroseconds(1); \ |
| 27 | } \ | 28 | } \ |
| 28 | } while (0) | 29 | } while (0) |
| 29 | #define wait_us(us) \ | 30 | |
| 30 | do { \ | 31 | #ifdef WAIT_US_TIMER |
| 31 | if (us != 0) { \ | 32 | void wait_us(uint16_t duration); |
| 32 | chThdSleepMicroseconds(us); \ | 33 | #else |
| 33 | } else { \ | 34 | # define wait_us(us) \ |
| 34 | chThdSleepMicroseconds(1); \ | 35 | do { \ |
| 35 | } \ | 36 | if (us != 0) { \ |
| 36 | } while (0) | 37 | chThdSleepMicroseconds(us); \ |
| 38 | } else { \ | ||
| 39 | chThdSleepMicroseconds(1); \ | ||
| 40 | } \ | ||
| 41 | } while (0) | ||
| 42 | #endif | ||
| 37 | 43 | ||
| 38 | /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus | 44 | /* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus |
| 39 | * to which the GPIO is connected. | 45 | * to which the GPIO is connected. |
| @@ -46,7 +52,7 @@ | |||
| 46 | * (A fairly large value of 0.25 microseconds is set.) | 52 | * (A fairly large value of 0.25 microseconds is set.) |
| 47 | */ | 53 | */ |
| 48 | 54 | ||
| 49 | #include "wait.c" | 55 | #include "_wait.c" |
| 50 | 56 | ||
| 51 | #ifndef GPIO_INPUT_PIN_DELAY | 57 | #ifndef GPIO_INPUT_PIN_DELAY |
| 52 | # define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) | 58 | # define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) |
diff --git a/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c index c6270fd95..56fd6ffce 100644 --- a/tmk_core/common/chibios/wait.c +++ b/tmk_core/common/chibios/wait.c | |||
| @@ -14,76 +14,28 @@ | |||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #ifndef __OPTIMIZE__ | 17 | #include <ch.h> |
| 18 | # pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" | 18 | #include <hal.h> |
| 19 | #endif | ||
| 20 | 19 | ||
| 21 | #define CLOCK_DELAY_NOP8 "nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t nop\n\t" | 20 | #include "_wait.h" |
| 22 | 21 | ||
| 23 | __attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ | 22 | #ifdef WAIT_US_TIMER |
| 24 | /* The argument n must be a constant expression. | 23 | void wait_us(uint16_t duration) { |
| 25 | * That way, compiler optimization will remove unnecessary code. */ | 24 | static const GPTConfig gpt_cfg = {1000000, NULL, 0, 0}; /* 1MHz timer, no callback */ |
| 26 | if (n < 1) { | 25 | |
| 27 | return; | 26 | if (duration == 0) { |
| 28 | } | 27 | duration = 1; |
| 29 | if (n > 8) { | ||
| 30 | unsigned int n8 = n / 8; | ||
| 31 | n = n - n8 * 8; | ||
| 32 | switch (n8) { | ||
| 33 | case 16: | ||
| 34 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 35 | case 15: | ||
| 36 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 37 | case 14: | ||
| 38 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 39 | case 13: | ||
| 40 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 41 | case 12: | ||
| 42 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 43 | case 11: | ||
| 44 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 45 | case 10: | ||
| 46 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 47 | case 9: | ||
| 48 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 49 | case 8: | ||
| 50 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 51 | case 7: | ||
| 52 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 53 | case 6: | ||
| 54 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 55 | case 5: | ||
| 56 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 57 | case 4: | ||
| 58 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 59 | case 3: | ||
| 60 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 61 | case 2: | ||
| 62 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 63 | case 1: | ||
| 64 | asm volatile(CLOCK_DELAY_NOP8::: "memory"); | ||
| 65 | case 0: | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | } | 28 | } |
| 69 | switch (n) { | 29 | |
| 70 | case 8: | 30 | /* |
| 71 | asm volatile("nop" ::: "memory"); | 31 | * Only use this timer on the main thread; |
| 72 | case 7: | 32 | * other threads need to use their own timer. |
| 73 | asm volatile("nop" ::: "memory"); | 33 | */ |
| 74 | case 6: | 34 | if (chThdGetSelfX() == &ch.mainthread && duration < (1ULL << (sizeof(gptcnt_t) * 8))) { |
| 75 | asm volatile("nop" ::: "memory"); | 35 | gptStart(&WAIT_US_TIMER, &gpt_cfg); |
| 76 | case 5: | 36 | gptPolledDelay(&WAIT_US_TIMER, duration); |
| 77 | asm volatile("nop" ::: "memory"); | 37 | } else { |
| 78 | case 4: | 38 | chThdSleepMicroseconds(duration); |
| 79 | asm volatile("nop" ::: "memory"); | ||
| 80 | case 3: | ||
| 81 | asm volatile("nop" ::: "memory"); | ||
| 82 | case 2: | ||
| 83 | asm volatile("nop" ::: "memory"); | ||
| 84 | case 1: | ||
| 85 | asm volatile("nop" ::: "memory"); | ||
| 86 | case 0: | ||
| 87 | break; | ||
| 88 | } | 39 | } |
| 89 | } \ No newline at end of file | 40 | } |
| 41 | #endif | ||
