[Core] Allow ChibiOS SIO driver for UART driver (#22839)

* onekey: stm32f3_disco: add usart pins and activate peripheral

Signed-off-by: Stefan Kerkmann <karlk90@pm.me>

* chibios: uart: change SD1 prefix to UART

Signed-off-by: Stefan Kerkmann <karlk90@pm.me>

* chibios: uart: add SIO driver and RP2040 compatibility

Signed-off-by: Stefan Kerkmann <karlk90@pm.me>
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>

* Update platforms/chibios/drivers/uart.h

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Signed-off-by: Stefan Kerkmann <karlk90@pm.me>
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
Co-authored-by: Joel Challis <git@zvecr.com>
This commit is contained in:
Stefan Kerkmann 2024-02-20 11:34:24 +01:00 committed by GitHub
parent 865a8f42a6
commit 61fa6949fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 428 additions and 149 deletions

View File

@ -960,6 +960,15 @@ ifeq ($(strip $(SPI_DRIVER_REQUIRED)), yes)
endif endif
ifeq ($(strip $(UART_DRIVER_REQUIRED)), yes) ifeq ($(strip $(UART_DRIVER_REQUIRED)), yes)
OPT_DEFS += -DHAL_USE_SERIAL=TRUE ifeq ($(strip $(PLATFORM)), CHIBIOS)
QUANTUM_LIB_SRC += uart.c 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 endif

View File

@ -2,7 +2,7 @@
The following table shows the current driver status for peripherals on RP2040 MCUs: 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: | | [ADC driver](adc_driver.md) | :heavy_check_mark: |
| [Audio](audio_driver.md#pwm-hardware) | :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 | | [External EEPROMs](eeprom_driver.md) | :heavy_check_mark: using `I2C` or `SPI` driver |
| [EEPROM emulation](eeprom_driver.md#wear_leveling-configuration) | :heavy_check_mark: | | [EEPROM emulation](eeprom_driver.md#wear_leveling-configuration) | :heavy_check_mark: |
| [serial driver](serial_driver.md) | :heavy_check_mark: using `SIO` or `PIO` driver | | [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 ## 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. 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 ## 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: 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` | | `SOFT_SERIAL_PIN` | undefined, use `SERIAL_USART_TX_PIN` |
| `SERIAL_USART_TX_PIN` | `GP0` | | `SERIAL_USART_TX_PIN` | `GP0` |
| `SERIAL_USART_RX_PIN` | `GP1` | | `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. ?> 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.

View File

@ -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. 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: To enable UART, modify your board's `mcuconf.h` to enable the peripheral you've chosen, for example:
```c
#define HAL_USE_SERIAL TRUE
```
Then, modify your board's `mcuconf.h` to enable the peripheral you've chosen, for example:
```c ```c
#undef STM32_SERIAL_USE_USART2 #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. 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| | `config.h` override | Description | Default Value |
|--------------------------|---------------------------------------------------------------|-------------| | --------------------------- | --------------------------------------------------------------- | ------------- |
|`#define SERIAL_DRIVER` |USART peripheral to use - USART1 -> `SD1`, USART2 -> `SD2` etc.|`SD1` | | `#define UART_DRIVER` | USART peripheral to use - USART1 -> `SD1`, USART2 -> `SD2` etc. | `SD1` |
|`#define SD1_TX_PIN` |The pin to use for TX |`A9` | | `#define UART_TX_PIN` | The pin to use for TX | `A9` |
|`#define SD1_TX_PAL_MODE` |The alternate function mode for TX |`7` | | `#define UART_TX_PAL_MODE` | The alternate function mode for TX | `7` |
|`#define SD1_RX_PIN` |The pin to use for RX |`A10` | | `#define UART_RX_PIN` | The pin to use for RX | `A10` |
|`#define SD1_RX_PAL_MODE` |The alternate function mode for RX |`7` | | `#define UART_RX_PAL_MODE` | The alternate function mode for RX | `7` |
|`#define SD1_CTS_PIN` |The pin to use for CTS |`A11` | | `#define UART_CTS_PIN` | The pin to use for CTS | `A11` |
|`#define SD1_CTS_PAL_MODE`|The alternate function mode for CTS |`7` | | `#define UART_CTS_PAL_MODE` | The alternate function mode for CTS | `7` |
|`#define SD1_RTS_PIN` |The pin to use for RTS |`A12` | | `#define UART_RTS_PIN` | The pin to use for RTS | `A12` |
|`#define SD1_RTS_PAL_MODE`|The alternate function mode for RTS |`7` | | `#define UART_RTS_PAL_MODE` | The alternate function mode for RTS | `7` |
## API :id=api ## API :id=api

View File

@ -4,3 +4,9 @@
#pragma once #pragma once
#define ADC_PIN A0 #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

View File

@ -7,3 +7,9 @@
#undef STM32_ADC_USE_ADC1 #undef STM32_ADC_USE_ADC1
#define STM32_ADC_USE_ADC1 TRUE #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

View File

@ -1,4 +1,4 @@
// Copyright 2022 Stefan Kerkmann // Copyright 2024 Stefan Kerkmann
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@ -55,6 +55,30 @@
# define SERIAL_USART_RX_PIN GP1 # define SERIAL_USART_RX_PIN GP1
#endif #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 ** Double-tap
*========================**/ *========================**/

View File

@ -3,6 +3,10 @@
#pragma once #pragma once
/**======================
** I2C Driver
*========================**/
#ifndef I2C_DRIVER #ifndef I2C_DRIVER
# define I2C_DRIVER I2CD0 # define I2C_DRIVER I2CD0
#endif #endif
@ -13,6 +17,26 @@
# define I2C1_SCL_PIN D0 # define I2C1_SCL_PIN D0
#endif #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 #ifndef RP2040_BOOTLOADER_DOUBLE_TAP_RESET
# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET # define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
#endif #endif

View File

@ -3,6 +3,10 @@
#pragma once #pragma once
/**======================
** I2C Driver
*========================**/
#ifndef I2C_DRIVER #ifndef I2C_DRIVER
# define I2C_DRIVER I2CD1 # define I2C_DRIVER I2CD1
#endif #endif
@ -13,6 +17,26 @@
# define I2C1_SCL_PIN D0 # define I2C1_SCL_PIN D0
#endif #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 #ifndef RP2040_BOOTLOADER_DOUBLE_TAP_RESET
# define RP2040_BOOTLOADER_DOUBLE_TAP_RESET # define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
#endif #endif

View File

@ -69,6 +69,20 @@
# ifndef SPI_MISO_PAL_MODE # ifndef SPI_MISO_PAL_MODE
# define SPI_MISO_PAL_MODE (PAL_MODE_ALTERNATE_SPI | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_DRIVE4) # define SPI_MISO_PAL_MODE (PAL_MODE_ALTERNATE_SPI | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_DRIVE4)
# endif # 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 #endif
// STM32 compatibility // STM32 compatibility

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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);
}

View File

@ -1,18 +1,7 @@
/* Copyright 2021 // Copyright 2024 Stefan Kerkmann
* // Copyright 2021 QMK
* This program is free software: you can redistribute it and/or modify // Copyright 2024 Stefan Kerkmann
* it under the terms of the GNU General Public License as published by // SPDX-License-Identifier: GPL-2.0-or-later
* 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 #pragma once
@ -24,93 +13,188 @@
#include "gpio.h" #include "gpio.h"
#include "chibios_config.h" #include "chibios_config.h"
#ifndef SERIAL_DRIVER // ======== DEPRECATED DEFINES - DO NOT USE ========
# define SERIAL_DRIVER SD1 #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 #endif
#ifndef SD1_TX_PIN #ifndef UART_TX_PIN
# define SD1_TX_PIN A9 # define UART_TX_PIN A9
#endif #endif
#ifndef SD1_RX_PIN #ifndef UART_RX_PIN
# define SD1_RX_PIN A10 # define UART_RX_PIN A10
#endif #endif
#ifndef SD1_CTS_PIN #ifndef UART_CTS_PIN
# define SD1_CTS_PIN A11 # define UART_CTS_PIN A11
#endif #endif
#ifndef SD1_RTS_PIN #ifndef UART_RTS_PIN
# define SD1_RTS_PIN A12 # define UART_RTS_PIN A12
#endif #endif
#ifdef USE_GPIOV1 #ifdef USE_GPIOV1
# ifndef SD1_TX_PAL_MODE # ifndef UART_TX_PAL_MODE
# define SD1_TX_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL # define UART_TX_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# endif # endif
# ifndef SD1_RX_PAL_MODE # ifndef UART_RX_PAL_MODE
# define SD1_RX_PAL_MODE PAL_MODE_INPUT # define UART_RX_PAL_MODE PAL_MODE_INPUT
# endif # endif
# ifndef SD1_CTS_PAL_MODE # ifndef UART_CTS_PAL_MODE
# define SD1_CTS_PAL_MODE PAL_MODE_INPUT # define UART_CTS_PAL_MODE PAL_MODE_INPUT
# endif # endif
# ifndef SD1_RTS_PAL_MODE # ifndef UART_RTS_PAL_MODE
# define SD1_RTS_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL # define UART_RTS_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
# endif # endif
#else #else
# ifndef SD1_TX_PAL_MODE # ifndef UART_TX_PAL_MODE
# define SD1_TX_PAL_MODE 7 # define UART_TX_PAL_MODE 7
# endif # endif
# ifndef SD1_RX_PAL_MODE # ifndef UART_RX_PAL_MODE
# define SD1_RX_PAL_MODE 7 # define UART_RX_PAL_MODE 7
# endif # endif
# ifndef SD1_CTS_PAL_MODE # ifndef UART_CTS_PAL_MODE
# define SD1_CTS_PAL_MODE 7 # define UART_CTS_PAL_MODE 7
# endif # endif
# ifndef SD1_RTS_PAL_MODE # ifndef UART_RTS_PAL_MODE
# define SD1_RTS_PAL_MODE 7 # define UART_RTS_PAL_MODE 7
# endif # endif
#endif #endif
#ifndef SD1_CR1 #ifndef UART_CR1
# define SD1_CR1 0 # define UART_CR1 0
#endif #endif
#ifndef SD1_CR2 #ifndef UART_CR2
# define SD1_CR2 0 # define UART_CR2 0
#endif #endif
#ifndef SD1_CR3 #ifndef UART_CR3
# define SD1_CR3 0 # define UART_CR3 0
#endif #endif
#ifndef SD1_WRDLEN #ifndef UART_WRDLEN
# define SD1_WRDLEN 3 # define UART_WRDLEN 3
#endif #endif
#ifndef SD1_STPBIT #ifndef UART_STPBIT
# define SD1_STPBIT 0 # define UART_STPBIT 0
#endif #endif
#ifndef SD1_PARITY #ifndef UART_PARITY
# define SD1_PARITY 0 # define UART_PARITY 0
#endif #endif
#ifndef SD1_ATFLCT #ifndef UART_ATFLCT
# define SD1_ATFLCT 0 # define UART_ATFLCT 0
#endif #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); void uart_init(uint32_t baud);
/**
* @brief Transmit a single byte.
*
* @param data The byte to transmit.
*/
void uart_write(uint8_t data); 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); 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); 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); 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); bool uart_available(void);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -329,6 +329,17 @@ ifeq ($(strip $(USE_CHIBIOS_CONTRIB)),yes)
EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various EXTRAINCDIRS += $(PLATFORMINC_CONTRIB) $(HALINC_CONTRIB) $(CHIBIOS_CONTRIB)/os/various
endif 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 # Project, sources and paths
############################################################################## ##############################################################################