diff options
| author | Ryan <[email protected]> | 2021-01-27 17:42:49 +1100 | 
|---|---|---|
| committer | GitHub <[email protected]> | 2021-01-27 17:42:49 +1100 | 
| commit | 30b46fad5764b54ab4d47e9c4024f8030e1bf1a7 (patch) | |
| tree | 9a9aa60158edf5adea802e33ee2db2ba4164145a | |
| parent | be897cbc2f9d542dfcc98c8e06aeb04179cc484c (diff) | |
| download | qmk_firmware-30b46fad5764b54ab4d47e9c4024f8030e1bf1a7.tar.gz qmk_firmware-30b46fad5764b54ab4d47e9c4024f8030e1bf1a7.zip | |
UART driver refactor (#11637)
| -rw-r--r-- | docs/_summary.md | 1 | ||||
| -rw-r--r-- | docs/uart_driver.md | 90 | ||||
| -rw-r--r-- | drivers/avr/uart.c (renamed from tmk_core/common/uart.c) | 42 | ||||
| -rw-r--r-- | drivers/avr/uart.h | 34 | ||||
| -rw-r--r-- | drivers/chibios/uart.c | 59 | ||||
| -rw-r--r-- | drivers/chibios/uart.h | 77 | ||||
| -rw-r--r-- | keyboards/mschwingen/modelm/rules.mk | 2 | ||||
| -rw-r--r-- | keyboards/nullbitsco/nibble/remote_kb.c | 1 | ||||
| -rw-r--r-- | keyboards/nullbitsco/nibble/remote_kb.h | 1 | ||||
| -rw-r--r-- | keyboards/nullbitsco/nibble/rules.mk | 7 | ||||
| -rw-r--r-- | platforms/chibios/QMK_PROTON_C/configs/mcuconf.h | 4 | ||||
| -rw-r--r-- | tmk_core/common/uart.h | 8 | 
12 files changed, 287 insertions, 39 deletions
| diff --git a/docs/_summary.md b/docs/_summary.md index 9bc0b193a7..526caf926f 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -138,6 +138,7 @@        * [WS2812 Driver](ws2812_driver.md)        * [EEPROM Driver](eeprom_driver.md)        * ['serial' Driver](serial_driver.md) +      * [UART Driver](uart_driver.md)      * [GPIO Controls](internals_gpio_control.md)      * [Keyboard Guidelines](hardware_keyboard_guidelines.md) diff --git a/docs/uart_driver.md b/docs/uart_driver.md new file mode 100644 index 0000000000..4d1716975f --- /dev/null +++ b/docs/uart_driver.md @@ -0,0 +1,90 @@ +# UART Driver + +The UART drivers used in QMK have a set of common functions to allow portability between MCUs. + +Currently, this driver does not support enabling hardware flow control (the `RTS` and `CTS` pins) if available, but may do so in future. + +## AVR Configuration + +No special setup is required - just connect the `RX` and `TX` pins of your UART device to the opposite pins on the MCU: + +|MCU          |`TX`|`RX`|`CTS`|`RTS`| +|-------------|----|----|-----|-----| +|ATmega16/32U2|`D3`|`D2`|`D7` |`D6` | +|ATmega16/32U4|`D3`|`D2`|`D5` |`B7` | +|AT90USB64/128|`D3`|`D2`|*n/a*|*n/a*| +|ATmega32A    |`D1`|`D0`|*n/a*|*n/a*| +|ATmega328/P  |`D1`|`D0`|*n/a*|*n/a*| + +## ChibiOS/ARM Configuration + +You'll need to determine which pins can be used for UART -- as an example, STM32 parts generally have multiple UART peripherals, labeled USART1, USART2, USART3 etc. + +To enable UART, modify your board's `halconf.h` to enable the serial driver: + +```c +#define HAL_USE_SERIAL TRUE +``` + +Then, modify your board's `mcuconf.h` to enable the peripheral you've chosen, for example: + +```c +#undef STM32_SERIAL_USE_USART2 +#define STM32_SERIAL_USE_USART2 TRUE +``` + +Configuration-wise, you'll need to set up the peripheral as per your MCU's datasheet -- the defaults match the pins for a Proton-C, i.e. STM32F303. + +|`config.h` override       |Description                                                    |Default Value| +|--------------------------|---------------------------------------------------------------|-------------| +|`#define SERIAL_DRIVER`   |USART peripheral to use - USART1 -> `SD1`, USART2 -> `SD2` etc.|`SD1`        | +|`#define SD1_TX_PIN`      |The pin to use for TX                                          |`A9`         | +|`#define SD1_TX_PAL_MODE` |The alternate function mode for TX                             |`7`          | +|`#define SD1_RX_PIN`      |The pin to use for RX                                          |`A10`        | +|`#define SD1_RX_PAL_MODE` |The alternate function mode for RX                             |`7`          | +|`#define SD1_CTS_PIN`     |The pin to use for CTS                                         |`A11`        | +|`#define SD1_CTS_PAL_MODE`|The alternate function mode for CTS                            |`7`          | +|`#define SD1_RTS_PIN`     |The pin to use for RTS                                         |`A12`        | +|`#define SD1_RTS_PAL_MODE`|The alternate function mode for RTS                            |`7`          | + +## Functions + +### `void uart_init(uint32_t baud)` + +Initialize the UART driver. This function must be called only once, before any of the below functions can be called. + +#### Arguments + + - `uint32_t baud`   +   The baud rate to transmit and receive at. This may depend on the device you are communicating with. Common values are 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200. + +--- + +### `void uart_putchar(uint8_t c)` + +Transmit a single byte. + +#### Arguments + + - `uint8_t c`   +   The byte (character) to send, from 0 to 255. + +--- + +### `uint8_t uart_getchar(void)` + +Receive a single byte. + +#### Return Value + +The byte read from the receive buffer. + +--- + +### `bool uart_available(void)` + +Return whether the receive buffer contains data. Call this function to determine if `uart_getchar()` will return meaningful data. + +#### Return Value + +`true` if the receive buffer length is non-zero. diff --git a/tmk_core/common/uart.c b/drivers/avr/uart.c index 150e256c8f..e866a9e4f8 100644 --- a/tmk_core/common/uart.c +++ b/drivers/avr/uart.c @@ -1,5 +1,3 @@ -// TODO: Teensy support(ATMega32u4/AT90USB128) -// Fixed for Arduino Duemilanove ATmega168p by Jun Wako  /* UART Example for Teensy USB Development Board   * http://www.pjrc.com/teensy/   * Copyright (c) 2009 PJRC.COM, LLC @@ -31,22 +29,7 @@  #include "uart.h" -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) -#    define UDRn UDR0 -#    define UBRRnL UBRR0L -#    define UCSRnA UCSR0A -#    define UCSRnB UCSR0B -#    define UCSRnC UCSR0C -#    define U2Xn U2X0 -#    define RXENn RXEN0 -#    define TXENn TXEN0 -#    define RXCIEn RXCIE0 -#    define UCSZn1 UCSZ01 -#    define UCSZn0 UCSZ00 -#    define UDRIEn UDRIE0 -#    define USARTn_UDRE_vect USART_UDRE_vect -#    define USARTn_RX_vect USART_RX_vect -#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) +#if defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)  #    define UDRn UDR1  #    define UBRRnL UBRR1L  #    define UCSRnA UCSR1A @@ -76,6 +59,21 @@  #    define UDRIEn UDRIE  #    define USARTn_UDRE_vect USART_UDRE_vect  #    define USARTn_RX_vect USART_RX_vect +#elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) +#    define UDRn UDR0 +#    define UBRRnL UBRR0L +#    define UCSRnA UCSR0A +#    define UCSRnB UCSR0B +#    define UCSRnC UCSR0C +#    define U2Xn U2X0 +#    define RXENn RXEN0 +#    define TXENn TXEN0 +#    define RXCIEn RXCIE0 +#    define UCSZn1 UCSZ01 +#    define UCSZn0 UCSZ00 +#    define UDRIEn UDRIE0 +#    define USARTn_UDRE_vect USART_UDRE_vect +#    define USARTn_RX_vect USART_RX_vect  #endif  // These buffers may be any size from 2 to 256 bytes. @@ -131,16 +129,16 @@ uint8_t uart_getchar(void) {      return c;  } -// Return the number of bytes waiting in the receive buffer. +// Return whether the number of bytes waiting in the receive buffer is nonzero.  // Call this before uart_getchar() to check if it will need  // to wait for a byte to arrive. -uint8_t uart_available(void) { +bool uart_available(void) {      uint8_t head, tail;      head = rx_buffer_head;      tail = rx_buffer_tail; -    if (head >= tail) return head - tail; -    return RX_BUFFER_SIZE + head - tail; +    if (head >= tail) return (head - tail) > 0; +    return (RX_BUFFER_SIZE + head - tail) > 0;  }  // Transmit Interrupt diff --git a/drivers/avr/uart.h b/drivers/avr/uart.h new file mode 100644 index 0000000000..d5ec563db2 --- /dev/null +++ b/drivers/avr/uart.h @@ -0,0 +1,34 @@ +/* UART Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/ + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <stdint.h> + +void uart_init(uint32_t baud); + +void uart_putchar(uint8_t c); + +uint8_t uart_getchar(void); + +bool uart_available(void); diff --git a/drivers/chibios/uart.c b/drivers/chibios/uart.c new file mode 100644 index 0000000000..6e94899b9d --- /dev/null +++ b/drivers/chibios/uart.c @@ -0,0 +1,59 @@ +/* Copyright 2021 + * + *  This program is free software: you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation, either version 3 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ + +#include "uart.h" + +#include "quantum.h" + +static SerialConfig serialConfig = { +    SERIAL_DEFAULT_BITRATE, +    SD1_CR1, +    SD1_CR2, +    SD1_CR3 +}; + +void uart_init(uint32_t baud) { +    static bool is_initialised = false; + +    if (!is_initialised) { +        is_initialised = true; + +        serialConfig.speed = baud; + +#if defined(USE_GPIOV1) +        palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); +        palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); +#else +        palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); +        palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); +#endif +        sdStart(&SERIAL_DRIVER, &serialConfig); +    } +} + +void uart_putchar(uint8_t c) { +    sdPut(&SERIAL_DRIVER, c); +} + +uint8_t uart_getchar(void) { +    msg_t res = sdGet(&SERIAL_DRIVER); + +    return (uint8_t)res; +} + +bool uart_available(void) { +    return !sdGetWouldBlock(&SERIAL_DRIVER); +} diff --git a/drivers/chibios/uart.h b/drivers/chibios/uart.h new file mode 100644 index 0000000000..b4e20e9fd3 --- /dev/null +++ b/drivers/chibios/uart.h @@ -0,0 +1,77 @@ +/* Copyright 2021 + * + *  This program is free software: you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation, either version 3 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdint.h> + +#include <hal.h> + +#ifndef SERIAL_DRIVER +#    define SERIAL_DRIVER SD1 +#endif + +#ifndef SD1_TX_PIN +#    define SD1_TX_PIN A9 +#endif + +#ifndef SD1_TX_PAL_MODE +#    define SD1_TX_PAL_MODE 7 +#endif + +#ifndef SD1_RX_PIN +#    define SD1_RX_PIN A10 +#endif + +#ifndef SD1_RX_PAL_MODE +#    define SD1_RX_PAL_MODE 7 +#endif + +#ifndef SD1_CTS_PIN +#    define SD1_CTS_PIN A11 +#endif + +#ifndef SD1_CTS_PAL_MODE +#    define SD1_CTS_PAL_MODE 7 +#endif + +#ifndef SD1_RTS_PIN +#    define SD1_RTS_PIN A12 +#endif + +#ifndef SD1_RTS_PAL_MODE +#    define SD1_RTS_PAL_MODE 7 +#endif + +#ifndef SD1_CR1 +#    define SD1_CR1 0 +#endif + +#ifndef SD1_CR2 +#    define SD1_CR2 0 +#endif + +#ifndef SD1_CR3 +#    define SD1_CR3 0 +#endif + +void uart_init(uint32_t baud); + +void uart_putchar(uint8_t c); + +uint8_t uart_getchar(void); + +bool uart_available(void); diff --git a/keyboards/mschwingen/modelm/rules.mk b/keyboards/mschwingen/modelm/rules.mk index f3af26eeeb..6775dfa203 100644 --- a/keyboards/mschwingen/modelm/rules.mk +++ b/keyboards/mschwingen/modelm/rules.mk @@ -29,7 +29,7 @@ DYNAMIC_MACRO_ENABLE = yes  UART_DEBUG = no  SRC += matrix.c -QUANTUM_LIB_SRC += $(COMMON_DIR)/uart.c \ +QUANTUM_LIB_SRC += uart.c \                     spi_master.c  OPT_DEFS += -DSLEEP_LED_ENABLE # we need our own sleep callbacks to turn of WS2812 LEDs diff --git a/keyboards/nullbitsco/nibble/remote_kb.c b/keyboards/nullbitsco/nibble/remote_kb.c index 2e36f5f22e..7a914993f3 100644 --- a/keyboards/nullbitsco/nibble/remote_kb.c +++ b/keyboards/nullbitsco/nibble/remote_kb.c @@ -27,6 +27,7 @@ This will require a new communication protocol, as the current one is limited.  */  #include "remote_kb.h" +#include "uart.h"  uint8_t   msg[UART_MSG_LEN], diff --git a/keyboards/nullbitsco/nibble/remote_kb.h b/keyboards/nullbitsco/nibble/remote_kb.h index e2b24655b5..f4b5c43f5d 100644 --- a/keyboards/nullbitsco/nibble/remote_kb.h +++ b/keyboards/nullbitsco/nibble/remote_kb.h @@ -16,7 +16,6 @@  #pragma once  #include "quantum.h" -#include "tmk_core/common/uart.h"  #define SERIAL_UART_BAUD 153600 //low error rate for 32u4 @ 16MHz diff --git a/keyboards/nullbitsco/nibble/rules.mk b/keyboards/nullbitsco/nibble/rules.mk index 683e290866..9340214027 100644 --- a/keyboards/nullbitsco/nibble/rules.mk +++ b/keyboards/nullbitsco/nibble/rules.mk @@ -1,9 +1,6 @@  # MCU name  MCU = atmega32u4 -# Interrupt driven control endpoint task(+60) -OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT -  # Bootloader selection  BOOTLOADER = atmel-dfu @@ -31,5 +28,5 @@ CUSTOM_MATRIX = lite        # Lite custom matrix  SRC += matrix.c \         bitc_led.c \         big_led.c \ -       remote_kb.c \ -       tmk_core/common/uart.c +       remote_kb.c +QUANTUM_LIB_SRC += uart.c diff --git a/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h b/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h index ac2d9a1eed..4d7b586c08 100644 --- a/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h +++ b/platforms/chibios/QMK_PROTON_C/configs/mcuconf.h @@ -212,8 +212,8 @@  /*   * SERIAL driver system settings.   */ -#define STM32_SERIAL_USE_USART1             FALSE -#define STM32_SERIAL_USE_USART2             TRUE +#define STM32_SERIAL_USE_USART1             TRUE +#define STM32_SERIAL_USE_USART2             FALSE  #define STM32_SERIAL_USE_USART3             FALSE  #define STM32_SERIAL_USE_UART4              FALSE  #define STM32_SERIAL_USE_UART5              FALSE diff --git a/tmk_core/common/uart.h b/tmk_core/common/uart.h deleted file mode 100644 index ea247b17b8..0000000000 --- a/tmk_core/common/uart.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include <stdint.h> - -void    uart_init(uint32_t baud); -void    uart_putchar(uint8_t c); -uint8_t uart_getchar(void); -uint8_t uart_available(void); | 
