TMK support for ARM Teensies

User avatar
flabbergast

14 Oct 2015, 11:39

TL;DR: I've added an alternative to hasu's mbed code to TMK, which supports Teensy LC, 3.x. (Beta!)

Hi all,

I've added ChibiOS backend to TMK, which effectively means supporting chips that are supported by ChibiOS: pretty much all STM32 MCUs and the common Kinetis MCUs (the ones in ARM Teensies and mchck).
Note that this is a "backend", so all of hasu's powerful keyboard/mouse/etc... logic is the same as "normal" in TMK.

I consider this in beta, because it hasn't been tested beyond my own tests. Any reports (of bugs, problems, etc... and/or (less likely ;) successes) are welcome!

There is one "onekey" example for Teensy LC and 3.0, instructions here.

Caveats:
- For Teensies, what's missing is some more fancy suspend support (breathing LED, power saving, waking up PC). This is on my todo list.
- For STM32s, same as for Teensies, plus missing bootmagic support (this requires EEPROM emulation, which I haven't done yet). There is bootloader support, but it requires an extra step to set up.

Why do I do this, if hasu's already put in mbed backend, you ask? Well, I don't like the mbed SDK too much. And I think it's good to have options to try if something doesn't work.

Finally, the infinity keyboard has a chip that's supported via this route, but I don't have the infinity PCB anymore. So if anyone with one is willing to help me with testing, please PM me. (I haven't added it to the main tree yet, the keyboard/infinity is hasu's mbed implementation.)

Engicoder

14 Oct 2015, 18:45

Great work. ChibiOS is pretty nice and seems to be gaining a lot of steam as of late. Have you talked to hasu about merging you additions once they have been field tested a bit more?

User avatar
flabbergast

14 Oct 2015, 18:55

Yes, I messaged hasu (also before I worked on the kinetis support in chibios, so it was mostly STM32 support then) - he said he'd check more deeply later on. I think he's pretty busy these days with all the boards he's supposed to assemble for the ALPS buy ;)

That's one of reasons I'd like to have the code more tested on "real hardware" - it's relatively speaking a fair amount of code, so not so easy to "review", especially without previous ChibiOS background.

User avatar
0100010

15 Oct 2015, 01:26

Will have to load this....

User avatar
hasu

16 Oct 2015, 17:15

Nice work, flabbergast.

I made firmware for my Infinity 60% keyobard with chibios/tmk and I'm going to testing more. I got duplicate key registers wrongly, I'll have to debug this.
https://github.com/tmk/tmk_keyboard/tre ... ty_chibios

It took long to grasp chibios build process and configuration but after that it was not difficult, Infinity is luckily compatible to MCHCK which is already supported in chibios.

User avatar
hasu

16 Oct 2015, 18:52

hasu wrote: I got duplicate key registers wrongly, I'll have to debug this.
Fixed report size for boot protocol.

Code: Select all

diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index 382966b..619b798 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -1130,7 +1130,7 @@ void send_keyboard(report_keyboard_t *report) {
   } else
 #endif /* NKRO_ENABLE */
   { /* boot protocol */
-    usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
+    usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
     osalSysLock();
     usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
     osalSysUnlock();

User avatar
flabbergast

16 Oct 2015, 19:39

Good catch! Thanks! (I didn't know how to test the boot protocol on my machine.)

I'll take a closer look at the infinity sources later tonight.

User avatar
hasu

17 Oct 2015, 09:04

I found another problem on keyboard report transfer. Keyboard report can be missing in case of successive very fast key events. This is can be occured with key events registered by program or macro.

Before the last report transfer is finished, if send_keyboard() is called with other key event then the last report will be lost. It has to make sure that keyboard report transfer is done before begins next transfer.

I'm not sure this fix is correct or proper but it works so far at least.

Now, my Infinity works well with your chibios/tmk, mouse key and media keys also work great! Thanks.

Code: Select all

diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index 619b798..0fc2f6e 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -1121,19 +1121,24 @@ void send_keyboard(report_keyboard_t *report) {
   }
   osalSysUnlock();
 
+  bool ret;
 #ifdef NKRO_ENABLE
   if(keyboard_nkro) {  /* NKRO protocol */
     usbPrepareTransmit(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
-    osalSysLock();
-    usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT);
-    osalSysUnlock();
+    do {
+        osalSysLock();
+        ret = usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT);
+        osalSysUnlock();
+    } while (ret);
   } else
 #endif /* NKRO_ENABLE */
   { /* boot protocol */
     usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
-    osalSysLock();
-    usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
-    osalSysUnlock();
+    do {
+        osalSysLock();
+        ret = usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
+        osalSysUnlock();
+    } while (ret);
   }
   keyboard_report_sent = *report;
 }

User avatar
flabbergast

17 Oct 2015, 19:27

Thanks! Another good catch. And I'm happy that the keyboard/mouse things work. Could you also test the console, please? There might be some flushing issues there.

I've merged your commits to my tmk/chibios branch. I also added the correct jumping-to-bootloader on infinity keyboard (it's different from the Teensy way of course). The method of jumping worked on my MCHCK with the default kiibohd bootloader (compiled from github sources), but I'm not 100% sure there were no changes to the bootloader on the "production" infinities.

User avatar
hasu

18 Oct 2015, 00:00

Yes, console works nicely with hid_listen from the begining.

Thanks for the merge, and bootloader jump works great with the latest kiibohd bootloader on my Infinity 60% now. My Infinity is a prototype which has different matrix from production model, but I don't think both are distinct each other in terms of bootloader.

Really great job!

User avatar
flabbergast

18 Oct 2015, 23:22

Thanks! Good to know!

(I now also implemented the sleep LED breathing for Kinetis devices, no STM32 yet. So the most serious thing left to do (apart from testing and hunting bugs) is power saving during sleep.)

User avatar
hasu

06 Nov 2015, 00:23

Hi,
I found my Infinity60 doesn't work without hid_listen on Linux(Ubuntu 15.04), it seems to be blocked by printf() or console output. If the keyboard executes printf() when hid_listen is not available it stop working and doesn't register any key press. Disabling console function in Makefie fixes this. Strangely, on OSX and Windows it starts up without the problem.
https://github.com/tmk/tmk_keyboard/issues/266

I looked console queue and chibios code but I couldn't get any clue. Any idea?

keru

10 Nov 2015, 16:06

I got excited about that as I wanted to use an STM32 I have. But then I realized I really don't know how to add my device correctly.
I found the files I need to create, but I'm having trouble getting the board.h correctly. I seem to need to have a ld file for the board but that's past my knowledge.
The board I'm trying to use is an ebay generic STM32F103C8T6 and I'm trying to use the MAPLE-MINI and OLIMEX-P103 as an example. If anybody has pointers that would be awesome or if there is some STM32F103 chips files I can reuse.

Thanks for the great work !

User avatar
flabbergast

10 Nov 2015, 17:08

I'll have a look at this in the evening.

User avatar
flabbergast

10 Nov 2015, 23:06

@keru:
- for ld script: create the "ld" directory inside your keyboard project directory, copy chibios/os/common/ports/ARMCMx/compilers/GCC/ld/STM32F103xB.ld into it (probably rename to STM32F103x8.ld so that the name makes sense), edit it, and change "128k" to "64k" for 'flash len'. That should be the only required change.
- for board files: as you write, it's good to start with one of those you mention. These files mostly contain the startup configuration for pins, as well as clocking - so it might be worth looking at the schematics and figure out whether the crystals are the same for your board vs maple mini and/or olimex. Can't really tell more without the specifics. Also, it might help googling "your board" (or "your MCU") together with "chibios", there might be some board files out there. Finally, you can stick with "STM32F103xB" in these (since the only difference between x8 and xB that I was able to discern is flash size, which only comes in in the .ld file).
- for TMK Makefile: if you're starting with the Makefiles in one of the *_chibios directories, then the variables should be as follows: MCU_FAMILY=STM32, MCU_SERIES=STM32F1xx, MCU_LDSCRIPT=STM32F103x8 (or whatever you called the file above), MCU_STARTUP=stm32f1xx, MCU=cortex-m3, ARMV=7.
- just to make sure: you're using an external programmer for programming the MCU, right? I.e. it doesn't have some sort of bootloader, does it? (If it does, you'd need to adjust the .ld file.)

keru

11 Nov 2015, 00:28

Awesome thanks a lot, that will help, I wasn't too far in my understanding.

I tried searching for chibios + my MCU but I found just a few references that didn't help my comprehension.

The board is one like http://www.ebay.ca/itm/STM32F103C8T6-AR ... 1469482910. If the pins are the same, I can leave the CRL/CRH settings (https://github.com/mabl/ChibiOS/blob/ma ... oard.h#L89) the same ? I'm confused to what I would need to change if pins are different, specially the parts about USB, USART.

The MCU right now has the stm32duino bootloader but for this purpose I can just start with flashing over serial, but that's good to know.

Thanks again, I'll update once I try.

keru

11 Nov 2015, 03:54

I also had to change the define in mcuconf.h, not sure what should change though :)

I now got

Code: Select all

In file included from ../../tmk_core/tool/chibios/chibios/os/hal/include/usb.h:363:0,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/include/hal.h:62,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/src/hal.c:25:
../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/USBv1/usb_lld.h:115:2: error: #error "the USB driver requires a 48MHz clock"
 #error "the USB driver requires a 48MHz clock"
  ^
make: *** [build/obj/hal.o] Error 1

User avatar
flabbergast

11 Nov 2015, 16:12

Well the error is just what it says - USB requires a 48MHz clock ;) ... normally the chips have a way of generating this by dividing and/or multiplying the main MCU frequency. This probably means that the settings in mcuconf.h are not quite right. Could you share your files somewhere? I can have a look and try to make a better guess (I don't have hardware to test it unfortunately). I'll also have a look at the stm32duino bootloader, to see what needs to be done with the .ld file.

keru

11 Nov 2015, 18:32

Thanks a lot for the help. I guessed it had to do with some clock/divider/multiplier settings but couldn't figure out where it was coming from.

I'll send my files on a git repo when I can, but here is what I found in chibios/os/hal/ports/STM32/STM32F1xx/hal_lld_f103.h

Code: Select all

#define STM32_PLLSRC            STM32_PLLSRC_HSI
#define STM32_HSICLK            8000000
#define STM32_PLLCLKIN        (STM32_HSICLK / 2)
[...]
#define STM32_PLLCLKOUT             (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)

#if (STM32_USBPRE == STM32_USBPRE_DIV1P5) || defined(__DOXYGEN__)
#define STM32_USBCLK                ((STM32_PLLCLKOUT * 2) / 3)
#elif (STM32_USBPRE == STM32_USBPRE_DIV1)
#define STM32_USBCLK                STM32_PLLCLKOUT
#else
#error "invalid STM32_USBPRE value specified"
#endif

I saw that STM32_USBPRE == STM32_USBPRE_DIV1P5 is the default so I changed my mcuconf.h for the following

Code: Select all

#define STM32_PLLSRC                        STM32_PLLSRC_HSI
#define STM32_PREDIV_VALUE                  1
#define STM32_PLLMUL_VALUE                  12
#define STM32_USBPRE                        STM32_USBPRE_DIV1
now getting

Code: Select all

Compiling st_lld.c
../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/TIMv1/st_lld.c:43:2: error: #error "TIM2 is not a 32bits timer"
 #error "TIM2 is not a 32bits timer"
EDIT: got past that by adding

Code: Select all

#define CH_CFG_ST_RESOLUTION                16
Now I'm off to fix matrix.c and the GPIOS :)

EDIT2: I got it to compile after fixing pins for LED and Buttons. I'll have to try to flash it next :)

User avatar
flabbergast

11 Nov 2015, 21:01

Nice! Yea, getting these things right is sometimes a pain in the ARM world.

Flashing: As far as I've read about the stm32duino bootloader, it occupies the first 8kB of flash - so the .ld file and firmware needs to be adjusted to expect to "begin" 8kB after the beginning of flash.

However if you'd be using a ROM bootloader (don't know if this MCU has one), or an external programmer, then it should be fine.

EDIT: OK, to be more specific, moving the firmware to start 8kb after the beginning of flash, you'll need to:

1) let the MCU know the interrupt table is not where it normally is. This is achieved by setting CORTEX_VTOR_INIT, so either have

Code: Select all

#define CORTEX_VTOR_INIT 0x2000
in chconf.h, or use

Code: Select all

OPT_DEFS = -DCORTEX_VTOR_INIT=0x2000
in Makefile.

2) Let the linker know where should the code start. Change the .ld file you're using, the line with flash, to

Code: Select all

flash : org = 0x08002000, len = 56k
(and probably rename the file to make it obvious it's intended for a setup with a bootloader.

EDIT2:

3) Possibly also change the ram0 line in the .ld file; it seems that there may be a portion at the beginning that's claimed by the bootloader. Have a look at chibios/os/common/ports/ARMCMx/compilers/GCC/ld/STM32F103xE_maplemini_bootloader.ld. I'll try to read some more of stm32duino bootloader docs to see whether this is really needed.

keru

13 Nov 2015, 15:55

thanks for the help. I didn't have time to try but that makes sense.
when I look at those ld files https://github.com/rogerclarkmelbourne/ ... 1/variants they indeed seem to reduce the ram size.
there is also https://github.com/rogerclarkmelbourne/ ... bootloader for the actual bootloader.

Ok I flashed but I might have something wrong, it keeps blinking the LED and it doesn't show any HID device in my syslog/dmesg.

I might have an issue somewhere, the hex files is 63kb

Code: Select all

63K Nov 13 11:37 ch.hex

User avatar
flabbergast

13 Nov 2015, 21:09

The size might be OK - intel hex is a "wasteful" format; it's essentially a hexdump of the actual binary, with addresses and checksums. You can check the actual "binary" size with "arm-none-eabi-size ch.hex".

keru

13 Nov 2015, 22:28

Ok, so I was flashing the .hex ... sorry about that :)
Now I still have the bootloader and the board still goes in DFU when booting, but when it's done waiting I get a bunch of

Code: Select all

[24919.664171] usb 1-1.4: new full-speed USB device number 83 using xhci_hcd
[24919.664343] usb 1-1.4: Device not responding to setup address.
[24919.868466] usb 1-1.4: Device not responding to setup address.
[24920.072437] usb 1-1.4: device not accepting address 83, error -71
[24920.072488] usb 1-1-port4: unable to enumerate USB device

User avatar
flabbergast

14 Nov 2015, 10:13

I'd take this as a "good" sign - some code actually does run. However with the code and the hardware for testing, I can't tell what's going on...

keru

15 Nov 2015, 19:11

I realized my board.h was not being used but instead it was using the path '${CHIBIOS}/os/hal/boards/MAPLEMINI_STM32_F103'. That's norma,l I just copied the code from there. So I fixed it to use my custom 'boards' folder so it compiles using my pins definition, but now when compiling I get the following.

Code: Select all

In file included from ../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/USBv1/usb_lld.h:30:0,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/include/usb.h:363,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/include/hal.h:62,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/src/hal.c:25:
../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h:39:5: warning: "STM32_USB_ACCESS_SCHEME_2x16" is not defined [-Wundef]
 #if STM32_USB_ACCESS_SCHEME_2x16
     ^
../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h:81:5: warning: "STM32_USB_HAS_BCDR" is not defined [-Wundef]
 #if STM32_USB_HAS_BCDR
     ^
In file included from ../../tmk_core/tool/chibios/chibios/os/hal/include/usb.h:363:0,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/include/hal.h:62,
                 from ../../tmk_core/tool/chibios/chibios/os/hal/src/hal.c:25:
../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/USBv1/usb_lld.h:96:2: error: #error "USB not present in the selected device"
 #error "USB not present in the selected device"
  ^
../../tmk_core/tool/chibios/chibios/os/hal/ports/STM32/LLD/USBv1/usb_lld.h:414:5: warning: "STM32_USB_HAS_BCDR" is not defined [-Wundef]
 #if STM32_USB_HAS_BCDR || defined(__DOXYGEN__)
     ^
make: *** [build/obj/hal.o] Error 1

I didn't touch any of those definitions so I'm not sure why it's an issue.
If I revert and use `${CHIBIOS}/os/hal/boards/MAPLEMINI_STM32_F103` it does compile.

EDIT : it seems related to the

Code: Select all

#define STM32F103x6
in the board.h, if I leave

Code: Select all

#define STM32F103xB
it compiles.

User avatar
flabbergast

16 Nov 2015, 15:46

I think you should keep the STM32F103xB there - I didn't see the definitions for x6 in the STM32 CMSIS files. Your chip is sufficiently "the same" as xB (except for the flash and RAM sizes). You can have a look at the defines in chibios/os/ext/CMSIS/ST directory - those are headers from ST I think.

keru

16 Nov 2015, 16:58

I read some code that was refering to x6 that's why I tried. But now with xB it compiles.

I must have some incorrect pin settings since I don't see anything in dmesg, except the board showing the usual 'maple leaf' information but no HID information. Might have to do with the USB pins or maybe something else, still searching :)

I also have a Maple Mini F103 pin compatible with the maple mini, it compiles and all, but with this one does show the "[24920.072437] usb 1-1.4: device not accepting address 83, error -71" error.

I'll continue to look around, thanks for the help.

User avatar
flabbergast

16 Nov 2015, 18:57

Ah well, I guess I should just get one of these boards, they're dirt cheap. Except the few weeks wait from China.

BTW, the pins on the opposite side to the USB socket seem to be for hardware debugging, that tends to be *very* helpful with these chips. (I think that's the best thing on ARMs compared to AVR or other 8bit platforms - hardware debugging...)

keru

16 Nov 2015, 19:43

I would send one to you, but that would cost more than buying from china.
I didn't look how to use it, and I think I need some tool to do so.

User avatar
flabbergast

16 Nov 2015, 20:24

THanks for the offer, but getting it from ebay is indeed cheaper than postage ;)

Debugging - yes you need an extra device, but you can get a "st-link v2" from ebay for £2 from china. A good investment if you intend to play with ARMs if you ask me.

Post Reply

Return to “Workshop”