Squashed 'tmk_core/' changes from ee8c5ba..d5c5ac6
d5c5ac6 Merge branch 'develop' 5957682 Merge branch 'hotfix-mediakey' a478c62 Merge branch 'hotfix-vusb' cccebfe Merge branch 'njbair-docfix' 0aaab57 Clean up wording in keymap example dc8bbc3 Clarify layer precedence 9e0b4c1 clarify layer documentation 915eb48 core: Fix media/consumer keys 88f90f3 Fix for VUSB configuration 3e290cd Fix including board.mk in chibios.mk 32c69e0 Merge branch 'newapi' into develop c9a56f9 Merge remote-tracking branch 'flabbergast/chibios' into develop 01e33ea Fix chibios and mbed common.mk for hook.c bea79d9 hook: Change func name of usb events 3e97536 hook: Change file and func names(*_hook -> hook_*) c286d8c Merge pull request #10 from fredizzimo/chibios-contrib2 062d74e Update ChibiOS instructions d47150f Add support for new version of ChibiOS and Contrib 62b5401 Chibios: disable LTO (link-time optimisation). c64e9aa hooks: Fix for LUFA 54e68b0 hooks: Remove led_restore_hook 325c09d Chibios: make the default bootloader_jump redefinable (weak). 078c722 Chibios: fix STM32_BOOTLOADER_ADDRESS name. e73cfe5 hooks: Fix for keyboard LED update e6120c5 Implement basic hooks. 7c370e9 Chibios: Update the main chibios README. 7f0198d Chibios: implement sleep LED for STM32. afef9b4 Fix hard-coded path of CHIBIOS 95c5b19 Merge pull request #7 from fredizzimo/sysvsize 27128a8 Sysv format for ChibiOS arm-none-eabi-size d4b8e68 core: Fix chibios user compile options b85d462 Merge branch 'chibios' of https://github.com/flabbergast/tmk_keyboard into flabbergast_chibios de41aa1 core: Fix ps2_mouse.c debug print d79d925 Removed duplicate debug message code and surrounded it with IFDEF as needed 8f28589 Chibios: Revert common.mk change (fix AVR linking problem). ec9eff2 Chibios: cleanup usb_main code. 28c4665 Chibios: Fix a HardFault bug (wait after start). git-subtree-dir: tmk_core git-subtree-split: d5c5ac63e60dfc6da6661a21bd968b4d577a27d5
This commit is contained in:
parent
657d9f23fe
commit
71381457fa
22 changed files with 446 additions and 119 deletions
|
|
@ -1,21 +1,30 @@
|
|||
## TMK running on top of ChibiOS
|
||||
|
||||
This code can be used to run TMK keyboard logic on top of [ChibiOS], meaning that you can run TMK on whatever [ChibiOS] supports. The notable examples are ARM-based Teensies (3.x and LC) and on the boards with STM32 MCUs.
|
||||
|
||||
### Usage
|
||||
|
||||
- To use, unpack or symlink [ChibiOS] to `tmk_core/tool/chibios/chibios`. For Kinetis support (this means Teensies, Infinity keyboard, WhiteFox keyboard), you'll need a fork which implements the USB driver, e.g. [this one](https://github.com/flabbergast/ChibiOS/tree/kinetis).
|
||||
- You will also need to install an ARM toolchain, for instance from [here](https://launchpad.net/gcc-arm-embedded). On linux, this is usually also present as a package for your distribution (as `gcc-arm` or something similar). On OS X, you can use [homebrew](http://brew.sh/) with an appropriate tap.
|
||||
|
||||
### Notes
|
||||
|
||||
- To use, unpack or symlink [ChibiOS] {currently 3.0.2} to `tmk_core/tool/chibios/chibios`. For Kinetis support, you'll need a fork which implements the USB driver, e.g. [this one](https://github.com/flabbergast/ChibiOS/tree/kinetis).
|
||||
- Some comments about ChibiOS syntax and the most commonly used GPIO functions are, as well as an example for ARM Teensies, is [here](https://github.com/tmk/tmk_keyboard/blob/master/keyboard/teensy_lc_onekey/instructions.md).
|
||||
- For gcc options, inspect `tmk_core/tool/chibios/chibios.mk`. For instance, I enabled `-Wno-missing-field-initializers`, because TMK common bits generated a lot of warnings on that.
|
||||
Also pay attention to `-O0` (enabled for debugging); for deployment use `-O2`.
|
||||
- USB string descriptors are messy. I did not find a way to cleanly generate the right structures from actual strings, so the definitions in individual keyboards' `config.h` are ugly as heck.
|
||||
- There are some random constants left so far, e.g. 5ms sleep between calling `keyboard_task`, or 1.5sec wait for USB init, in `main.c`. There should be no such in `usb_main.c` (the main USB stack). Everything is based on timers/interrupts/kernel scheduling (well except `keyboard_task`), so no periodically called things (again, except `keyboard_task`, which is just how TMK is designed).
|
||||
- It is easy to add some code for testing (e.g. blink LED, do stuff on button press, etc...) - just create another thread in `main.c`, it will run independently of the keyboard business.
|
||||
- Jumping to (the built-in) bootloaders on STM32 works, but it is not entirely pleasant, since it is very much MCU dependent. So, one needs to dig out the right address to jump to, and either pass it to the compiler in the `Makefile`, or better, define it in `<your_kb>/bootloader_defs.h`. Also, a patch to upstream ChibiOS is needed (supplied), because it `ResetHandler` needs adjusting.
|
||||
- Sleep LED works, but at the moment only on/off, i.e. no breathing.
|
||||
- Jumping to (the built-in) bootloaders on STM32 works, but it is not entirely pleasant, since it is very much MCU dependent. So, one needs to dig out the right address to jump to, and either pass it to the compiler in the `Makefile`, or better, define it in `<your_kb>/bootloader_defs.h`. An additional startup code is also needed; the best way to deal with this is to define custom board files. (Example forthcoming.)
|
||||
|
||||
### Experimental pre-ChibiOS 4 support
|
||||
- As an alternative to the mentioned flabbergast branch above, you can use the [master branch of ChibiOS](https://github.com/ChibiOS/ChibiOS).
|
||||
- Note that the Kinetis support has moved to the [ChibiOS-Contrib repository](https://github.com/ChibiOS/ChibiOS-Contrib), so you need to put that into your repository in the same way as you did for the main ChibiOS repository.
|
||||
- You also need to define CHIBIOS_CONTRIB in your makefile and point it to the right directory.
|
||||
- You need to add some new options to chconf.h, or you will get compiler errors. Just copy the new options from samples provided by the ChibiOS-Contrib repository.
|
||||
|
||||
### Immediate todo
|
||||
|
||||
- host-wakeup packet sending during suspend
|
||||
- power saving for suspend?
|
||||
- PWM for sleep led
|
||||
- power saving for suspend
|
||||
|
||||
### Not tested, but possibly working
|
||||
|
||||
|
|
@ -27,14 +36,14 @@ Also pay attention to `-O0` (enabled for debugging); for deployment use `-O2`.
|
|||
|
||||
### Tried with
|
||||
|
||||
- ChibiOS 3.0.1, 3.0.2 and ST F072RB DISCOVERY board.
|
||||
- Need to test on other STM32 chips (F3, F4) to make it as much chip-independent as possible.
|
||||
- ChibiOS with Kinetis patches and Teensy LC and 3.0.
|
||||
- Infinity, WhiteFox keyboards
|
||||
- all ARM-based Teensies
|
||||
- some STM32-based boards (e.g. ST-F072RB-DISCOVERY board, STM32F042 breakout board, Maple Mini (STM32F103-based))
|
||||
|
||||
## ChibiOS-supported MCUs (as of 3.0.2)
|
||||
## ChibiOS-supported MCUs
|
||||
|
||||
- Pretty much all STM32 chips.
|
||||
- There is some support for K20x and KL2x Freescale chips (i.e. Teensy 3.x/LC, mchck, FRDM-KL2{5,6}Z, FRDM-K20D50M), but again, no official USB stack yet. However the `kinetis` branch of [my ChibiOS fork](https://github.com/flabbergast/ChibiOS). With this fork, TMK work normally on all the ARM Teensies.
|
||||
- There is some support for K20x and KL2x Freescale chips (i.e. Teensy 3.x/LC, mchck, FRDM-KL2{5,6}Z, FRDM-K20D50M), but again, no official USB stack yet. However the `kinetis` branch of [flabbergast's ChibiOS fork](https://github.com/flabbergast/ChibiOS). With this fork, TMK work normally on all the ARM Teensies.
|
||||
- There is also support for AVR8, but the USB stack is not implemented for them yet, and also the kernel itself takes about 1k of RAM. I think people managed to get ChibiOS running on atmega32[8p/u4] though.
|
||||
- I've seen community support for Nordic NRF51822 (the chip in Adafruit's Bluefruit bluetooth-low-energy boards), but not sure about the extent.
|
||||
|
||||
|
|
@ -43,7 +52,6 @@ Also pay attention to `-O0` (enabled for debugging); for deployment use `-O2`.
|
|||
- STM32F0x2 chips can do crystal-less USB, but they still need a 3.3V voltage regulator.
|
||||
- The BOOT0 pin should be tied to GND.
|
||||
- For a hardware way of accessing the in-built DFU bootloader, in addition to the reset button, put another button between the BOOT0 pin and 3V3.
|
||||
- For breathing the caps lock LED during the suspended state ("sleep LED"), it is desirable to have that LED on a hardware PWM pin (there's usually plenty of those, look for TIMERs in the datasheet). However this is not strictly necessary, because instead of direct output of a timer to a pin (better of course), it is easy to define timer callbacks in ChibiOS that turn on/off an arbitrary pin.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "sleep_led.h"
|
||||
#endif
|
||||
#include "suspend.h"
|
||||
#include "hook.h"
|
||||
|
||||
|
||||
/* -------------------------
|
||||
|
|
@ -58,6 +59,22 @@ host_driver_t chibios_driver = {
|
|||
send_consumer
|
||||
};
|
||||
|
||||
/* Default hooks definitions. */
|
||||
__attribute__((weak))
|
||||
void hook_early_init(void) {}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_late_init(void) {}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_usb_suspend_loop(void) {
|
||||
/* Do this in the suspended state */
|
||||
suspend_power_down(); // on AVR this deep sleeps for 15ms
|
||||
/* Remote wakeup */
|
||||
if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) {
|
||||
send_remote_wakeup(&USB_DRIVER);
|
||||
}
|
||||
}
|
||||
|
||||
/* TESTING
|
||||
* Amber LED blinker thread, times are in milliseconds.
|
||||
|
|
@ -91,6 +108,8 @@ int main(void) {
|
|||
// TESTING
|
||||
// chThdCreateStatic(waBlinkerThread, sizeof(waBlinkerThread), NORMALPRIO, blinkerThread, NULL);
|
||||
|
||||
hook_early_init();
|
||||
|
||||
/* Init USB */
|
||||
init_usb_driver(&USB_DRIVER);
|
||||
|
||||
|
|
@ -101,6 +120,13 @@ int main(void) {
|
|||
while(USB_DRIVER.state != USB_ACTIVE)
|
||||
chThdSleepMilliseconds(50);
|
||||
|
||||
/* Do need to wait here!
|
||||
* Otherwise the next print might start a transfer on console EP
|
||||
* before the USB is completely ready, which sometimes causes
|
||||
* HardFaults.
|
||||
*/
|
||||
chThdSleepMilliseconds(50);
|
||||
|
||||
print("USB configured.\n");
|
||||
|
||||
/* init TMK modules */
|
||||
|
|
@ -113,21 +139,18 @@ int main(void) {
|
|||
|
||||
print("Keyboard start.\n");
|
||||
|
||||
hook_late_init();
|
||||
|
||||
/* Main loop */
|
||||
while(true) {
|
||||
|
||||
if(USB_DRIVER.state == USB_SUSPENDED) {
|
||||
print("[s]");
|
||||
while(USB_DRIVER.state == USB_SUSPENDED) {
|
||||
/* Do this in the suspended state */
|
||||
suspend_power_down(); // on AVR this deep sleeps for 15ms
|
||||
/* Remote wakeup */
|
||||
if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) {
|
||||
send_remote_wakeup(&USB_DRIVER);
|
||||
}
|
||||
hook_usb_suspend_loop();
|
||||
}
|
||||
/* Woken up */
|
||||
// variables has been already cleared by the wakeup hook
|
||||
// variables have been already cleared
|
||||
send_keyboard_report();
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
mousekey_send();
|
||||
|
|
|
|||
|
|
@ -27,15 +27,34 @@
|
|||
#include "sleep_led.h"
|
||||
#include "led.h"
|
||||
#endif
|
||||
#include "hook.h"
|
||||
|
||||
/* TMK hooks */
|
||||
__attribute__((weak))
|
||||
void hook_usb_wakeup(void) {
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_disable();
|
||||
// NOTE: converters may not accept this
|
||||
led_set(host_keyboard_leds());
|
||||
#endif /* SLEEP_LED_ENABLE */
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_usb_suspend_entry(void) {
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_enable();
|
||||
#endif /* SLEEP_LED_ENABLE */
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Global interface variables and declarations
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
|
||||
uint8_t keyboard_idle = 0;
|
||||
uint8_t keyboard_protocol = 1;
|
||||
uint16_t keyboard_led_stats = 0;
|
||||
uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
|
||||
uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
|
||||
uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
|
||||
volatile uint16_t keyboard_idle_count = 0;
|
||||
static virtual_timer_t keyboard_idle_timer;
|
||||
static void keyboard_idle_timer_cb(void *arg);
|
||||
|
|
@ -795,19 +814,13 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
|
|||
|
||||
case USB_EVENT_SUSPEND:
|
||||
//TODO: from ISR! print("[S]");
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_enable();
|
||||
#endif /* SLEEP_LED_ENABLE */
|
||||
hook_usb_suspend_entry();
|
||||
return;
|
||||
|
||||
case USB_EVENT_WAKEUP:
|
||||
//TODO: from ISR! print("[W]");
|
||||
suspend_wakeup_init();
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_disable();
|
||||
// NOTE: converters may not accept this
|
||||
led_set(host_keyboard_leds());
|
||||
#endif /* SLEEP_LED_ENABLE */
|
||||
hook_usb_wakeup();
|
||||
return;
|
||||
|
||||
case USB_EVENT_STALLED:
|
||||
|
|
@ -1350,7 +1363,7 @@ int8_t sendchar(uint8_t c) {
|
|||
return 0;
|
||||
}
|
||||
osalSysUnlock();
|
||||
/* Timeout after 5us if the queue is full.
|
||||
/* Timeout after 100us if the queue is full.
|
||||
* Increase this timeout if too much stuff is getting
|
||||
* dropped (i.e. the buffer is getting full too fast
|
||||
* for USB/HIDRAW to dequeue). Another possibility
|
||||
|
|
|
|||
|
|
@ -58,9 +58,6 @@ void send_remote_wakeup(USBDriver *usbp);
|
|||
#define NKRO_REPORT_KEYS (NKRO_EPSIZE - 1)
|
||||
#endif
|
||||
|
||||
/* this defines report_keyboard_t and computes REPORT_SIZE defines */
|
||||
// #include "report.h"
|
||||
|
||||
/* extern report_keyboard_t keyboard_report_sent; */
|
||||
|
||||
/* keyboard IN request callback handler */
|
||||
|
|
@ -122,8 +119,7 @@ typedef struct {
|
|||
#define CONSOLE_EPSIZE 16
|
||||
|
||||
/* Number of IN reports that can be stored inside the output queue */
|
||||
#define CONSOLE_QUEUE_CAPACITY 2
|
||||
#define CONSOLE_QUEUE_BUFFER_SIZE (CONSOLE_QUEUE_CAPACITY * CONSOLE_EPSIZE)
|
||||
#define CONSOLE_QUEUE_CAPACITY 4
|
||||
|
||||
/* Console flush time */
|
||||
#define CONSOLE_FLUSH_MS 50
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "sleep_led.h"
|
||||
#endif
|
||||
#include "suspend.h"
|
||||
#include "hook.h"
|
||||
|
||||
#include "descriptor.h"
|
||||
#include "lufa.h"
|
||||
|
|
@ -180,21 +181,13 @@ void EVENT_USB_Device_Reset(void)
|
|||
void EVENT_USB_Device_Suspend()
|
||||
{
|
||||
print("[S]");
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_enable();
|
||||
#endif
|
||||
hook_usb_suspend_entry();
|
||||
}
|
||||
|
||||
void EVENT_USB_Device_WakeUp()
|
||||
{
|
||||
print("[W]");
|
||||
suspend_wakeup_init();
|
||||
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_disable();
|
||||
// NOTE: converters may not accept this
|
||||
led_set(host_keyboard_leds());
|
||||
#endif
|
||||
hook_usb_wakeup();
|
||||
}
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|
|
@ -592,6 +585,7 @@ int main(void) __attribute__ ((weak));
|
|||
int main(void)
|
||||
{
|
||||
setup_mcu();
|
||||
hook_early_init();
|
||||
keyboard_setup();
|
||||
setup_usb();
|
||||
sei();
|
||||
|
|
@ -614,13 +608,11 @@ int main(void)
|
|||
#endif
|
||||
|
||||
print("Keyboard start.\n");
|
||||
hook_late_init();
|
||||
while (1) {
|
||||
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
||||
print("[s]");
|
||||
suspend_power_down();
|
||||
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
|
||||
USB_Device_SendRemoteWakeup();
|
||||
}
|
||||
hook_usb_suspend_loop();
|
||||
}
|
||||
|
||||
keyboard_task();
|
||||
|
|
@ -630,3 +622,39 @@ int main(void)
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* hooks */
|
||||
__attribute__((weak))
|
||||
void hook_early_init(void) {}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_late_init(void) {}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_usb_suspend_entry(void)
|
||||
{
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_usb_suspend_loop(void)
|
||||
{
|
||||
suspend_power_down();
|
||||
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
|
||||
USB_Device_SendRemoteWakeup();
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void hook_usb_wakeup(void)
|
||||
{
|
||||
suspend_wakeup_init();
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_disable();
|
||||
// NOTE: converters may not accept this
|
||||
led_set(host_keyboard_leds());
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,17 +85,13 @@ void ps2_mouse_task(void)
|
|||
if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
|
||||
return;
|
||||
}
|
||||
xprintf("%ud ", timer_read());
|
||||
print("ps2_mouse raw: [");
|
||||
phex(mouse_report.buttons); print("|");
|
||||
print_hex8((uint8_t)mouse_report.x); print(" ");
|
||||
print_hex8((uint8_t)mouse_report.y); print("]\n");
|
||||
|
||||
/* if mouse moves or buttons state changes */
|
||||
if (mouse_report.x || mouse_report.y ||
|
||||
((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
|
||||
|
||||
#ifdef PS2_MOUSE_DEBUG
|
||||
xprintf("%ud ", timer_read());
|
||||
print("ps2_mouse raw: [");
|
||||
phex(mouse_report.buttons); print("|");
|
||||
print_hex8((uint8_t)mouse_report.x); print(" ");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ SRC += $(VUSB_DIR)/main.c \
|
|||
|
||||
|
||||
ifdef NO_UART
|
||||
OPT_DEFS += -DNO_UART
|
||||
SRC += $(COMMON_DIR)/sendchar_null.c
|
||||
else
|
||||
SRC += $(COMMON_DIR)/sendchar_uart.c \
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int main(void)
|
|||
#endif
|
||||
|
||||
CLKPR = 0x80, CLKPR = 0;
|
||||
#ifndef PS2_USE_USART
|
||||
#ifndef NO_UART
|
||||
uart_init(UART_BAUD_RATE);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue