TMK support for ARM Teensies


16 Nov 2015, 23:04

here is my attempt to make it work


19 Nov 2015, 22:02

keru, I have a Chinese maple mini clone (Baite) and have been trying for more than a month to get it to work as the controller for a phantom. I had been trying to use libopencm3 and had problems, so I was glad to find flabbergast's work on chibios support for tmk a week or two ago.

I do have a working tmk_onekey for the maple mini clone, but I had to comment out CONSOLE_ENABLE = yes in the makefile, or it wouldn't enumerate and I'd get the "error -71" like you are getting.

Actually, I just tried it again, and now I it enumerates with CONSOLE_ENABLE=yes, but it won't output characters when I press the button... It does output characters (I have it set to output KC_A in keymap_plain.c) when I comment out CONSOLE_ENABLE=yes.

So, maybe try commenting out all the xxx_ENABLE options except NKRO in the makefile and see if it will enumerate.

Also, the maple-mini clone that I have has 128K flash (-0x5000 for the default bootloader) and 20K ram (-0x0C00 used by the bootloader), as it has a STM32F013RBT6, though the the chibios maple mini files all seem to be set up for a STM32F103xE, so if you try the mini again, be sure to create your own LDSCRIPT with the proper flash and ram sizes.


20 Nov 2015, 23:48

@mfr000 nice I have a Baite too, I'll try again with removing the _ENABLE.
For the LDSCRIPT and memory settings, I did indeed configure those with -0x5000 and -0x0c00.
Would you mind sharing your onekey for baite maple mini clone somewhere ?
Thanks a lot.


23 Nov 2015, 06:31

keru, the onekey code for the maple-mini is here: ... ini_onekey


23 Nov 2015, 06:45

Awesome !
Thanks a lot, I'll have to wait before I can try, but I'll keep you posted.

User avatar

30 Nov 2015, 18:46

All right, I received that STM32F103C8T6 board. keru - you've actually had it fine, i.e. it works for me on mac, more-less. I've added that example to my tree on github.

About the more-less: I'm on a mac, and so no problem with CONSOLE. Need to investigate that some more...

And now the main catch: I couldn't make it work with stm32duino bootloader. I think the problem is caused by the hardware - there's no pull-up on the D+ line, and I don't know how to signal USB disconnect/reset to the computer (yet). This means (I think) that even after the bootloader jumps to the TMK code, the device stays enumerated as stm32duino bootloader (and so TMK USB code doesn't work). Similarly, sometimes I need to disconnect and reconnect the board for the USB to work properly. I'll try to fiddle with the D+ and D- lines in software, maybe something will work.

However, when no bootloader is used (i.e. the firmware is uploaded to the board either using the serial bootloader in ROM, or via SWD), it works fine for me.

User avatar

03 Dec 2015, 10:49

I've pushed a couple more commits to my TMK/chibios branch. Now it seems to work (modulo the console problem) on the generic STM32F103C8T6 board both with the stm32duino bootloader and without it; as well as on a maple mini clone (with the standard maple bootloader). It's all in stm32_f103_onekey example, selectable in the Makefile.

I'm actually kinda happy that I finally have a reproducible instance of the console problem, on a board that I can run debugger on. Just need to dig in (it crashes my virtualboxed linux instance, so the actual debugging may get interesting).


03 Dec 2015, 19:35

That's great. Thanks a lot for the help, I won't have time soon to try it, but I'm glad that works. Now I have more purpose for my boards :)
Thanks again !


05 Dec 2015, 04:46

Hi !
I've been able to flash both the generic board and the maple mini clone with their respective bootloaders.
I see both as follow yeah \o/

Code: Select all

[ 1896.773971] input: TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/0003:FEED:6464.0013/input/input33
[ 1896.827221] hid-generic 0003:FEED:6464.0013: input,hidraw2: USB HID v1.11 Keyboard [TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test] on usb-0000:00:14.0-1/input0
[ 1896.828416] input: TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.1/0003:FEED:6464.0014/input/input34
[ 1896.883275] hid-generic 0003:FEED:6464.0014: input,hidraw3: USB HID v1.11 Mouse [TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test] on usb-0000:00:14.0-1/input1
[ 1896.884617] input: TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.3/0003:FEED:6464.0015/input/input35
[ 1896.939217] hid-generic 0003:FEED:6464.0015: input,hidraw4: USB HID v1.11 Device [TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test] on usb-0000:00:14.0-1/input3
[ 1896.939975] input: TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.4/0003:FEED:6464.0016/input/input36
[ 1896.995246] hid-generic 0003:FEED:6464.0016: input,hidraw5: USB HID v1.11 Keyboard [TMK \xffffffc3\xffffff86\xffffff86 ChibiOS TMK test] on usb-0000:00:14.0-1/input4
Now, small question : how do I test it ? I don't seem to find what button to press/input to set low. It seems to be the port B pin 8 but I don't get anything from it.

EDIT: Aha ! I figured out the button was mapped to caps lock (which does backspace on my colemak layout double trouble :) ), it works on the maple mini clone, didn't try with the generic board yet. Thanks !
Thanks again for the help, it's greatly appreciated !
Last edited by keru on 08 Dec 2015, 04:28, edited 1 time in total.


05 Dec 2015, 06:04

I'm going to do the atreus keyboard next, should I send a pull request to you for the chibios branch once its done ?

User avatar

08 Dec 2015, 13:31

Great work, flabbergast! Before I design my next keyboard, I'll take a look at your code and pick one of the MCUs that you support (I haven't got the time to port to another device, even within the same family). I hope the KL27x is going to run out of the box by then, being my current favourite.

User avatar

27 Dec 2015, 09:51

don't know how this slipped off my radar!


30 Dec 2015, 05:36

thanks again for the great job. I got my atreus working, but now I'm trying to add PS2/Trackpoint support and running into an issue.
following this thread ... msg1291412 I added the lines to the Makefile but I get the following when compiling :

Code: Select all

../../tmk_core/common/keyboard.c:37:26: fatal error: ps2_mouse.h: No such file or directory
 #   include "ps2_mouse.h"
I also tried to edit the file to have a rule similar to the one in the without avr specific files, with the same results.

Any clue to what I should change/add to have the PS2 support ?

Thanks again.

User avatar

30 Dec 2015, 10:43

Right. This is not implemented yet. To fix the include problem, you need to edit tmk_core/tool/chibios/ and add $(TMK_DIR)/protocol to INCDIR (I'll commit that in a bit). {Backstory: I wanted to use chibios' make system as vanilla as possible, so that it's "easier" to upgrade to newer chibioses, but that also means that some complications like this crop up, interfacing with the (already relatively complicated) TMK makefile system.}

The system is not integrated yet; the most straightforward way to add this to an existing keyboard with chibios backend should be to add

Code: Select all

SRC += $(TMK_DIR)/protocol/ps2_busywait.c
SRC += $(TMK_DIR)/protocol/ps2_io_chibios.c
to your Makefile, *before* the last two "include" lines. I haven't done ps2_io_chibios.c yet (completely missing); that's the "communicating with the hardware" part of the protocol. I'll do that in a while - but you can give it a shot yourself - there are _io_avr and _io_mbed files that should be quite helpful for implementing this.


30 Dec 2015, 16:19

thank, I'm going to try.
I already have an issue, it seems I also need ps2_mouse.c but it refers to some avr libraries. Do I need to port that too ?
And I'm having a basic beginner issue : it seems I should use _wait_ms instead of _delay_ms, so I added #include "wait.h" but I still get

Code: Select all

../../tmk_core/protocol/ps2_mouse.c: In function 'ps2_mouse_init':
../../tmk_core/protocol/ps2_mouse.c:43:5: warning: implicit declaration of function '_wait_ms' [-Wimplicit-function-declaration]
     _wait_ms(1000);    // wait for powering up

User avatar

30 Dec 2015, 16:57

Yep, it should use wait_ms(...) (without the first underscore). There are a couple of things like this still left in TMK - I haven't looked at any code in tmk_core/protocol yet at all, so you may come across a couple of issues like this also in other files from protocol/*. {On AVR, wait_ms is an alias for _delay_ms; for chibios it's chThdSleepMilliseconds.}


31 Dec 2015, 02:55

ok thanks after commenting the avr delay.h and renaming _delay_ms to wait_ms, it compiles.
I didn't solder the trackpoint yet, but is there anything that should be fixed before or I can ignore the warnings ?

Code: Select all

Compiling ps2_mouse.c
../../tmk_core/protocol/ps2_mouse.c: In function 'ps2_mouse_init':
../../tmk_core/protocol/ps2_mouse.c:39:13: warning: variable 'rcv' set but not used [-Wunused-but-set-variable]
     uint8_t rcv;
../../tmk_core/protocol/ps2_mouse.c: In function 'ps2_mouse_task':
../../tmk_core/protocol/ps2_mouse.c:86:72: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
         if (debug_mouse) print("ps2_mouse: fail to get mouse packet
../../tmk_core/protocol/ps2_mouse.c:117:27: warning: comparison is always true due to limited range of data type [-Wtype-limits]
                           ((!X_IS_OVF && 0 <= mouse_report.x && mouse_report.x <= 127) ? mouse_report.x : 127);
../../tmk_core/protocol/ps2_mouse.c:120:27: warning: comparison is always true due to limited range of data type [-Wtype-limits]
                           ((!Y_IS_OVF && 0 <= mouse_report.y && mouse_report.y <= 127) ? mouse_report.y : 127);
Compiling ps2_busywait.c
Compiling ps2_io_chibios.c
Compiling host.c
Compiling keyboard.c
Compiling action.c
../../tmk_core/common/action.c: In function 'debug_event':
../../tmk_core/common/action.c:539:29: warning: unused parameter 'event' [-Wunused-parameter]
 void debug_event(keyevent_t event)
Compiling action_tapping.c
../../tmk_core/common/action_tapping.c:327:6: warning: 'waiting_buffer_has_anykey_pressed' defined but not used [-Wunused-function]
 bool waiting_buffer_has_anykey_pressed(void)
Compiling action_macro.c
Compiling action_layer.c
Compiling action_util.c
Compiling keymap.c
../../tmk_core/common/keymap.c: In function 'action_for_key':
../../tmk_core/common/keymap.c:136:14: warning: 'action.code' may be used uninitialized in this function [-Wmaybe-uninitialized]
     action_t action;
I flashed it but it interferes with my keys now. A simple keypress doesn't do anything, but if I keep the key pressed for maybe one second, I get a lot of repeat. As if it was buffering this key for one second and sending them all at once. Any idea ?


31 Dec 2015, 05:19

It seems to be due to some combination of wait/WAIT and data/try in ps2_busywait.c
should those block the rest of the firmware ?

User avatar

31 Dec 2015, 08:58

The warnings are mainly because the default warnings asked for in chibios makefiles are more stringent than in AVR makefiles. It does make sense to have a look at those places, but they shouldn't be showstoppers.

Delays - perhaps someone with more traditional PS2/TMK/AVR knowledge could chime in - to me they look like the behaviour would be the same on AVRs. Busywait - going just by the name now - does probably do that: busy wait ;)

Porting the interrupt version to chibios is a bit more involved.


31 Dec 2015, 15:36

Yeah, I figured out that busywait was blocking, I was hoping that some magic threading would let the rest work while waiting :)

I looked for interrupts, but that's to complicated for my knowledge. I was hoping that USART/UART would be an easier alternative, but I still need to read a lot of things and figure out the settings.

User avatar

31 Dec 2015, 15:48

Hm. The wait_ms in chibios is actually not "blocking", i.e. the kernel can switch to other waiting threads during the waits. The problem is that TMK was not written in a way that could use this functionality: there's only one thread which calls keyboard_task and mouse_task (or whatever _task) alternately, so if one of those blocks (like ps2_busywait), it blocks the keyboard stuff. That's quite normal on AVRs, where there's no fancy RTOS kernel to manage things :)

I think it's possible to rewrite the chibios backend a bit, so that the ps2 stuff would be moved to a separate thread though... I intend to have a look at those things, but it may take a while. Sorry. I'll probably try to port the ps2_interrupt stuff before that - it shouldn't be complicated, it just requires knowing how to work with pin interrupts within chibios (it's the EXT driver).


31 Dec 2015, 15:52

ha ok thanks for the details, that makes sense regarding the AVRs.
I'll look at the interrupts in that case, thanks again !

User avatar

31 Dec 2015, 15:56

I had to recently figure the pin interrupts out for another "project", the code is here (just ignore all the USB stuff; the EXT things are happening in the wiegand section). The way it's used that you configure the EXT driver by telling it which pins should trigger which callback functions, and then just write the callback functions.


01 Jan 2016, 06:02

Thanks for that, I'll try to get something.
So what I have on the list is :
- replace the ISR(PS2_INT_VECT) with my callback function (like extcb0 in your code)
- configure the interrupts and callback using EXTConfig
- initialize my interrupt pin as PAL_MODE_INPUT_PULLUP

Regarding your code, do I need to setup anything about the _PULSE_ settings ?

And in the AVR code, there is sreg = SREG and then SREG = sreg, do I need something similar for chibios ?

User avatar

01 Jan 2016, 12:27

Exactly. Nice work!

You can ignore all the pulse stuff from my code (it has to do with the protocol I'm dealing with in that code, not the interrupt mechanism). SREG in AVRs is the status register; the point is that on AVRs there's no layer between the TMK code and the processor itself, so the interrupt code is exactly what will happen when an interrupt occurs. So the code has to take care of not changing the processor status (so that when the interrupt routine finishes and the control goes back to the "normal" code, it can continue without any surprises). That's why SREG is saved at the beginning of the interrupt code and restored back at the end. On chibios, the RTOS layer is between the processor and your code; and it takes care of all of that (and more). So effectively a RTOS hides a lot of low level stuff, for the price of a bit of CPU time+memory+flash.


02 Jan 2016, 04:58

Thanks, getting closer :-)

Now I have an issue that I don't really get, maybe you could help ?

Code: Select all

../../tmk_core/protocol/ps2_interrupt_chibios.c: In function 'extcb0':
../../tmk_core/protocol/ps2_interrupt_chibios.c:244:20: error: invalid storage class for function 'pbuf_enqueue'
 static inline void pbuf_enqueue(uint8_t data)
I added a prototype for the extcb0 function and if I change all the functions like pbuf_enqueue from 'static inline <type> <function>' to only '<type> <function>' it seems happier, but I don't know what this implies.

I got that 'inline' is just a clue for the compiler to try to 'inline' the function where it's used instead of calling it, and static would have impact on the scope, but if I keep either, it complains.

EDIT: my bad, it was an unclosed bracket, now I'm getting closer, but seems I have undefined references to things I thought I '#included'

Code: Select all

/tmp/ccHM70AS.ltrans1.ltrans.o: In function `pbuf_dequeue':
../../tmk_core/protocol/ps2_interrupt_chibios.c:281: undefined reference to `cli'
/tmp/ccHM70AS.ltrans2.ltrans.o: In function `ps2_host_send':
../../tmk_core/protocol/ps2_interrupt_chibios.c:108: undefined reference to `extChannelDisable'
../../tmk_core/protocol/ps2_interrupt_chibios.c:155: undefined reference to `extChannelEnable'
../../tmk_core/protocol/ps2_interrupt_chibios.c:152: undefined reference to `EXTD1'
/tmp/ccHM70AS.ltrans3.ltrans.o: In function `halInit':
../../tmk_core/tool/chibios/chibios/os/hal/src/hal.c:77: undefined reference to `extInit'
/tmp/ccHM70AS.ltrans3.ltrans.o: In function `ps2_host_init':
../../tmk_core/protocol/ps2_interrupt_chibios.c:97: undefined reference to `extStart'
collect2: error: ld returned 1 exit status
make: *** [build/ch.elf] Error 1
EDIT 2 : I got that fixed by setting HAL_USE_EXT correctly in halconf.h instead of putting it in the mcuconf.h. For cli() I think it is to disable the interrupts, but I thought that was what the PS2_INT_ON/OFF macros were for ...


02 Jan 2016, 06:50

If I use busywait or interrupts, it seems my issue comes from

Code: Select all

    rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
in the ps2_mouse_task in ps2_mouse.c
I'm trying to debug but I can't get the hid_listen to see my keyboard.

EDIT : I got some debugging, using 'sudo hid_listen' and adding -DDEBUG

I can see that matrix_scan and ps2_mouse_task are called one after the other. I think I'm missing something between ps2_io_chibios.c ps2_mouse.c and ps2_interrupt_chibios.c ...

The interrupt callback doesn't seem to be triggered so it shouldn't be the issue.

I'll push my code somewhere when I can. Meanwhile if anybody has something working, I'd be glad to test it :-)


05 Jan 2016, 18:40

Hi, sorry, me again ...
I couldn't make interrupts run smoothly but I've been able to run ps2 busywait and keyboard using threads, I'll have yet to try the ps2 but the debug works.

I've added that in main.c

Code: Select all

/* ps2 mouse thread */
static THD_WORKING_AREA(WA_ps2_mouse, 128);
static THD_FUNCTION(ps2_mouse_thr, arg) {
  print("running mouse thread");
  while(true) {

int main(void) {
chThdCreateStatic(WA_ps2_mouse, sizeof(WA_ps2_mouse), NORMALPRIO, ps2_mouse_thr, NULL);
I also had to remove the ps2_mouse_task from the keyboard_task.

I moved the keyboard loop into a thread too, but it didn't work. I realized it was because the main loop didn't have something stopping it from ending, so I add a while(true).

I still have some lag though, but it's getting better.
EDIT the lag seemed due to the debug, now it seems OK. I'll have to try connecting my trackpoint next.


07 Jan 2016, 00:08

Good evening all, just curious if any of you have attempted compiling on a Windows box, I've been running for a couple of hours now and it seems like error after error, I fix one, another appears...

I'm by no means versed in ARM dev so I've struggled to keep track with this thread. I'm wondering if it'll be less painfull to stand-up a Linux vm to perform the make/build etc..

As always any assistance appreciated :)



07 Jan 2016, 03:29

Hi Nic,
Nope I never tried, I don't even have a windows box :)
In order to compile you have to :
1. checkout flabbergast's repository at the chibios branch
2. clone chibios (I did it using into tmk_core/tool/chibios/chibios
3. configure stuff in your keyboard project, you can get started using the stm32_f103_onekey project

What are your errors/issues ?
Are you able to compile TMK for AVRs using the main repository, or do you also have issues ?
What board are you trying to compile for ?

Post Reply

Return to “Workshop”