diff options
Diffstat (limited to 'tmk_core/common/chibios')
| -rw-r--r-- | tmk_core/common/chibios/_wait.h | 55 | ||||
| -rw-r--r-- | tmk_core/common/chibios/bootloader.c | 2 | ||||
| -rw-r--r-- | tmk_core/common/chibios/chibios_config.h | 7 | ||||
| -rw-r--r-- | tmk_core/common/chibios/sleep_led.c | 88 | ||||
| -rw-r--r-- | tmk_core/common/chibios/suspend.c | 8 | ||||
| -rw-r--r-- | tmk_core/common/chibios/wait.c | 89 | 
6 files changed, 193 insertions, 56 deletions
diff --git a/tmk_core/common/chibios/_wait.h b/tmk_core/common/chibios/_wait.h new file mode 100644 index 0000000000..5bface53e1 --- /dev/null +++ b/tmk_core/common/chibios/_wait.h @@ -0,0 +1,55 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#pragma once + +#include <ch.h> + +/* chThdSleepX of zero maps to infinite - so we map to a tiny delay to still yield */ +#define wait_ms(ms)                     \ +    do {                                \ +        if (ms != 0) {                  \ +            chThdSleepMilliseconds(ms); \ +        } else {                        \ +            chThdSleepMicroseconds(1);  \ +        }                               \ +    } while (0) +#define wait_us(us)                     \ +    do {                                \ +        if (us != 0) {                  \ +            chThdSleepMicroseconds(us); \ +        } else {                        \ +            chThdSleepMicroseconds(1);  \ +        }                               \ +    } while (0) + +/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus + * to which the GPIO is connected. + * The connected buses differ depending on the various series of MCUs. + * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, + * there is a delay of several clocks to read the change of the input signal. + * + * Define this delay with the GPIO_INPUT_PIN_DELAY macro. + * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. + * (A fairly large value of 0.25 microseconds is set.) + */ + +#include "wait.c" + +#ifndef GPIO_INPUT_PIN_DELAY +#    define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +#endif + +#define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c index 6cabcc4b81..4a175a6283 100644 --- a/tmk_core/common/chibios/bootloader.c +++ b/tmk_core/common/chibios/bootloader.c @@ -79,7 +79,7 @@ void enter_bootloader_mode_if_requested(void) {      }  } -#elif defined(KL2x) || defined(K20x)  // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS +#elif defined(KL2x) || defined(K20x) || defined(MK66F18)  // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS  /* Kinetis */  #    if defined(BOOTLOADER_KIIBOHD) diff --git a/tmk_core/common/chibios/chibios_config.h b/tmk_core/common/chibios/chibios_config.h index b4d96465d1..1d8ace4955 100644 --- a/tmk_core/common/chibios/chibios_config.h +++ b/tmk_core/common/chibios/chibios_config.h @@ -15,6 +15,8 @@   */  #pragma once +#define SPLIT_USB_DETECT  // Force this on for now +  #if defined(STM32F1XX)  #    define USE_GPIOV1  #endif @@ -28,4 +30,9 @@  #    define USE_I2CV1  #    define USE_I2CV1_CONTRIB  // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed  #    define USE_GPIOV1 +#    define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY +#endif + +#if defined(MK66F18) +#    define STM32_SYSCLK KINETIS_SYSCLK_FREQUENCY  #endif diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index 5595eec0e5..477056a454 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -9,21 +9,13 @@   * Use LP timer on Kinetises, TIM14 on STM32F0.   */ -#if defined(KL2x) || defined(K20x) - -/* Use Low Power Timer (LPTMR) */ -#    define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR -#    define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF - -#elif defined(STM32F0XX) - -/* Use TIM14 manually */ -#    define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER -#    define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF - +#ifndef SLEEP_LED_GPT_DRIVER +#    if defined(STM32F0XX) +#        define SLEEP_LED_GPT_DRIVER GPTD14 +#    endif  #endif -#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */ +#if defined(KL2x) || defined(K20x) || defined(SLEEP_LED_GPT_DRIVER) /* common parts for timers/interrupts */  /* Breathing Sleep LED brighness(PWM On period) table   * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle @@ -33,10 +25,7 @@   */  static const uint8_t breathing_table[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -/* interrupt handler */ -OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { -    OSAL_IRQ_PROLOGUE(); - +void sleep_led_timer_callback(void) {      /* Software PWM       * timer:1111 1111 1111 1111       *       \_____/\/ \_______/____  count(0-255) @@ -64,17 +53,16 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {      if (timer.pwm.count == breathing_table[timer.pwm.index]) {          led_set(0);      } - -    /* Reset the counter */ -    RESET_COUNTER; - -    OSAL_IRQ_EPILOGUE();  }  #endif /* common parts for known platforms */  #if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */ +/* Use Low Power Timer (LPTMR) */ +#    define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR +#    define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF +  /* LPTMR clock options */  #    define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */  #    define LPTMR_CLOCK_LPO 1      /* 1kHz clock */ @@ -86,6 +74,18 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {  #        define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER  #    endif +/* interrupt handler */ +OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { +    OSAL_IRQ_PROLOGUE(); + +    sleep_led_timer_callback(); + +    /* Reset the counter */ +    RESET_COUNTER; + +    OSAL_IRQ_EPILOGUE(); +} +  /* Initialise the timer */  void sleep_led_init(void) {      /* Make sure the clock to the LPTMR is enabled */ @@ -159,45 +159,23 @@ void sleep_led_toggle(void) {      LPTMR0->CSR ^= LPTMRx_CSR_TEN;  } -#elif defined(STM32F0XX) /* platform selection: STM32F0XX */ - -/* Initialise the timer */ -void sleep_led_init(void) { -    /* enable clock */ -    rccEnableTIM14(FALSE); /* low power enable = FALSE */ -    rccResetTIM14(); - -    /* prescale */ -    /* Assuming 48MHz internal clock */ -    /* getting cca 65484 irqs/sec */ -    STM32_TIM14->PSC = 733; +#elif defined(SLEEP_LED_GPT_DRIVER) -    /* auto-reload */ -    /* 0 => interrupt every time */ -    STM32_TIM14->ARR = 3; +static void gptTimerCallback(GPTDriver *gptp) { +    (void)gptp; +    sleep_led_timer_callback(); +} -    /* enable counter update event interrupt */ -    STM32_TIM14->DIER |= STM32_TIM_DIER_UIE; +static const GPTConfig gptcfg = {1000000, gptTimerCallback, 0, 0}; -    /* register interrupt vector */ -    nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */ -} +/* Initialise the timer */ +void sleep_led_init(void) { gptStart(&SLEEP_LED_GPT_DRIVER, &gptcfg); } -void sleep_led_enable(void) { -    /* Enable the timer */ -    STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS; -    /* URS => update event only on overflow; setting UG bit disabled */ -} +void sleep_led_enable(void) { gptStartContinuous(&SLEEP_LED_GPT_DRIVER, gptcfg.frequency / 0xFFFF); } -void sleep_led_disable(void) { -    /* Disable the timer */ -    STM32_TIM14->CR1 = 0; -} +void sleep_led_disable(void) { gptStopTimer(&SLEEP_LED_GPT_DRIVER); } -void sleep_led_toggle(void) { -    /* Toggle the timer */ -    STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN; -} +void sleep_led_toggle(void) { (SLEEP_LED_GPT_DRIVER.state == GPT_READY) ? sleep_led_enable() : sleep_led_disable(); }  #else /* platform selection: not on familiar chips */ diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 49e20641fb..17f024caba 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -24,6 +24,10 @@  #    include "rgblight.h"  #endif +#ifdef RGB_MATRIX_ENABLE +#    include "rgb_matrix.h" +#endif +  /** \brief suspend idle   *   * FIXME: needs doc @@ -53,6 +57,10 @@ void suspend_power_down(void) {      backlight_set(0);  #endif +#ifdef RGB_MATRIX_ENABLE +    rgb_matrix_task(); +#endif +      // Turn off LED indicators      uint8_t leds_off = 0;  #if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) diff --git a/tmk_core/common/chibios/wait.c b/tmk_core/common/chibios/wait.c new file mode 100644 index 0000000000..c6270fd95e --- /dev/null +++ b/tmk_core/common/chibios/wait.c @@ -0,0 +1,89 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __OPTIMIZE__ +#    pragma message "Compiler optimizations disabled; wait_cpuclock() won't work as designed" +#endif + +#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" + +__attribute__((always_inline)) static inline void wait_cpuclock(unsigned int n) { /* n: 1..135 */ +    /* The argument n must be a constant expression. +     * That way, compiler optimization will remove unnecessary code. */ +    if (n < 1) { +        return; +    } +    if (n > 8) { +        unsigned int n8 = n / 8; +        n               = n - n8 * 8; +        switch (n8) { +            case 16: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 15: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 14: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 13: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 12: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 11: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 10: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 9: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 8: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 7: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 6: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 5: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 4: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 3: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 2: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 1: +                asm volatile(CLOCK_DELAY_NOP8::: "memory"); +            case 0: +                break; +        } +    } +    switch (n) { +        case 8: +            asm volatile("nop" ::: "memory"); +        case 7: +            asm volatile("nop" ::: "memory"); +        case 6: +            asm volatile("nop" ::: "memory"); +        case 5: +            asm volatile("nop" ::: "memory"); +        case 4: +            asm volatile("nop" ::: "memory"); +        case 3: +            asm volatile("nop" ::: "memory"); +        case 2: +            asm volatile("nop" ::: "memory"); +        case 1: +            asm volatile("nop" ::: "memory"); +        case 0: +            break; +    } +}
\ No newline at end of file  | 
