Adding support for UART0 (#14094)
[betaflight.git] / src / main / io / serial_resource.c
blob878968d0bfddd3b65626d3ea05516090613764ac
1 /*
2 * This file is part of Betaflight.
4 * Betaflight is free software. You can redistribute this software
5 * and/or modify this software under the terms of the GNU General
6 * Public License as published by the Free Software Foundation,
7 * either version 3 of the License, or (at your option) any later
8 * version.
10 * Betaflight is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this software.
19 * If not, see <http://www.gnu.org/licenses/>.
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <limits.h>
26 #include "platform.h"
28 #include "io/serial.h"
30 // convert identifier into port type
31 serialType_e serialType(serialPortIdentifier_e identifier)
33 #ifdef USE_VCP
34 if (identifier == SERIAL_PORT_USB_VCP) {
35 return SERIALTYPE_USB_VCP;
37 #endif
38 #ifdef USE_UART
39 if (identifier >= SERIAL_PORT_UART_FIRST
40 && identifier < SERIAL_PORT_UART_FIRST + SERIAL_UART_MAX) {
41 const unsigned idx = identifier - SERIAL_PORT_UART_FIRST;
42 if (BIT(idx) & SERIAL_UART_MASK) {
43 return SERIALTYPE_UART;
44 } else {
45 // no other type in this range
46 return SERIALTYPE_INVALID;
49 #endif
50 #ifdef USE_LPUART
51 if (identifier >= SERIAL_PORT_LPUART_FIRST
52 && identifier < SERIAL_PORT_LPUART_FIRST + SERIAL_LPUART_MAX) {
53 const unsigned idx = identifier - SERIAL_PORT_LPUART_FIRST;
54 if (BIT(idx) & SERIAL_LPUART_MASK) {
55 return SERIALTYPE_LPUART;
56 } else {
57 // no other type in this range
58 return SERIALTYPE_INVALID;
61 #endif
62 #ifdef USE_SOFTSERIAL
63 if (identifier >= SERIAL_PORT_SOFTSERIAL_FIRST && identifier < SERIAL_PORT_SOFTSERIAL_FIRST + SERIAL_SOFTSERIAL_MAX) {
64 // sotserials always start from 1, without holes
65 return SERIALTYPE_SOFTSERIAL;
67 #endif
68 return SERIALTYPE_INVALID;
71 static const struct SerialTypeInfo {
72 resourceOwner_e owner;
73 serialPortIdentifier_e firstId;
74 int8_t resourceOffset;
75 } serialTypeMap[] = {
76 [SERIALTYPE_USB_VCP] = { OWNER_FREE /* no owner*/, SERIAL_PORT_USB_VCP, -1 },
77 [SERIALTYPE_UART] = { OWNER_SERIAL_TX, SERIAL_PORT_UART_FIRST, RESOURCE_UART_OFFSET },
78 [SERIALTYPE_LPUART] = { OWNER_LPUART_TX, SERIAL_PORT_LPUART_FIRST, RESOURCE_LPUART_OFFSET },
79 [SERIALTYPE_SOFTSERIAL] = { OWNER_SOFTSERIAL_TX, SERIAL_PORT_SOFTSERIAL_FIRST, RESOURCE_SOFTSERIAL_OFFSET },
82 STATIC_ASSERT(ARRAYLEN(serialTypeMap) == SERIALTYPE_COUNT, "type table mismatch");
84 static const struct SerialTypeInfo* serialTypeInfo(serialPortIdentifier_e identifier)
86 const serialType_e type = serialType(identifier);
87 if (type == SERIALTYPE_INVALID) {
88 return NULL;
90 return serialTypeMap + type;
93 // resourceOwner_e for this serial (UART/LPUART/SOFTSERIAL/..)
94 // Used together with serialOwnerIndex to identify claimed resources
95 // Tx member is returned, Rx is always Tx + 1
96 // OWNER_FREE is returned for serials without owner (VCP)
97 resourceOwner_e serialOwnerTxRx(serialPortIdentifier_e identifier)
99 const struct SerialTypeInfo* inf = serialTypeInfo(identifier);
100 return inf ? inf->owner : OWNER_FREE;
103 // return index used to claim given resource. Returned value is 1 based, for IOInit and similar
104 // 0 is returned when given port is not defined or if it is singleton port (USB)
105 int serialOwnerIndex(serialPortIdentifier_e identifier)
107 const struct SerialTypeInfo* inf = serialTypeInfo(identifier);
108 if (!inf || inf->owner == OWNER_FREE) {
109 return 0;
111 return RESOURCE_INDEX(identifier - inf->firstId);
114 // map identifier into index used to store port resources:
115 // pins(RX,TX), external inversion, port DMA configuration
116 // order is UART, LPUART, SOFTSERIAL, with each group using index
117 // coresponding to port name (UART1 -> 0, UART5 -> 4, but LPUART -> 5 if
118 // there is no UART6 and higher on given target.
119 // -1 is returned if given port is not defined or is not using resources
120 // some code uses this ordering for optimizations, be carefull if reordering is necessary
121 int serialResourceIndex(serialPortIdentifier_e identifier)
123 const struct SerialTypeInfo* inf = serialTypeInfo(identifier);
124 if (!inf || inf->resourceOffset < 0) {
125 return -1;
127 return identifier - inf->firstId + inf->resourceOffset;