aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/_summary.md4
-rw-r--r--docs/platformdev_chibios_earlyinit.md53
-rw-r--r--tmk_core/protocol/chibios/init_hooks.h5
-rw-r--r--tmk_core/protocol/chibios/main.c38
-rw-r--r--tmk_core/rules.mk16
5 files changed, 111 insertions, 5 deletions
diff --git a/docs/_summary.md b/docs/_summary.md
index e35125109..d47b252c0 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -136,6 +136,10 @@
136 * [Development Environment](api_development_environment.md) 136 * [Development Environment](api_development_environment.md)
137 * [Architecture Overview](api_development_overview.md) 137 * [Architecture Overview](api_development_overview.md)
138 138
139 * Hardware Platform Development
140 * Arm/ChibiOS
141 * [Early initialization](platformdev_chibios_earlyinit.md)
142
139 * QMK Reference 143 * QMK Reference
140 * [Contributing to QMK](contributing.md) 144 * [Contributing to QMK](contributing.md)
141 * [Translating the QMK Docs](translating.md) 145 * [Translating the QMK Docs](translating.md)
diff --git a/docs/platformdev_chibios_earlyinit.md b/docs/platformdev_chibios_earlyinit.md
new file mode 100644
index 000000000..699c22377
--- /dev/null
+++ b/docs/platformdev_chibios_earlyinit.md
@@ -0,0 +1,53 @@
1# Arm/ChibiOS Early Initialization :id=chibios-early-init
2
3This page describes a part of QMK that is a somewhat advanced concept, and is only relevant to keyboard designers.
4
5QMK uses ChibiOS as the underlying layer to support a multitude of Arm-based devices. Each ChibiOS-supported keyboard has a low-level board definition which is responsible for initializing hardware peripherals such as the clocks, and GPIOs.
6
7Older QMK revisions required duplication of these board definitions inside your keyboard's directory in order to override such early initialization points; this is now abstracted into the following APIs, and allows usage of the board definitions supplied with ChibiOS itself. Check `<qmk_firmware>/lib/chibios/os/hal/boards` for the list of official definitions. If your keyboard needs extra initialization at a very early stage, consider providing keyboard-level overrides of the following APIs:
8
9## `early_hardware_init_pre()` :id=early-hardware-init-pre
10
11The function `early_hardware_init_pre` is the earliest possible code that can be executed by a keyboard firmware. This is intended as a replacement for the ChibiOS board definition's `__early_init` function, and is the equivalent of executing at the start of the function.
12
13This is executed before RAM gets cleared, and before clocks or GPIOs are configured; any delays or preparation using GPIOs is not likely to work at this point. After executing this function, RAM on the MCU may be zero'ed. Assigning values to variables during execution of this function may be overwritten.
14
15As such, if you wish to override this API consider limiting use to writing to low-level registers. The default implementation of this function can be configured to jump to bootloader if a `RESET` key was pressed, by ensuring `#define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE` is in the keyboard's `config.h` file.
16
17To implement your own version of this function, in your keyboard's source files:
18
19```c
20void early_hardware_init_pre(void) {
21 // do things with registers
22}
23```
24
25## `early_hardware_init_post()` :id=early-hardware-init-post
26
27The function `early_hardware_init_post` is the next earliest possible code that can be executed by a keyboard firmware. This is executed after RAM has been cleared, and clocks and GPIOs are configured. This is intended as a replacement for the ChibiOS board definition's `__early_init` function, and is the equivalent of executing at the end of the function.
28
29Much like `early_hardware_init_pre`, ChibiOS has not yet been initialized either, so the same restrictions on delays and timing apply.
30
31If you wish to override this API, consider limiting functionality to register writes, variable initialization, and GPIO toggling. The default implementation of this function is to do nothing.
32
33To implement your own version of this function, in your keyboard's source files:
34
35```c
36void early_hardware_init_post(void) {
37 // toggle GPIO pins and write to variables
38}
39```
40
41## `board_init()` :id=board-init
42
43The function `board_init` is executed directly after the ChibiOS initialization routines have completed. At this stage, all normal low-level functionality should be available for use (including timers and delays), with the restriction that USB is not yet connected. This is intended as a replacement for the ChibiOS board definition's `boardInit` function.
44
45The default implementation of this function is to do nothing.
46
47To implement your own version of this function, in your keyboard's source files:
48
49```c
50void board_init(void) {
51 // initialize anything that requires ChibiOS
52}
53``` \ No newline at end of file
diff --git a/tmk_core/protocol/chibios/init_hooks.h b/tmk_core/protocol/chibios/init_hooks.h
new file mode 100644
index 000000000..fffced913
--- /dev/null
+++ b/tmk_core/protocol/chibios/init_hooks.h
@@ -0,0 +1,5 @@
1#pragma once
2
3// Override the initialisation functions inside the ChibiOS board.c files
4#define __early_init __chibios_override___early_init
5#define boardInit __chibios_override_boardInit
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c
index 6479fd09d..61665eb6f 100644
--- a/tmk_core/protocol/chibios/main.c
+++ b/tmk_core/protocol/chibios/main.c
@@ -33,6 +33,11 @@
33#include "debug.h" 33#include "debug.h"
34#include "printf.h" 34#include "printf.h"
35 35
36#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
37// Change this to be TRUE once we've migrated keyboards to the new init system
38# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP FALSE
39#endif
40
36#ifdef SLEEP_LED_ENABLE 41#ifdef SLEEP_LED_ENABLE
37# include "sleep_led.h" 42# include "sleep_led.h"
38#endif 43#endif
@@ -101,6 +106,39 @@ void midi_ep_task(void);
101// } 106// }
102// } 107// }
103 108
109/* Early initialisation
110 */
111__attribute__((weak)) void early_hardware_init_pre(void) {
112#if EARLY_INIT_PERFORM_BOOTLOADER_JUMP
113 void enter_bootloader_mode_if_requested(void);
114 enter_bootloader_mode_if_requested();
115#endif // EARLY_INIT_PERFORM_BOOTLOADER_JUMP
116}
117
118__attribute__((weak)) void early_hardware_init_post(void) {}
119
120__attribute__((weak)) void board_init(void) {}
121
122// This overrides what's normally in ChibiOS board definitions
123void __early_init(void) {
124 early_hardware_init_pre();
125
126 // This is the renamed equivalent of __early_init in the board.c file
127 void __chibios_override___early_init(void);
128 __chibios_override___early_init();
129
130 early_hardware_init_post();
131}
132
133// This overrides what's normally in ChibiOS board definitions
134void boardInit(void) {
135 // This is the renamed equivalent of boardInit in the board.c file
136 void __chibios_override_boardInit(void);
137 __chibios_override_boardInit();
138
139 board_init();
140}
141
104/* Main thread 142/* Main thread
105 */ 143 */
106int main(void) { 144int main(void) {
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index c1474a5c2..a66718cd2 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -223,6 +223,12 @@ $(foreach LOBJ, $(NO_LTO_OBJ), $(eval $(call NO_LTO,$(LOBJ))))
223 223
224MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@) 224MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
225 225
226# For a ChibiOS build, ensure that the board files have the hook overrides injected
227define BOARDSRC_INJECT_HOOKS
228$(KEYBOARD_OUTPUT)/$(patsubst %.c,%.o,$(patsubst ./%,%,$1)): INIT_HOOK_CFLAGS += -include $(TOP_DIR)/tmk_core/protocol/chibios/init_hooks.h
229endef
230$(foreach LOBJ, $(BOARDSRC), $(eval $(call BOARDSRC_INJECT_HOOKS,$(LOBJ))))
231
226# Add QMK specific flags 232# Add QMK specific flags
227DFU_SUFFIX ?= dfu-suffix 233DFU_SUFFIX ?= dfu-suffix
228DFU_SUFFIX_ARGS ?= 234DFU_SUFFIX_ARGS ?=
@@ -306,27 +312,27 @@ ifdef $1_CONFIG
306$1_CONFIG_FLAGS += $$(patsubst %,-include %,$$($1_CONFIG)) 312$1_CONFIG_FLAGS += $$(patsubst %,-include %,$$($1_CONFIG))
307endif 313endif
308$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS) 314$1_CFLAGS = $$(ALL_CFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS)
309$1_CXXFLAGS= $$(ALL_CXXFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS) 315$1_CXXFLAGS = $$(ALL_CXXFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) $$(NOLTO_CFLAGS)
310$1_ASFLAGS= $$(ALL_ASFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS) 316$1_ASFLAGS = $$(ALL_ASFLAGS) $$($1_DEFS) $$($1_INCFLAGS) $$($1_CONFIG_FLAGS)
311 317
312# Compile: create object files from C source files. 318# Compile: create object files from C source files.
313$1/%.o : %.c $1/%.d $1/cflags.txt $1/compiler.txt | $(BEGIN) 319$1/%.o : %.c $1/%.d $1/cflags.txt $1/compiler.txt | $(BEGIN)
314 @mkdir -p $$(@D) 320 @mkdir -p $$(@D)
315 @$$(SILENT) || printf "$$(MSG_COMPILING) $$<" | $$(AWK_CMD) 321 @$$(SILENT) || printf "$$(MSG_COMPILING) $$<" | $$(AWK_CMD)
316 $$(eval CMD := $$(CC) -c $$($1_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP)) 322 $$(eval CMD := $$(CC) -c $$($1_CFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
317 @$$(BUILD_CMD) 323 @$$(BUILD_CMD)
318 324
319# Compile: create object files from C++ source files. 325# Compile: create object files from C++ source files.
320$1/%.o : %.cpp $1/%.d $1/cxxflags.txt $1/compiler.txt | $(BEGIN) 326$1/%.o : %.cpp $1/%.d $1/cxxflags.txt $1/compiler.txt | $(BEGIN)
321 @mkdir -p $$(@D) 327 @mkdir -p $$(@D)
322 @$$(SILENT) || printf "$$(MSG_COMPILING_CXX) $$<" | $$(AWK_CMD) 328 @$$(SILENT) || printf "$$(MSG_COMPILING_CXX) $$<" | $$(AWK_CMD)
323 $$(eval CMD=$$(CC) -c $$($1_CXXFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP)) 329 $$(eval CMD=$$(CC) -c $$($1_CXXFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
324 @$$(BUILD_CMD) 330 @$$(BUILD_CMD)
325 331
326$1/%.o : %.cc $1/%.d $1/cxxflags.txt $1/compiler.txt | $(BEGIN) 332$1/%.o : %.cc $1/%.d $1/cxxflags.txt $1/compiler.txt | $(BEGIN)
327 @mkdir -p $$(@D) 333 @mkdir -p $$(@D)
328 @$$(SILENT) || printf "$$(MSG_COMPILING_CXX) $$<" | $$(AWK_CMD) 334 @$$(SILENT) || printf "$$(MSG_COMPILING_CXX) $$<" | $$(AWK_CMD)
329 $$(eval CMD=$$(CC) -c $$($1_CXXFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP)) 335 $$(eval CMD=$$(CC) -c $$($1_CXXFLAGS) $$(INIT_HOOK_CFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
330 @$$(BUILD_CMD) 336 @$$(BUILD_CMD)
331 337
332# Assemble: create object files from assembler source files. 338# Assemble: create object files from assembler source files.