1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-13 03:20:00 +03:00

Improve serial_post.h (#14096)

This commit is contained in:
Petr Ledvina 2024-12-20 19:01:00 +01:00 committed by GitHub
parent 7dec49ce42
commit 2f21754a69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 120 additions and 37 deletions

View file

@ -197,8 +197,8 @@ static void resetBuffers(softSerial_t *softSerial)
softSerial_t* softSerialFromIdentifier(serialPortIdentifier_e identifier)
{
if (identifier >= SERIAL_PORT_SOFTSERIAL1 && identifier < SERIAL_PORT_SOFTSERIAL1 + SERIAL_SOFTSERIAL_COUNT) {
return &softSerialPorts[identifier - SERIAL_PORT_SOFTSERIAL1];
if (identifier >= SERIAL_PORT_SOFTSERIAL_FIRST && identifier < SERIAL_PORT_SOFTSERIAL_FIRST + SERIAL_SOFTSERIAL_COUNT) {
return &softSerialPorts[identifier - SERIAL_PORT_SOFTSERIAL_FIRST];
}
return NULL;
}

View file

@ -174,7 +174,7 @@ uartDeviceIdx_e uartDeviceIdxFromIdentifier(serialPortIdentifier_e identifier)
}
#else
{
const int idx = identifier - SERIAL_PORT_USART1;
const int idx = identifier - SERIAL_PORT_UART_FIRST;
if (idx >= 0 && idx < SERIAL_UART_MAX) {
if (BIT(idx) & SERIAL_UART_MASK) {
// return number of enabled UART ports smaller than idx

View file

@ -83,7 +83,14 @@ extern const uint32_t baudRates[];
typedef enum {
SERIAL_PORT_ALL = -2,
SERIAL_PORT_NONE = -1,
SERIAL_PORT_USART1 = 0,
// prepare for transition to SERIAL_PORT_UART0
SERIAL_PORT_UART_FIRST = 0,
#if SERIAL_UART_FIRST_INDEX == 0
SERIAL_PORT_UART0 = SERIAL_PORT_UART_FIRST,
SERIAL_PORT_USART1,
#else
SERIAL_PORT_USART1 = SERIAL_PORT_UART_FIRST,
#endif
SERIAL_PORT_UART1 = SERIAL_PORT_USART1,
SERIAL_PORT_USART2,
SERIAL_PORT_UART2 = SERIAL_PORT_USART2,
@ -103,10 +110,12 @@ typedef enum {
SERIAL_PORT_USB_VCP = 20,
SERIAL_PORT_SOFTSERIAL1 = 30,
SERIAL_PORT_SOFTSERIAL_FIRST = 30,
SERIAL_PORT_SOFTSERIAL1 = SERIAL_PORT_SOFTSERIAL_FIRST,
SERIAL_PORT_SOFTSERIAL2,
SERIAL_PORT_LPUART1 = 40,
SERIAL_PORT_LPUART_FIRST = 40,
SERIAL_PORT_LPUART1 = SERIAL_PORT_LPUART_FIRST,
} serialPortIdentifier_e;
// use value from target serial port normalization

View file

@ -36,8 +36,9 @@ serialType_e serialType(serialPortIdentifier_e identifier)
}
#endif
#ifdef USE_UART
if (identifier >= SERIAL_PORT_USART1 && identifier < SERIAL_PORT_USART1 + SERIAL_UART_MAX) {
const unsigned idx = identifier - SERIAL_PORT_USART1;
if (identifier >= SERIAL_PORT_UART_FIRST
&& identifier < SERIAL_PORT_UART_FIRST + SERIAL_UART_MAX) {
const unsigned idx = identifier - SERIAL_PORT_UART_FIRST;
if (BIT(idx) & SERIAL_UART_MASK) {
return SERIALTYPE_UART;
} else {
@ -47,8 +48,9 @@ serialType_e serialType(serialPortIdentifier_e identifier)
}
#endif
#ifdef USE_LPUART
if (identifier >= SERIAL_PORT_LPUART1 && identifier < SERIAL_PORT_LPUART1 + SERIAL_LPUART_MAX) {
const unsigned idx = identifier - SERIAL_PORT_LPUART1;
if (identifier >= SERIAL_PORT_LPUART_FIRST
&& identifier < SERIAL_PORT_LPUART_FIRST + SERIAL_LPUART_MAX) {
const unsigned idx = identifier - SERIAL_PORT_LPUART_FIRST;
if (BIT(idx) & SERIAL_LPUART_MASK) {
return SERIALTYPE_LPUART;
} else {
@ -58,8 +60,9 @@ serialType_e serialType(serialPortIdentifier_e identifier)
}
#endif
#ifdef USE_SOFTSERIAL
if (identifier >= SERIAL_PORT_SOFTSERIAL1 && identifier < SERIAL_PORT_SOFTSERIAL1 + SERIAL_SOFTSERIAL_MAX) {
// sotserials always start from 1, without holes
if (identifier >= SERIAL_PORT_SOFTSERIAL_FIRST
&& identifier < SERIAL_PORT_SOFTSERIAL_FIRST + SERIAL_SOFTSERIAL_MAX) {
// sotserials always start from first index, without holes
return SERIALTYPE_SOFTSERIAL;
}
#endif
@ -72,9 +75,9 @@ static const struct SerialTypeInfo {
int8_t resourceOffset;
} serialTypeMap[] = {
[SERIALTYPE_USB_VCP] = { OWNER_FREE /* no owner*/, SERIAL_PORT_USB_VCP, -1 },
[SERIALTYPE_UART] = { OWNER_SERIAL_TX, SERIAL_PORT_USART1, RESOURCE_UART_OFFSET },
[SERIALTYPE_LPUART] = { OWNER_LPUART_TX, SERIAL_PORT_LPUART1, RESOURCE_LPUART_OFFSET },
[SERIALTYPE_SOFTSERIAL] = { OWNER_SOFTSERIAL_TX, SERIAL_PORT_SOFTSERIAL1, RESOURCE_SOFTSERIAL_OFFSET },
[SERIALTYPE_UART] = { OWNER_SERIAL_TX, SERIAL_PORT_UART_FIRST, RESOURCE_UART_OFFSET },
[SERIALTYPE_LPUART] = { OWNER_LPUART_TX, SERIAL_PORT_LPUART_FIRST, RESOURCE_LPUART_OFFSET },
[SERIALTYPE_SOFTSERIAL] = { OWNER_SOFTSERIAL_TX, SERIAL_PORT_SOFTSERIAL_FIRST, RESOURCE_SOFTSERIAL_OFFSET },
};
STATIC_ASSERT(ARRAYLEN(serialTypeMap) == SERIALTYPE_COUNT, "type table mismatch");

View file

@ -30,7 +30,7 @@ in Betaflight topmost directory.
This include will provide following defines:
SERIAL_<type><n>_USED 0/1 - always defined, value depends on target configuration
SERIAL_<type>_MASK - bitmask of used ports or given type. <port>1 is BIT(0)
SERIAL_<type>_MASK - bitmask of used ports or given type. <port>0 or <port>1 is BIT(0), based on port first_index
SERIAL_<type>_COUNT - number of enabled ports of given type
SERIAL_<type>_MAX - <index of highest used port> + 1, 0 when no port is enabled
@ -39,22 +39,41 @@ All <type><n>_(RX|TX)_PINS are normalized too:
- if port is not enable, both will be undefined, possibly with warning
- pass -DWARN_UNUSED_SERIAL_PORT to compiler to check pin defined without corresponding port being enabled.
Generated on 2024-11-04
Generated on 2024-12-20
Configuration used:
{ 'LPUART': {'depends': {'UART'}, 'ids': [1]},
'SOFTSERIAL': { 'force_continuous': True,
'ids': [1, 2],
'use_enables_all': True},
'UART': {'ids': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'inverter': True},
'UART': { 'first_index': True,
'ids': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'inverter': True},
'VCP': {'no_pins': True, 'singleton': True}}
*/
#include "common/utils.h" // BIT, LOG2
/**** UART *****/
// normalize SERIAL_UART_FIRST_INDEX
#ifndef SERIAL_UART_FIRST_INDEX
#define SERIAL_UART_FIRST_INDEX 1
#endif
#if SERIAL_UART_FIRST_INDEX == 0
#if defined(USE_UART0)
# define SERIAL_UART0_USED 1
#else
# define SERIAL_UART0_USED 0
#endif
#else // USE_UART0 is not allowed
# if defined(USE_UART0)
# error "USE_UART0 is defined, but SERIAL_UART does not allow index 0"
# else
# define SERIAL_UART0_USED 0
# endif
#endif
#if defined(USE_UART1)
# define SERIAL_UART1_USED 1
#else
@ -106,16 +125,43 @@ Configuration used:
# define SERIAL_UART10_USED 0
#endif
#define SERIAL_UART_MASK ((SERIAL_UART1_USED * BIT(1 - 1)) | (SERIAL_UART2_USED * BIT(2 - 1)) | (SERIAL_UART3_USED * BIT(3 - 1)) | (SERIAL_UART4_USED * BIT(4 - 1)) | (SERIAL_UART5_USED * BIT(5 - 1)) | (SERIAL_UART6_USED * BIT(6 - 1)) | (SERIAL_UART7_USED * BIT(7 - 1)) | (SERIAL_UART8_USED * BIT(8 - 1)) | (SERIAL_UART9_USED * BIT(9 - 1)) | (SERIAL_UART10_USED * BIT(10 - 1)))
#define SERIAL_UART_COUNT (SERIAL_UART1_USED + SERIAL_UART2_USED + SERIAL_UART3_USED + SERIAL_UART4_USED + SERIAL_UART5_USED + SERIAL_UART6_USED + SERIAL_UART7_USED + SERIAL_UART8_USED + SERIAL_UART9_USED + SERIAL_UART10_USED)
#define SERIAL_UART_MASK ((SERIAL_UART0_USED * BIT(0)) | (SERIAL_UART1_USED * BIT(1 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART2_USED * BIT(2 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART3_USED * BIT(3 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART4_USED * BIT(4 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART5_USED * BIT(5 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART6_USED * BIT(6 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART7_USED * BIT(7 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART8_USED * BIT(8 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART9_USED * BIT(9 - SERIAL_UART_FIRST_INDEX)) | (SERIAL_UART10_USED * BIT(10 - SERIAL_UART_FIRST_INDEX)))
#define SERIAL_UART_COUNT (SERIAL_UART0_USED + SERIAL_UART1_USED + SERIAL_UART2_USED + SERIAL_UART3_USED + SERIAL_UART4_USED + SERIAL_UART5_USED + SERIAL_UART6_USED + SERIAL_UART7_USED + SERIAL_UART8_USED + SERIAL_UART9_USED + SERIAL_UART10_USED)
// 0 if no port is defined
#define SERIAL_UART_MAX (SERIAL_UART_MASK ? LOG2(SERIAL_UART_MASK) + 1 : 0)
// enable USE_INVERTED first, before normalization
#if !defined(USE_INVERTER) && (INVERTER_PIN_UART1 || INVERTER_PIN_UART2 || INVERTER_PIN_UART3 || INVERTER_PIN_UART4 || INVERTER_PIN_UART5 || INVERTER_PIN_UART6 || INVERTER_PIN_UART7 || INVERTER_PIN_UART8 || INVERTER_PIN_UART9 || INVERTER_PIN_UART10)
#if !defined(USE_INVERTER) && (INVERTER_PIN_UART0 || INVERTER_PIN_UART1 || INVERTER_PIN_UART2 || INVERTER_PIN_UART3 || INVERTER_PIN_UART4 || INVERTER_PIN_UART5 || INVERTER_PIN_UART6 || INVERTER_PIN_UART7 || INVERTER_PIN_UART8 || INVERTER_PIN_UART9 || INVERTER_PIN_UART10)
# define USE_INVERTER
#endif
// Normalize UART TX/RX/INVERTER
#if SERIAL_UART0_USED && !defined(UART0_RX_PIN)
# define UART0_RX_PIN NONE
#endif
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART0_USED && defined(UART0_RX_PIN)
# warning "UART0_RX_PIN is defined but UART0 is not enabled"
#endif
#if !SERIAL_UART0_USED && defined(UART0_RX_PIN)
# undef UART0_RX_PIN
#endif
#if SERIAL_UART0_USED && !defined(UART0_TX_PIN)
# define UART0_TX_PIN NONE
#endif
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART0_USED && defined(UART0_TX_PIN)
# warning "UART0_TX_PIN is defined but UART0 is not enabled"
#endif
#if !SERIAL_UART0_USED && defined(UART0_TX_PIN)
# undef UART0_TX_PIN
#endif
#if SERIAL_UART0_USED && !defined(INVERTER_PIN_UART0)
# define INVERTER_PIN_UART0 NONE
#endif
#if defined(WARN_UNUSED_SERIAL_PORT) && !SERIAL_UART0_USED && defined(INVERTER_PIN_UART0)
# warning "INVERTER_PIN_UART0 is defined but UART0 is not enabled"
#endif
#if !SERIAL_UART0_USED && defined(INVERTER_PIN_UART0)
# undef INVERTER_PIN_UART0
#endif
#if SERIAL_UART1_USED && !defined(UART1_RX_PIN)
# define UART1_RX_PIN NONE
#endif
@ -421,7 +467,9 @@ Configuration used:
#endif
/**** SOFTSERIAL *****/
#if defined(USE_SOFTSERIAL)
// USE_SOFTSERIAL enables all SOFTSERIAL ports
# if !defined(USE_SOFTSERIAL1)
# define USE_SOFTSERIAL1
# endif
@ -496,7 +544,7 @@ Configuration used:
# define SERIAL_VCP_USED 0
#endif
// set one bit if port is enabled for consistency
// for consistency, set one bit if port is enabled
#define SERIAL_VCP_MASK (SERIAL_VCP_USED * BIT(0))
#define SERIAL_VCP_COUNT (SERIAL_VCP_USED)
// 0 if no port is defined

View file

@ -8,14 +8,15 @@ import pprint
# configuration for template generation
serials = {
"UART": {"ids": [i + 1 for i in range(10)],
"UART": {"ids": list(range(0, 10 + 1)),
"inverter": True,
"first_index": True, # support configurable first index for this port
},
"LPUART": {"ids": [1],
"depends": {"UART"},
# "inverter": True, # TODO: old code compatibility only, disabled
},
"SOFTSERIAL": {"ids": [i + 1 for i in range(2)],
"SOFTSERIAL": {"ids": list(range(1, 2 + 1)),
"use_enables_all": True,
"force_continuous": True,
},
@ -69,6 +70,7 @@ def main():
singleton = cfg.setdefault('singleton', False)
no_pins = cfg.setdefault('no_pins', False)
inverter = cfg.setdefault('inverter', False)
cfg.setdefault('first_index', False)
cfg.setdefault("use_enables_all", False)
cfg.setdefault("force_continuous", False)
cfg.setdefault("depends", {})

View file

@ -1,7 +1,6 @@
{# serial_post.h #}
{# DEFAULT_LICENCE.md is used #}
{{ license|safe }}
/*
{# Start with generated warning. It you want to change something, edit this file #}
This file is automatically generated by src/utils/gen-serial.py script from src/utils/templates/serial_post.h jinja2 template.
@ -14,7 +13,7 @@ in Betaflight topmost directory.
This include will provide following defines:
SERIAL_<type><n>_USED 0/1 - always defined, value depends on target configuration
SERIAL_<type>_MASK - bitmask of used ports or given type. <port>1 is BIT(0)
SERIAL_<type>_MASK - bitmask of used ports or given type. <port>0 or <port>1 is BIT(0), based on port first_index
SERIAL_<type>_COUNT - number of enabled ports of given type
SERIAL_<type>_MAX - <index of highest used port> + 1, 0 when no port is enabled
@ -30,56 +29,77 @@ Configuration used:
{# TODO - maybe store configuration in this file, not Python one #}
{# TODO - pretty is not enough pretty #}
{{ user_config|pprint|safe }}
*/
#include "common/utils.h" // BIT, LOG2
{# config array is passed to this script. It is flattened version of user_config, with default fileld in #}
{# config array is passed to this script. It is flattened version of user_config, with defaults filled in #}
{% for cfg in config %}
/**** {{ cfg.typ }} *****/
{% if cfg.first_index %}
// normalize SERIAL_{{ cfg.typ }}_FIRST_INDEX
#ifndef SERIAL_{{ cfg.typ }}_FIRST_INDEX
#define SERIAL_{{ cfg.typ }}_FIRST_INDEX 1
#endif
{% endif %}
{# use_enables_all - USE_<type> enables all ports of this type #}
{% if cfg.use_enables_all %}
#if defined(USE_{{cfg.typ}})
// USE_{{cfg.typ}} enables all {{cfg.typ}} ports
{% for port in cfg.ports %}
# if !defined(USE_{{port}})
# define USE_{{port}}
# endif
{% endfor %}
#endif
{% endif %}
{% endif %}
{# USE_<port> - SERIAL_<port>_USED 0/1 #}
{% for port in cfg.ports %}
{% for port, i in cfg.ports|zip(cfg.ids|default([-1])) %}{# handle singleton without ids #}
{% if i == 0 and cfg.first_index %}{# port 0, test if it is allowed #}
#if SERIAL_{{ cfg.typ }}_FIRST_INDEX == 0
{% endif %}
#if defined(USE_{{port}})
# define SERIAL_{{port}}_USED 1
#else
# define SERIAL_{{port}}_USED 0
#endif
{% if i == 0 and cfg.first_index %}{# port 0, #else branch #}
#else // USE_{{port}} is not allowed
# if defined(USE_{{port}})
# error "USE_{{port}} is defined, but SERIAL_{{ cfg.typ }} does not allow index 0"
# else
# define SERIAL_{{port}}_USED 0
# endif
#endif
{% endif %}
{% endfor %}
{# SERIAL_<port>_* summary macros #}
{% if not cfg.singleton %}
{% set pipe = joiner(' | ') %}
#define SERIAL_{{ cfg.typ }}_MASK ({% for port, i in cfg.ports|zip(cfg.ids) %}{{ pipe() }}(SERIAL_{{ port }}_USED * BIT({{ i }} - 1)){% endfor %})
#define SERIAL_{{ cfg.typ }}_MASK ({% for port, i in cfg.ports|zip(cfg.ids) %}
{{- pipe() }}(SERIAL_{{ port }}_USED * BIT({{ "0" if i==0 else "{} - SERIAL_{}_FIRST_INDEX".format(i, cfg.typ) if cfg.first_index else "{} - 1".format(i) }})){% endfor %})
{# export first index information, so serial.h can assert that it does match #}
{% else %}
{# one port without number is defined #}
// set one bit if port is enabled for consistency
// for consistency, set one bit if port is enabled
#define SERIAL_{{ cfg.typ }}_MASK (SERIAL_{{ cfg.ports[0] }}_USED * BIT(0))
{% endif %}
{% set plus = joiner(' + ') %}
#define SERIAL_{{ cfg.typ }}_COUNT ({% for port in cfg.ports %}{{ plus() }}SERIAL_{{ port }}_USED{% endfor %})
{# LOG2 is simpler than chaining MAX(SERIAL_x1_USED * 1, MAX(SERIAL_x2_USED * 2, ... #}
// 0 if no port is defined
{# LOG2 is simpler than chaining MAX(SERIAL_x1_USED * 1, MAX(SERIAL_x2_USED * 2, ... #}
#define SERIAL_{{ cfg.typ }}_MAX (SERIAL_{{cfg.typ}}_MASK ? LOG2(SERIAL_{{cfg.typ}}_MASK) + 1 : 0)
{# for softserial, we don't want softserial2 only #}
{% if cfg.force_continuous %}
#if SERIAL_{{cfg.typ}}_COUNT != SERIAL_{{cfg.typ}}_MAX
# error {{cfg.typ}} ports must start with {{cfg.typ}}1 and be continuous
#endif
{% endif %}
{# backward compatibility, code did set USE_INVERTER this way. It must be done before normalizing to NONE #}
{% if cfg.inverter %}
// enable USE_INVERTED first, before normalization
@ -90,6 +110,7 @@ Configuration used:
{% endif %}
{# no pins for VCP port #}
{% if not cfg.no_pins %}
// Normalize {{cfg.typ}} TX/RX{{ "/INVERTER" if cfg.inverter else "" }}
{% for port in cfg.ports %}
{% set pins = [ port ~ '_RX_PIN', port ~ '_TX_PIN' ] + (['INVERTER_PIN_' ~ port] if cfg.inverter else []) %}