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 | ||