UART driver refactor (#11637)
parent
be897cbc2f
commit
30b46fad57
|
@ -138,6 +138,7 @@
|
||||||
* [WS2812 Driver](ws2812_driver.md)
|
* [WS2812 Driver](ws2812_driver.md)
|
||||||
* [EEPROM Driver](eeprom_driver.md)
|
* [EEPROM Driver](eeprom_driver.md)
|
||||||
* ['serial' Driver](serial_driver.md)
|
* ['serial' Driver](serial_driver.md)
|
||||||
|
* [UART Driver](uart_driver.md)
|
||||||
* [GPIO Controls](internals_gpio_control.md)
|
* [GPIO Controls](internals_gpio_control.md)
|
||||||
* [Keyboard Guidelines](hardware_keyboard_guidelines.md)
|
* [Keyboard Guidelines](hardware_keyboard_guidelines.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.
|
|
@ -1,5 +1,3 @@
|
||||||
// TODO: Teensy support(ATMega32u4/AT90USB128)
|
|
||||||
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
|
|
||||||
/* UART Example for Teensy USB Development Board
|
/* UART Example for Teensy USB Development Board
|
||||||
* http://www.pjrc.com/teensy/
|
* http://www.pjrc.com/teensy/
|
||||||
* Copyright (c) 2009 PJRC.COM, LLC
|
* Copyright (c) 2009 PJRC.COM, LLC
|
||||||
|
@ -31,22 +29,7 @@
|
||||||
|
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
|
#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 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__)
|
|
||||||
# define UDRn UDR1
|
# define UDRn UDR1
|
||||||
# define UBRRnL UBRR1L
|
# define UBRRnL UBRR1L
|
||||||
# define UCSRnA UCSR1A
|
# define UCSRnA UCSR1A
|
||||||
|
@ -76,6 +59,21 @@
|
||||||
# define UDRIEn UDRIE
|
# define UDRIEn UDRIE
|
||||||
# define USARTn_UDRE_vect USART_UDRE_vect
|
# define USARTn_UDRE_vect USART_UDRE_vect
|
||||||
# define USARTn_RX_vect USART_RX_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
|
#endif
|
||||||
|
|
||||||
// These buffers may be any size from 2 to 256 bytes.
|
// These buffers may be any size from 2 to 256 bytes.
|
||||||
|
@ -131,16 +129,16 @@ uint8_t uart_getchar(void) {
|
||||||
return c;
|
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
|
// Call this before uart_getchar() to check if it will need
|
||||||
// to wait for a byte to arrive.
|
// to wait for a byte to arrive.
|
||||||
uint8_t uart_available(void) {
|
bool uart_available(void) {
|
||||||
uint8_t head, tail;
|
uint8_t head, tail;
|
||||||
|
|
||||||
head = rx_buffer_head;
|
head = rx_buffer_head;
|
||||||
tail = rx_buffer_tail;
|
tail = rx_buffer_tail;
|
||||||
if (head >= tail) return head - tail;
|
if (head >= tail) return (head - tail) > 0;
|
||||||
return RX_BUFFER_SIZE + head - tail;
|
return (RX_BUFFER_SIZE + head - tail) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit Interrupt
|
// Transmit Interrupt
|
|
@ -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);
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
|
@ -29,7 +29,7 @@ DYNAMIC_MACRO_ENABLE = yes
|
||||||
UART_DEBUG = no
|
UART_DEBUG = no
|
||||||
|
|
||||||
SRC += matrix.c
|
SRC += matrix.c
|
||||||
QUANTUM_LIB_SRC += $(COMMON_DIR)/uart.c \
|
QUANTUM_LIB_SRC += uart.c \
|
||||||
spi_master.c
|
spi_master.c
|
||||||
|
|
||||||
OPT_DEFS += -DSLEEP_LED_ENABLE # we need our own sleep callbacks to turn of WS2812 LEDs
|
OPT_DEFS += -DSLEEP_LED_ENABLE # we need our own sleep callbacks to turn of WS2812 LEDs
|
||||||
|
|
|
@ -27,6 +27,7 @@ This will require a new communication protocol, as the current one is limited.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "remote_kb.h"
|
#include "remote_kb.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
msg[UART_MSG_LEN],
|
msg[UART_MSG_LEN],
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "quantum.h"
|
#include "quantum.h"
|
||||||
#include "tmk_core/common/uart.h"
|
|
||||||
|
|
||||||
#define SERIAL_UART_BAUD 153600 //low error rate for 32u4 @ 16MHz
|
#define SERIAL_UART_BAUD 153600 //low error rate for 32u4 @ 16MHz
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
# MCU name
|
# MCU name
|
||||||
MCU = atmega32u4
|
MCU = atmega32u4
|
||||||
|
|
||||||
# Interrupt driven control endpoint task(+60)
|
|
||||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
|
||||||
|
|
||||||
# Bootloader selection
|
# Bootloader selection
|
||||||
BOOTLOADER = atmel-dfu
|
BOOTLOADER = atmel-dfu
|
||||||
|
|
||||||
|
@ -31,5 +28,5 @@ CUSTOM_MATRIX = lite # Lite custom matrix
|
||||||
SRC += matrix.c \
|
SRC += matrix.c \
|
||||||
bitc_led.c \
|
bitc_led.c \
|
||||||
big_led.c \
|
big_led.c \
|
||||||
remote_kb.c \
|
remote_kb.c
|
||||||
tmk_core/common/uart.c
|
QUANTUM_LIB_SRC += uart.c
|
||||||
|
|
|
@ -212,8 +212,8 @@
|
||||||
/*
|
/*
|
||||||
* SERIAL driver system settings.
|
* SERIAL driver system settings.
|
||||||
*/
|
*/
|
||||||
#define STM32_SERIAL_USE_USART1 FALSE
|
#define STM32_SERIAL_USE_USART1 TRUE
|
||||||
#define STM32_SERIAL_USE_USART2 TRUE
|
#define STM32_SERIAL_USE_USART2 FALSE
|
||||||
#define STM32_SERIAL_USE_USART3 FALSE
|
#define STM32_SERIAL_USE_USART3 FALSE
|
||||||
#define STM32_SERIAL_USE_UART4 FALSE
|
#define STM32_SERIAL_USE_UART4 FALSE
|
||||||
#define STM32_SERIAL_USE_UART5 FALSE
|
#define STM32_SERIAL_USE_UART5 FALSE
|
||||||
|
|
|
@ -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);
|
|
Loading…
Reference in New Issue