qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

serial.md (18353B)


      1 # 'serial' Driver
      2 
      3 The Serial driver powers the [Split Keyboard](../features/split_keyboard) feature. Several implementations are available that cater to the platform and capabilities of MCU in use. Note that none of the drivers support split keyboards with more than two halves.
      4 
      5 | Driver                                  | AVR                | ARM                | Connection between halves                                                                     |
      6 | --------------------------------------- | ------------------ | ------------------ | --------------------------------------------------------------------------------------------- |
      7 | [Bitbang](#bitbang)                     | :heavy_check_mark: | :heavy_check_mark: | Single wire communication. One wire is used for reception and transmission.                   |
      8 | [USART Half-duplex](#usart-half-duplex) |                    | :heavy_check_mark: | Efficient single wire communication. One wire is used for reception and transmission.         |
      9 | [USART Full-duplex](#usart-full-duplex) |                    | :heavy_check_mark: | Efficient two wire communication. Two distinct wires are used for reception and transmission. |
     10 
     11 ::: tip
     12 Serial in this context should be read as **sending information one bit at a time**, rather than implementing UART/USART/RS485/RS232 standards.
     13 :::
     14 
     15 ## Bitbang
     16 
     17 This is the Default driver, absence of configuration assumes this driver. It works by [bit banging](https://en.wikipedia.org/wiki/Bit_banging) a GPIO pin using the CPU. It is therefore not as efficient as a dedicated hardware peripheral, which the Half-duplex and Full-duplex drivers use.
     18 
     19 ::: warning
     20 On ARM platforms the bitbang driver causes connection issues when using it together with the bitbang WS2812 driver. Choosing alternate drivers for both serial and WS2812 (instead of bitbang) is strongly recommended.
     21 :::
     22 
     23 ### Pin configuration
     24 
     25 ```
     26   LEFT                      RIGHT
     27 +-------+      SERIAL     +-------+
     28 |   SSP |-----------------| SSP   |
     29 |       |       VDD       |       |
     30 |       |-----------------|       |
     31 |       |       GND       |       |
     32 |       |-----------------|       |
     33 +-------+                 +-------+
     34 ```
     35 
     36 One GPIO pin is needed for the bitbang driver, as only one wire is used for receiving and transmitting data. This pin is referred to as the `SOFT_SERIAL_PIN` (SSP) in the configuration. A TRS or USB cable provides enough conductors for this driver to function.
     37 
     38 ### Setup
     39 
     40 To use the bitbang driver follow these steps to activate it.
     41 
     42 1. Change the `SERIAL_DRIVER` to `bitbang` in your keyboards `rules.mk` file:
     43 
     44 ```make
     45 SERIAL_DRIVER = bitbang
     46 ```
     47 
     48 2. Configure the GPIO pin of your keyboard via the `config.h` file:
     49 
     50 ```c
     51 #define SOFT_SERIAL_PIN D0  // or D1, D2, D3, E6
     52 ```
     53 
     54 3. On ARM platforms you must turn on ChibiOS PAL callbacks:
     55 
     56 ```c
     57 #pragma once
     58 
     59 #define PAL_USE_CALLBACKS TRUE // [!code focus]
     60 
     61 #include_next <halconf.h>
     62 ```
     63 
     64 ## USART Half-duplex
     65 
     66 Targeting ARM boards based on ChibiOS, where communication is offloaded to a USART hardware device that supports Half-duplex operation. The advantages over bitbanging are fast, accurate timings and reduced CPU usage. Therefore it is advised to choose Half-duplex over Bitbang if MCU is capable of utilising Half-duplex, and Full-duplex can't be used instead (e.g. lack of available GPIO pins, or incompatible PCB design).
     67 
     68 ### Pin configuration
     69 
     70 ```
     71   LEFT                      RIGHT
     72 +-------+  |           |  +-------+
     73 |       |  R           R  |       |
     74 |       |  |   SERIAL  |  |       |
     75 |    TX |-----------------| TX    |
     76 |       |       VDD       |       |
     77 |       |-----------------|       |
     78 |       |       GND       |       |
     79 |       |-----------------|       |
     80 +-------+                 +-------+
     81 ```
     82 
     83 Only one GPIO pin is needed for the Half-duplex driver, as only one wire is used for receiving and transmitting data. This pin is referred to as the `SERIAL_USART_TX_PIN` in the configuration. Ensure that the pin chosen for split communication can operate as the TX pin of the contoller's USART peripheral. A TRS or USB cable provides enough conductors for this driver to function. As the split connection is configured to operate in open-drain mode, an **external pull-up resistor is needed to keep the line high**. Resistor values of 1.5kΩ to 8.2kΩ are known to work.
     84 
     85 ::: warning
     86 ***Note:*** A pull-up resistor isn't required for RP2040 controllers configured with PIO subsystem.
     87 :::
     88 
     89 ### Setup
     90 
     91 To use the Half-duplex driver follow these steps to activate it. If you target the Raspberry Pi RP2040 PIO implementation, start at step 2.
     92 
     93 1. Change the `SERIAL_DRIVER` to `usart` in your keyboards `rules.mk` file:
     94 
     95 ```make
     96 SERIAL_DRIVER = usart
     97 ```
     98 
     99 Skip to step 3.
    100 
    101 2. (RP2040 + PIO only!) Change the `SERIAL_DRIVER` to `vendor` in your keyboards `rules.mk` file:
    102 
    103 ```make
    104 SERIAL_DRIVER = vendor
    105 ```
    106 
    107 3. Configure the hardware of your keyboard via the `config.h` file:
    108 
    109 ```c
    110 #define SERIAL_USART_TX_PIN B6     // The GPIO pin that is used split communication.
    111 ```
    112 
    113 For STM32 MCUs several GPIO configuration options can be changed as well. See the section ["Alternate Functions for selected STM32 MCUs"](#alternate-functions-for-selected-stm32-mcus).
    114 
    115 ```c
    116 #define USART1_REMAP               // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
    117 #define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
    118 ```
    119 
    120 4. Decide either for `SERIAL`, `SIO`, or `PIO` subsystem. See section ["Choosing a driver subsystem"](#choosing-a-driver-subsystem).
    121 
    122 ## USART Full-duplex
    123 
    124 Targeting ARM boards based on ChibiOS where communication is offloaded to an USART hardware device. The advantages over bitbanging are fast, accurate timings and reduced CPU usage; therefore it is advised to choose this driver over all others where possible. Due to its internal design Full-duplex is slightly more efficient than the Half-duplex driver, but Full-duplex should be primarily chosen if Half-duplex operation is not supported by the controller's USART peripheral.
    125 
    126 ### Pin configuration
    127 
    128 ```
    129   LEFT                      RIGHT
    130 +-------+                 +-------+
    131 |       |      SERIAL     |       |
    132 |    TX |-----------------| RX    |
    133 |       |      SERIAL     |       |
    134 |    RX |-----------------| TX    |
    135 |       |       VDD       |       |
    136 |       |-----------------|       |
    137 |       |       GND       |       |
    138 |       |-----------------|       |
    139 +-------+                 +-------+
    140 ```
    141 
    142 Two GPIO pins are needed for the Full-duplex driver, as two distinct wires are used for receiving and transmitting data. The pin transmitting data is the `TX` pin and refereed to as the `SERIAL_USART_TX_PIN`, the pin receiving data is the `RX` pin and refereed to as the `SERIAL_USART_RX_PIN` in this configuration. Please note that `TX` pin of the master half has to be connected with the `RX` pin of the slave half and the `RX` pin of the master half has to be connected with the `TX` pin of the slave half! Usually this pin swap has to be done outside of the MCU e.g. with cables or on the PCB. Some MCUs like the STM32F303 used on the Proton-C allow this pin swap directly inside the MCU. A TRRS or USB cable provides enough conductors for this driver to function.
    143 
    144 To use this driver the USART peripherals `TX` and `RX` pins must be configured with the correct Alternate-functions. If you are using a Proton-C development board everything is already setup, same is true for STM32F103 MCUs. For MCUs which are using a modern flexible GPIO configuration you have to specify these by setting `SERIAL_USART_TX_PAL_MODE` and `SERIAL_USART_RX_PAL_MODE`. Refer to the corresponding datasheets of your MCU or find those settings in the section ["Alternate Functions for selected STM32 MCUs"](#alternate-functions-for-selected-stm32-mcus).
    145 
    146 ### Setup
    147 
    148 To use the Full-duplex driver follow these steps to activate it. If you target the Raspberry Pi RP2040 PIO implementation, start at step 2
    149 
    150 1. Change the `SERIAL_DRIVER` to `usart` in your keyboards `rules.mk` file:
    151 
    152 ```make
    153 SERIAL_DRIVER = usart
    154 ```
    155 
    156 Skip to step 3
    157 
    158 2. (RP2040 + PIO only!) Change the `SERIAL_DRIVER` to `vendor` in your keyboards `rules.mk` file:
    159 
    160 ```make
    161 SERIAL_DRIVER = vendor
    162 ```
    163 
    164 3. Configure the hardware of your keyboard via the `config.h` file:
    165 
    166 ```c
    167 #define SERIAL_USART_FULL_DUPLEX   // Enable full duplex operation mode.
    168 #define SERIAL_USART_TX_PIN B6     // USART TX pin
    169 #define SERIAL_USART_RX_PIN B7     // USART RX pin
    170 ```
    171 
    172 For STM32 MCUs several GPIO configuration options, including the ability for `TX` to `RX` pin swapping, can be changed as well. See the section ["Alternate Functions for selected STM32 MCUs"](#alternate-functions-for-selected-stm32-mcus).
    173 
    174 ```c
    175 #define SERIAL_USART_PIN_SWAP      // Swap TX and RX pins if keyboard is master halve. (Only available on some MCUs)
    176 #define USART1_REMAP               // Remap USART TX and RX pins on STM32F103 MCUs, see table below.
    177 #define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
    178 ```
    179 
    180 4. Decide either for `SERIAL`, `SIO`, or `PIO` subsystem. See section ["Choosing a driver subsystem"](#choosing-a-driver-subsystem).
    181 
    182 ## Choosing a driver subsystem
    183 
    184 ### The `SERIAL` driver
    185 
    186 The `SERIAL` Subsystem is supported for the majority of ChibiOS MCUs and should be used whenever supported. Follow these steps in order to activate it:
    187 
    188 1. Enable the SERIAL subsystem in the ChibiOS HAL.
    189 
    190    Add the following to your keyboard's `halconf.h`, creating it if necessary:
    191 
    192    ```c
    193    #pragma once
    194 
    195    #define HAL_USE_SERIAL TRUE // [!code focus]
    196 
    197    #include_next <halconf.h>
    198    ```
    199 
    200 2. Activate the USART peripheral that is used on your MCU. The shown example is for an STM32 MCU, so this will not work on MCUs by other manufacturers. You can find the correct names in the `mcuconf.h` files of your MCU that ship with ChibiOS.
    201 
    202    Add the following to your keyboard's `mcuconf.h`, creating it if necessary:
    203 
    204    ```c
    205    #pragma once
    206 
    207    #include_next <mcuconf.h>
    208 
    209    #undef STM32_SERIAL_USE_USARTn // [!code focus]
    210    #define STM32_SERIAL_USE_USARTn TRUE // [!code focus]
    211    ```
    212 
    213    Where *n* matches the peripheral number of your selected USART on the MCU.
    214 
    215 3. Override the default USART `SERIAL` driver if you use a USART peripheral that does not belong to the default selected `SD1` driver. For instance, if you selected `STM32_SERIAL_USE_USART3` the matching driver would be `SD3`.
    216 
    217    Add the following to your keyboard's `config.h`:
    218 
    219    ```c
    220    #define SERIAL_USART_DRIVER SD3
    221    ```
    222 
    223 ### The `SIO` driver
    224 
    225 The `SIO` Subsystem was added to ChibiOS with the 21.11 release and is only supported on selected MCUs. It should only be chosen when the `SERIAL` subsystem is not supported by your MCU.
    226 
    227 Follow these steps in order to activate it:
    228 
    229 1. Enable the SIO subsystem in the ChibiOS HAL.
    230 
    231    Add the following to your keyboard's `halconf.h`, creating it if necessary:
    232 
    233    ```c
    234    #pragma once
    235 
    236    #define HAL_USE_SIO TRUE // [!code focus]
    237 
    238    #include_next <halconf.h>
    239    ```
    240 
    241 2. Activate the USART peripheral that is used on your MCU. The shown example is for an STM32 MCU, so this will not work on MCUs by other manufacturers. You can find the correct names in the `mcuconf.h` files of your MCU that ship with ChibiOS.
    242 
    243    Add the following to your keyboard's `mcuconf.h`, creating it if necessary:
    244 
    245    ```c
    246    #pragma once
    247 
    248    #include_next <mcuconf.h>
    249 
    250    #undef STM32_SIO_USE_USARTn // [!code focus]
    251    #define STM32_SIO_USE_USARTn TRUE // [!code focus]
    252    ```
    253 
    254    Where *n* matches the peripheral number of your selected USART on the MCU.
    255 
    256 3. Override the default USART `SIO` driver if you use a USART peripheral that does not belong to the default selected `SIOD1` driver. For instance, if you selected `STM32_SERIAL_USE_USART3` the matching driver would be `SIOD3`.
    257 
    258    Add the following to your keyboard's `config.h`:
    259 
    260    ```c
    261    #define SERIAL_USART_DRIVER SIOD3
    262    ```
    263 
    264 ### The `PIO` driver
    265 
    266 The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using an integrated PIO peripheral and is therefore only available on this MCU. Because of the flexible nature of PIO peripherals, **any** GPIO pin can be used as a `TX` or `RX` pin. Half-duplex and Full-duplex operation modes are fully supported with this driver. Half-duplex uses the built-in pull-ups and GPIO manipulation of the RP2040 to drive the line high by default, thus an external pull-up resistor **is not required**.
    267 
    268 Optionally, the PIO peripheral utilized for split communication can be changed with the following define in config.h:
    269 ```c
    270 #define SERIAL_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the Serial implementation uses the PIO0 peripheral
    271 ```
    272 
    273 The Serial PIO program uses 2 state machines, 13 instructions and the complete interrupt handler of the PIO peripheral it is running on.
    274 
    275 ## Advanced Configuration
    276 
    277 There are several advanced configuration options that can be defined in your keyboards `config.h` file:
    278 
    279 ### Baudrate
    280 
    281 If you're having issues or need a higher baudrate with serial communication, you can change the baudrate which in turn controls the communication speed for serial. You want to lower the baudrate if you experience failed transactions.
    282 
    283 ```c
    284 #define SELECT_SOFT_SERIAL_SPEED n
    285 ```
    286 
    287 Where *n* is one of:
    288 
    289 | Speed | Bitbang                    | Half-duplex and Full-duplex |
    290 | ----- | -------------------------- | --------------------------- |
    291 | `0`   | 189000 baud (experimental) | 460800 baud                 |
    292 | `1`   | 137000 baud (default)      | 230400 baud (default)       |
    293 | `2`   | 75000 baud                 | 115200 baud                 |
    294 | `3`   | 39000 baud                 | 57600 baud                  |
    295 | `4`   | 26000 baud                 | 38400 baud                  |
    296 | `5`   | 20000 baud                 | 19200 baud                  |
    297 
    298 Alternatively you can specify the baudrate directly by defining `SERIAL_USART_SPEED`.
    299 
    300 ### Timeout
    301 
    302 This is the default time window in milliseconds in which a successful communication has to complete. Usually you don't want to change this value. But you can do so anyways by defining an alternate one in your keyboards `config.h` file:
    303 
    304 ```c
    305 #define SERIAL_USART_TIMEOUT 20    // USART driver timeout. default 20
    306 ```
    307 
    308 ## Troubleshooting
    309 
    310 If you're having issues with serial communication, you can enable debug messages that will give you insights which part of the communication failed. The enable these messages add to your keyboards `config.h` file:
    311 
    312 ```c
    313 #define SERIAL_DEBUG
    314 ```
    315 
    316 ::: tip
    317 The messages will be printed out to the `CONSOLE` output. For additional information, refer to [Debugging/Troubleshooting QMK](../faq_debug).
    318 :::
    319 
    320 ## Alternate Functions for selected STM32 MCUs
    321 
    322 Pins for USART Peripherals with
    323 
    324 ### STM32F303 / Proton-C [Datasheet](https://www.st.com/resource/en/datasheet/stm32f303cc.pdf)
    325 
    326 Pin Swap available: :heavy_check_mark:
    327 
    328 | Pin        | Function | Mode |
    329 | ---------- | -------- | ---- |
    330 | **USART1** |          |      |
    331 | PA9        | TX       | AF7  |
    332 | PA10       | RX       | AF7  |
    333 | PB6        | TX       | AF7  |
    334 | PB7        | RX       | AF7  |
    335 | PC4        | TX       | AF7  |
    336 | PC5        | RX       | AF7  |
    337 | PE0        | TX       | AF7  |
    338 | PE1        | RX       | AF7  |
    339 | **USART2** |          |      |
    340 | PA2        | TX       | AF7  |
    341 | PA3        | RX       | AF7  |
    342 | PA14       | TX       | AF7  |
    343 | PA15       | RX       | AF7  |
    344 | PB3        | TX       | AF7  |
    345 | PB4        | RX       | AF7  |
    346 | PD5        | TX       | AF7  |
    347 | PD6        | RX       | AF7  |
    348 | **USART3** |          |      |
    349 | PB10       | TX       | AF7  |
    350 | PB11       | RX       | AF7  |
    351 | PC10       | TX       | AF7  |
    352 | PC11       | RX       | AF7  |
    353 | PD8        | TX       | AF7  |
    354 | PD9        | RX       | AF7  |
    355 
    356 ### STM32F072 [Datasheet](https://www.st.com/resource/en/datasheet/stm32f072c8.pdf)
    357 
    358 Pin Swap available: :heavy_check_mark:
    359 
    360 | Pin    | Function | Mode |
    361 | ------ | -------- | ---- |
    362 | USART1 |          |      |
    363 | PA9    | TX       | AF1  |
    364 | PA10   | RX       | AF1  |
    365 | PB6    | TX       | AF0  |
    366 | PB7    | RX       | AF0  |
    367 | USART2 |          |      |
    368 | PA2    | TX       | AF1  |
    369 | PA3    | RX       | AF1  |
    370 | PA14   | TX       | AF1  |
    371 | PA15   | RX       | AF1  |
    372 | USART3 |          |      |
    373 | PB10   | TX       | AF4  |
    374 | PB11   | RX       | AF4  |
    375 | PC4    | TX       | AF1  |
    376 | PC5    | RX       | AF1  |
    377 | PC10   | TX       | AF1  |
    378 | PC11   | RX       | AF1  |
    379 | PD8    | TX       | AF0  |
    380 | PD9    | RX       | AF0  |
    381 | USART4 |          |      |
    382 | PA0    | TX       | AF4  |
    383 | PA1    | RX       | AF4  |
    384 
    385 ### STM32F103 Medium Density (C8-CB) [Datasheet](https://www.st.com/resource/en/datasheet/stm32f103c8.pdf)
    386 
    387 Pin Swap available: N/A
    388 
    389 TX Pin is always Alternate Function Push-Pull, RX Pin is always regular input pin for any USART peripheral. **For STM32F103 no additional Alternate Function configuration is necessary. QMK is already configured.**
    390 
    391 Pin remapping:
    392 
    393 The pins of USART Peripherals use default Pins that can be remapped to use other pins using the AFIO registers. Default pins are marked **bold**. Add the appropriate defines to your config.h file.
    394 
    395 | Pin        | Function | Mode | USART_REMAP         |
    396 | ---------- | -------- | ---- | ------------------- |
    397 | **USART1** |          |      |                     |
    398 | **PA9**    | TX       | AFPP |                     |
    399 | **PA10**   | RX       | IN   |                     |
    400 | PB6        | TX       | AFPP | USART1_REMAP        |
    401 | PB7        | RX       | IN   | USART1_REMAP        |
    402 | **USART2** |          |      |                     |
    403 | **PA2**    | TX       | AFPP |                     |
    404 | **PA3**    | RX       | IN   |                     |
    405 | PD5        | TX       | AFPP | USART2_REMAP        |
    406 | PD6        | RX       | IN   | USART2_REMAP        |
    407 | **USART3** |          |      |                     |
    408 | **PB10**   | TX       | AFPP |                     |
    409 | **PB11**   | RX       | IN   |                     |
    410 | PC10       | TX       | AFPP | USART3_PARTIALREMAP |
    411 | PC11       | RX       | IN   | USART3_PARTIALREMAP |
    412 | PD8        | TX       | AFPP | USART3_FULLREMAP    |
    413 | PD9        | RX       | IN   | USART3_FULLREMAP    |