diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 58e41f52302..7227a5558e2 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -960,6 +960,15 @@ ifeq ($(strip $(SPI_DRIVER_REQUIRED)), yes) endif ifeq ($(strip $(UART_DRIVER_REQUIRED)), yes) - OPT_DEFS += -DHAL_USE_SERIAL=TRUE - QUANTUM_LIB_SRC += uart.c + ifeq ($(strip $(PLATFORM)), CHIBIOS) + ifneq ($(filter $(MCU_SERIES),RP2040),) + OPT_DEFS += -DHAL_USE_SIO=TRUE + QUANTUM_LIB_SRC += uart_sio.c + else + OPT_DEFS += -DHAL_USE_SERIAL=TRUE + QUANTUM_LIB_SRC += uart_serial.c + endif + else + QUANTUM_LIB_SRC += uart.c + endif endif diff --git a/docs/platformdev_rp2040.md b/docs/platformdev_rp2040.md index 890dadb6f06..593a8198eb1 100644 --- a/docs/platformdev_rp2040.md +++ b/docs/platformdev_rp2040.md @@ -2,7 +2,7 @@ The following table shows the current driver status for peripherals on RP2040 MCUs: -| System | Support | +| System | Support | | ---------------------------------------------------------------- | ---------------------------------------------- | | [ADC driver](adc_driver.md) | :heavy_check_mark: | | [Audio](audio_driver.md#pwm-hardware) | :heavy_check_mark: | @@ -13,7 +13,7 @@ The following table shows the current driver status for peripherals on RP2040 MC | [External EEPROMs](eeprom_driver.md) | :heavy_check_mark: using `I2C` or `SPI` driver | | [EEPROM emulation](eeprom_driver.md#wear_leveling-configuration) | :heavy_check_mark: | | [serial driver](serial_driver.md) | :heavy_check_mark: using `SIO` or `PIO` driver | -| [UART driver](uart_driver.md) | Support planned (no ETA) | +| [UART driver](uart_driver.md) | :heavy_check_mark: using `SIO` driver | ## GPIO @@ -52,6 +52,13 @@ To configure the I2C driver please read the [ChibiOS/ARM](i2c_driver.md#arm-conf To configure the SPI driver please read the [ChibiOS/ARM](spi_driver.md#chibiosarm-configuration) section. +### UART Driver + +| RP2040 Peripheral | `mcuconf.h` values | `UART_DRIVER` | +| ----------------- | ------------------ | ------------- | +| `UART0` | `RP_SIO_USE_UART0` | `SIOD0` | +| `UART1` | `RP_SIO_USE_UART1` | `SIOD1` | + ## Double-tap reset boot-loader entry :id=double-tap The double-tap reset mechanism is an alternate way in QMK to enter the embedded mass storage UF2 boot-loader of the RP2040. It enables bootloader entry by a fast double-tap of the reset pin on start up, which is similar to the behavior of AVR Pro Micros. This feature activated by default for the Pro Micro RP2040 board, but has to be configured for other boards. To activate it, add the following options to your keyboards `config.h` file: @@ -87,6 +94,10 @@ This is the default board that is chosen, unless any other RP2040 board is selec | `SOFT_SERIAL_PIN` | undefined, use `SERIAL_USART_TX_PIN` | | `SERIAL_USART_TX_PIN` | `GP0` | | `SERIAL_USART_RX_PIN` | `GP1` | +| **UART driver** | | +| `UART_DRIVER` | `SIOD0` | +| `UART_TX_PIN` | `GP0` | +| `UART_RX_PIN` | `GP1` | ?> The pin-outs of Adafruit's KB2040 and Boardsource's Blok both deviate from the Sparkfun Pro Micro RP2040. Lookup the pin-out of these boards and adjust your keyboards pin definition accordingly if you want to use these boards. diff --git a/docs/uart_driver.md b/docs/uart_driver.md index a88278d5438..9b0a92d23d1 100644 --- a/docs/uart_driver.md +++ b/docs/uart_driver.md @@ -32,13 +32,7 @@ No special setup is required - just connect the `RX` and `TX` pins of your UART 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: +To enable UART, modify your board's `mcuconf.h` to enable the peripheral you've chosen, for example: ```c #undef STM32_SERIAL_USE_USART2 @@ -47,17 +41,17 @@ Then, modify your board's `mcuconf.h` to enable the peripheral you've chosen, fo 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` | +| `config.h` override | Description | Default Value | +| --------------------------- | --------------------------------------------------------------- | ------------- | +| `#define UART_DRIVER` | USART peripheral to use - USART1 -> `SD1`, USART2 -> `SD2` etc. | `SD1` | +| `#define UART_TX_PIN` | The pin to use for TX | `A9` | +| `#define UART_TX_PAL_MODE` | The alternate function mode for TX | `7` | +| `#define UART_RX_PIN` | The pin to use for RX | `A10` | +| `#define UART_RX_PAL_MODE` | The alternate function mode for RX | `7` | +| `#define UART_CTS_PIN` | The pin to use for CTS | `A11` | +| `#define UART_CTS_PAL_MODE` | The alternate function mode for CTS | `7` | +| `#define UART_RTS_PIN` | The pin to use for RTS | `A12` | +| `#define UART_RTS_PAL_MODE` | The alternate function mode for RTS | `7` | ## API :id=api diff --git a/keyboards/handwired/onekey/stm32f3_disco/config.h b/keyboards/handwired/onekey/stm32f3_disco/config.h index a0e3c54ec1c..0927767772a 100644 --- a/keyboards/handwired/onekey/stm32f3_disco/config.h +++ b/keyboards/handwired/onekey/stm32f3_disco/config.h @@ -4,3 +4,9 @@ #pragma once #define ADC_PIN A0 + +#define UART_TX_PIN C4 +#define UART_RX_PIN C5 + +#define SERIAL_USART_TX_PIN C4 +#define SERIAL_USART_RX_PIN C4 diff --git a/keyboards/handwired/onekey/stm32f3_disco/mcuconf.h b/keyboards/handwired/onekey/stm32f3_disco/mcuconf.h index 9172860b0f1..520a5dc3048 100644 --- a/keyboards/handwired/onekey/stm32f3_disco/mcuconf.h +++ b/keyboards/handwired/onekey/stm32f3_disco/mcuconf.h @@ -7,3 +7,9 @@ #undef STM32_ADC_USE_ADC1 #define STM32_ADC_USE_ADC1 TRUE + +#undef STM32_SIO_USE_USART1 +#define STM32_SIO_USE_USART1 TRUE + +#undef STM32_SERIAL_USE_USART1 +#define STM32_SERIAL_USE_USART1 TRUE diff --git a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h index 9209e99e760..73c2b40f469 100644 --- a/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h +++ b/platforms/chibios/boards/GENERIC_PROMICRO_RP2040/configs/config.h @@ -1,4 +1,4 @@ -// Copyright 2022 Stefan Kerkmann +// Copyright 2024 Stefan Kerkmann // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -55,8 +55,32 @@ # define SERIAL_USART_RX_PIN GP1 #endif +/**====================== + ** UART Driver + *========================**/ + +#if !defined(UART_DRIVER) +# define UART_DRIVER SIOD0 +#endif + +#if !defined(UART_TX_PIN) +# define UART_TX_PIN GP0 +#endif + +#if !defined(UART_RX_PIN) +# define UART_RX_PIN GP1 +#endif + +#if !defined(UART_CTS_PIN) +# define UART_CTS_PIN GP2 +#endif + +#if !defined(UART_RTS_PIN) +# define UART_RTS_PIN GP3 +#endif + /**====================== ** Double-tap *========================**/ -#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET diff --git a/platforms/chibios/boards/QMK_BLOK/configs/config.h b/platforms/chibios/boards/QMK_BLOK/configs/config.h index 168afb1fc46..834dc497d3b 100644 --- a/platforms/chibios/boards/QMK_BLOK/configs/config.h +++ b/platforms/chibios/boards/QMK_BLOK/configs/config.h @@ -3,6 +3,10 @@ #pragma once +/**====================== + ** I2C Driver + *========================**/ + #ifndef I2C_DRIVER # define I2C_DRIVER I2CD0 #endif @@ -13,6 +17,26 @@ # define I2C1_SCL_PIN D0 #endif +/**====================== + ** UART Driver + *========================**/ + +#ifndef UART_DRIVER +# define UART_DRIVER SIOD0 +#endif + +#ifndef UART_TX_PIN +# define UART_TX_PIN D3 +#endif + +#ifndef UART_RX_PIN +# define UART_RX_PIN D2 +#endif + +/**====================== + ** Double-tap + *========================**/ + #ifndef RP2040_BOOTLOADER_DOUBLE_TAP_RESET # define RP2040_BOOTLOADER_DOUBLE_TAP_RESET #endif diff --git a/platforms/chibios/boards/QMK_PM2040/configs/config.h b/platforms/chibios/boards/QMK_PM2040/configs/config.h index ec85ae0cf40..f8b46b7fe45 100644 --- a/platforms/chibios/boards/QMK_PM2040/configs/config.h +++ b/platforms/chibios/boards/QMK_PM2040/configs/config.h @@ -3,6 +3,10 @@ #pragma once +/**====================== + ** I2C Driver + *========================**/ + #ifndef I2C_DRIVER # define I2C_DRIVER I2CD1 #endif @@ -13,6 +17,26 @@ # define I2C1_SCL_PIN D0 #endif +/**====================== + ** UART Driver + *========================**/ + +#ifndef UART_DRIVER +# define UART_DRIVER SIOD0 +#endif + +#ifndef UART_TX_PIN +# define UART_TX_PIN D3 +#endif + +#ifndef UART_RX_PIN +# define UART_RX_PIN D2 +#endif + +/**====================== + ** Double-tap + *========================**/ + #ifndef RP2040_BOOTLOADER_DOUBLE_TAP_RESET # define RP2040_BOOTLOADER_DOUBLE_TAP_RESET #endif diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h index f1636f9da05..759ac6943ba 100644 --- a/platforms/chibios/chibios_config.h +++ b/platforms/chibios/chibios_config.h @@ -69,6 +69,20 @@ # ifndef SPI_MISO_PAL_MODE # define SPI_MISO_PAL_MODE (PAL_MODE_ALTERNATE_SPI | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_DRIVE4) # endif + +# ifndef UART_TX_PAL_MODE +# define UART_TX_PAL_MODE PAL_MODE_ALTERNATE_UART +# endif +# ifndef UART_RX_PAL_MODE +# define UART_RX_PAL_MODE PAL_MODE_ALTERNATE_UART +# endif +# ifndef UART_CTS_PAL_MODE +# define UART_CTS_PAL_MODE PAL_MODE_ALTERNATE_UART +# endif +# ifndef UART_RTS_PAL_MODE +# define UART_RTS_PAL_MODE PAL_MODE_ALTERNATE_UART +# endif + #endif // STM32 compatibility diff --git a/platforms/chibios/drivers/uart.c b/platforms/chibios/drivers/uart.c deleted file mode 100644 index 39a59dd4450..00000000000 --- a/platforms/chibios/drivers/uart.c +++ /dev/null @@ -1,70 +0,0 @@ -/* 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 . - */ - -#include "uart.h" - -#if defined(MCU_KINETIS) -static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE}; -#elif defined(WB32F3G71xx) || defined(WB32FQ95xx) -static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_WRDLEN, SD1_STPBIT, SD1_PARITY, SD1_ATFLCT}; -#else -static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3}; -#endif - -void uart_init(uint32_t baud) { - static bool is_initialised = false; - - if (!is_initialised) { - is_initialised = true; - -#if defined(MCU_KINETIS) - serialConfig.sc_speed = baud; -#else - serialConfig.speed = baud; -#endif - -#if defined(USE_GPIOV1) - palSetLineMode(SD1_TX_PIN, SD1_TX_PAL_MODE); - palSetLineMode(SD1_RX_PIN, SD1_RX_PAL_MODE); -#else - palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST); - palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST); -#endif - sdStart(&SERIAL_DRIVER, &serialConfig); - } -} - -void uart_write(uint8_t data) { - sdPut(&SERIAL_DRIVER, data); -} - -uint8_t uart_read(void) { - msg_t res = sdGet(&SERIAL_DRIVER); - - return (uint8_t)res; -} - -void uart_transmit(const uint8_t *data, uint16_t length) { - sdWrite(&SERIAL_DRIVER, data, length); -} - -void uart_receive(uint8_t *data, uint16_t length) { - sdRead(&SERIAL_DRIVER, data, length); -} - -bool uart_available(void) { - return !sdGetWouldBlock(&SERIAL_DRIVER); -} diff --git a/platforms/chibios/drivers/uart.h b/platforms/chibios/drivers/uart.h index 16983072cec..c1945575f13 100644 --- a/platforms/chibios/drivers/uart.h +++ b/platforms/chibios/drivers/uart.h @@ -1,18 +1,7 @@ -/* 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 . - */ +// Copyright 2024 Stefan Kerkmann +// Copyright 2021 QMK +// Copyright 2024 Stefan Kerkmann +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -24,93 +13,188 @@ #include "gpio.h" #include "chibios_config.h" -#ifndef SERIAL_DRIVER -# define SERIAL_DRIVER SD1 +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef SERIAL_DRIVER +# define UART_DRIVER SERIAL_DRIVER +#endif +#ifdef SD1_TX_PIN +# define UART_TX_PIN SD1_TX_PIN +#endif +#ifdef SD1_RX_PIN +# define UART_RX_PIN SD1_RX_PIN +#endif +#ifdef SD1_CTS_PIN +# define UART_CTS_PIN SD1_CTS_PIN +#endif +#ifdef SD1_RTS_PIN +# define UART_RTS_PIN SD1_RTS_PIN +#endif +#ifdef SD1_TX_PAL_MODE +# define UART_TX_PAL_MODE SD1_TX_PAL_MODE +#endif +#ifdef SD1_RX_PAL_MODE +# define UART_RX_PAL_MODE SD1_RX_PAL_MODE +#endif +#ifdef SD1_CTS_PAL_MODE +# define UART_RTS_PAL_MODE SD1_CTS_PAL_MODE +#endif +#ifdef SD1_RTS_PAL_MODE +# define UART_TX_PAL_MODE SD1_RTS_PAL_MODE +#endif +#ifdef SD1_CR1 +# define UART_CR1 SD1_CR1 +#endif +#ifdef SD1_CR2 +# define UART_CR2 SD1_CR2 +#endif +#ifdef SD1_CR3 +# define UART_CR3 SD1_CR3 +#endif +#ifdef SD1_WRDLEN +# define UART_WRDLEN SD1_WRDLEN +#endif +#ifdef SD1_STPBIT +# define UART_STPBIT SD1_STPBIT +#endif +#ifdef SD1_PARITY +# define UART_PARITY SD1_PARITY +#endif +#ifdef SD1_ATFLCT +# define UART_ATFLCT SD1_ATFLCT +#endif +// ======== + +#ifndef UART_DRIVER +# if (HAL_USE_SERIAL == TRUE) +# define UART_DRIVER SD1 +# elif (HAL_USE_SIO == TRUE) +# define UART_DRIVER SIOD1 +# endif #endif -#ifndef SD1_TX_PIN -# define SD1_TX_PIN A9 +#ifndef UART_TX_PIN +# define UART_TX_PIN A9 #endif -#ifndef SD1_RX_PIN -# define SD1_RX_PIN A10 +#ifndef UART_RX_PIN +# define UART_RX_PIN A10 #endif -#ifndef SD1_CTS_PIN -# define SD1_CTS_PIN A11 +#ifndef UART_CTS_PIN +# define UART_CTS_PIN A11 #endif -#ifndef SD1_RTS_PIN -# define SD1_RTS_PIN A12 +#ifndef UART_RTS_PIN +# define UART_RTS_PIN A12 #endif #ifdef USE_GPIOV1 -# ifndef SD1_TX_PAL_MODE -# define SD1_TX_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# ifndef UART_TX_PAL_MODE +# define UART_TX_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL # endif -# ifndef SD1_RX_PAL_MODE -# define SD1_RX_PAL_MODE PAL_MODE_INPUT +# ifndef UART_RX_PAL_MODE +# define UART_RX_PAL_MODE PAL_MODE_INPUT # endif -# ifndef SD1_CTS_PAL_MODE -# define SD1_CTS_PAL_MODE PAL_MODE_INPUT +# ifndef UART_CTS_PAL_MODE +# define UART_CTS_PAL_MODE PAL_MODE_INPUT # endif -# ifndef SD1_RTS_PAL_MODE -# define SD1_RTS_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# ifndef UART_RTS_PAL_MODE +# define UART_RTS_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL # endif #else -# ifndef SD1_TX_PAL_MODE -# define SD1_TX_PAL_MODE 7 +# ifndef UART_TX_PAL_MODE +# define UART_TX_PAL_MODE 7 # endif -# ifndef SD1_RX_PAL_MODE -# define SD1_RX_PAL_MODE 7 +# ifndef UART_RX_PAL_MODE +# define UART_RX_PAL_MODE 7 # endif -# ifndef SD1_CTS_PAL_MODE -# define SD1_CTS_PAL_MODE 7 +# ifndef UART_CTS_PAL_MODE +# define UART_CTS_PAL_MODE 7 # endif -# ifndef SD1_RTS_PAL_MODE -# define SD1_RTS_PAL_MODE 7 +# ifndef UART_RTS_PAL_MODE +# define UART_RTS_PAL_MODE 7 # endif #endif -#ifndef SD1_CR1 -# define SD1_CR1 0 +#ifndef UART_CR1 +# define UART_CR1 0 #endif -#ifndef SD1_CR2 -# define SD1_CR2 0 +#ifndef UART_CR2 +# define UART_CR2 0 #endif -#ifndef SD1_CR3 -# define SD1_CR3 0 +#ifndef UART_CR3 +# define UART_CR3 0 #endif -#ifndef SD1_WRDLEN -# define SD1_WRDLEN 3 +#ifndef UART_WRDLEN +# define UART_WRDLEN 3 #endif -#ifndef SD1_STPBIT -# define SD1_STPBIT 0 +#ifndef UART_STPBIT +# define UART_STPBIT 0 #endif -#ifndef SD1_PARITY -# define SD1_PARITY 0 +#ifndef UART_PARITY +# define UART_PARITY 0 #endif -#ifndef SD1_ATFLCT -# define SD1_ATFLCT 0 +#ifndef UART_ATFLCT +# define UART_ATFLCT 0 #endif +/** + * @brief Initialize the UART driver. This function must be called only once, + * before any of the below functions can be called. + * + * @param 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_init(uint32_t baud); +/** + * @brief Transmit a single byte. + * + * @param data The byte to transmit. + */ void uart_write(uint8_t data); +/** + * @brief Receive a single byte. + * + * @return uint8_t The byte read from the receive buffer. This function will + * block if the buffer is empty (ie. no data to read). + */ uint8_t uart_read(void); +/** + * @brief Transmit multiple bytes. + * + * @param data A pointer to the data to write from. + * @param length The number of bytes to write. Take care not to overrun the + * length of `data`. + */ void uart_transmit(const uint8_t *data, uint16_t length); +/** + * @brief Receive multiple bytes. + * + * @param data A pointer to the buffer to read into. + * @param length The number of bytes to read. Take care not to overrun the + * length of `data`. + */ void uart_receive(uint8_t *data, uint16_t length); +/** + * @brief Return whether the receive buffer contains data. Call this function + * to determine if `uart_read()` will return data immediately. + * + * @return true If there is data available to read. + * @return false If there is no data available to read. + */ bool uart_available(void); diff --git a/platforms/chibios/drivers/uart_serial.c b/platforms/chibios/drivers/uart_serial.c new file mode 100644 index 00000000000..6aff4eae47a --- /dev/null +++ b/platforms/chibios/drivers/uart_serial.c @@ -0,0 +1,65 @@ +// Copyright 2024 Stefan Kerkmann (@KarlK90) +// Copyright 2021 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "uart.h" + +#if defined(MCU_KINETIS) +static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE}; +#elif defined(WB32F3G71xx) || defined(WB32FQ95xx) +static SerialConfig serialConfig = { + SERIAL_DEFAULT_BITRATE, UART_WRDLEN, UART_STPBIT, UART_PARITY, UART_ATFLCT, +}; +#else +static SerialConfig serialConfig = { + SERIAL_DEFAULT_BITRATE, + UART_CR1, + UART_CR2, + UART_CR3, +}; +#endif + +void uart_init(uint32_t baud) { + static bool is_initialised = false; + + if (is_initialised) { + return; + } + is_initialised = true; + +#if defined(MCU_KINETIS) + serialConfig.sc_speed = baud; +#else + serialConfig.speed = baud; +#endif + +#if defined(USE_GPIOV1) + palSetLineMode(UART_TX_PIN, UART_TX_PAL_MODE); + palSetLineMode(UART_RX_PIN, UART_RX_PAL_MODE); +#else + palSetLineMode(UART_TX_PIN, PAL_MODE_ALTERNATE(UART_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST); + palSetLineMode(UART_RX_PIN, PAL_MODE_ALTERNATE(UART_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST); +#endif + + sdStart(&UART_DRIVER, &serialConfig); +} + +void uart_write(uint8_t data) { + sdPut(&UART_DRIVER, data); +} + +uint8_t uart_read(void) { + return (uint8_t)sdGet(&UART_DRIVER); +} + +void uart_transmit(const uint8_t *data, uint16_t length) { + sdWrite(&UART_DRIVER, data, length); +} + +void uart_receive(uint8_t *data, uint16_t length) { + sdRead(&UART_DRIVER, data, length); +} + +bool uart_available(void) { + return !sdGetWouldBlock(&UART_DRIVER); +} diff --git a/platforms/chibios/drivers/uart_sio.c b/platforms/chibios/drivers/uart_sio.c new file mode 100644 index 00000000000..ebf51ae5a81 --- /dev/null +++ b/platforms/chibios/drivers/uart_sio.c @@ -0,0 +1,77 @@ +// Copyright 2024 Stefan Kerkmann (@KarlK90) +// Copyright 2021 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "uart.h" + +#if defined(MCU_RP) +// 38400 baud, 8 data bits, 1 stop bit, no parity, no flow control +static SIOConfig sioConfig = { + .baud = SIO_DEFAULT_BITRATE, + .UARTLCR_H = (UART_UARTLCR_H_WLEN_8BITS | UART_UARTLCR_H_FEN), + .UARTCR = 0U, + .UARTIFLS = (UART_UARTIFLS_RXIFLSEL_1_8F | UART_UARTIFLS_TXIFLSEL_1_8E), + .UARTDMACR = 0U, +}; +#else +static SIOConfig sioConfig = { + .baud = SIO_DEFAULT_BITRATE, +# if defined(MCU_STM32) && defined(CHIBIOS_HAL_USARTv3) + .presc = USART_PRESC1, +# endif + .cr1 = UART_CR1, + .cr2 = UART_CR2, + .cr3 = UART_CR3, +}; +#endif + +void uart_init(uint32_t baud) { + static bool is_initialised = false; + + if (is_initialised) { + return; + } + is_initialised = true; + + sioConfig.baud = baud; + +#if defined(USE_GPIOV1) + palSetLineMode(UART_TX_PIN, UART_TX_PAL_MODE); + palSetLineMode(UART_RX_PIN, UART_RX_PAL_MODE); +#else + palSetLineMode(UART_TX_PIN, PAL_MODE_ALTERNATE(UART_TX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST); + palSetLineMode(UART_RX_PIN, PAL_MODE_ALTERNATE(UART_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST); +#endif + + sioStart(&UART_DRIVER, &sioConfig); +} + +void uart_write(uint8_t data) { + chnPutTimeout(&UART_DRIVER, data, TIME_INFINITE); +} + +uint8_t uart_read(void) { + msg_t result = chnGetTimeout(&UART_DRIVER, TIME_INFINITE); + + if (sioHasRXErrorsX(&UART_DRIVER)) { + sioGetAndClearErrors(&UART_DRIVER); + } + + return (uint8_t)result; +} + +void uart_transmit(const uint8_t *data, uint16_t length) { + chnWrite(&UART_DRIVER, data, length); +} + +void uart_receive(uint8_t *data, uint16_t length) { + chnRead(&UART_DRIVER, data, length); + + if (sioHasRXErrorsX(&UART_DRIVER)) { + sioGetAndClearErrors(&UART_DRIVER); + } +} + +bool uart_available() { + return !sioIsRXEmptyX(&UART_DRIVER); +} diff --git a/platforms/chibios/platform.mk b/platforms/chibios/platform.mk index f38a888012e..a2178412f3f 100644 --- a/platforms/chibios/platform.mk +++ b/platforms/chibios/platform.mk @@ -329,6 +329,17 @@ ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes) EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various endif +# +# Extract supported HAL drivers +############################################################################## + +define add_lld_driver_define + $(eval driver := $(word 2,$(subst /LLD/, ,$(1)))) + $(eval OPT_DEFS += -DCHIBIOS_HAL_$(driver)) +endef + +$(foreach dir,$(EXTRAINCDIRS),$(if $(findstring /LLD/,$(dir)),$(call add_lld_driver_define,$(dir)))) + # # Project, sources and paths ##############################################################################