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
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/>.
28 #include "io/serial.h"
30 // convert identifier into port type
31 serialType_e
serialType(serialPortIdentifier_e identifier
)
34 if (identifier
== SERIAL_PORT_USB_VCP
) {
35 return SERIALTYPE_USB_VCP
;
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
;
45 // no other type in this range
46 return SERIALTYPE_INVALID
;
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
;
57 // no other type in this range
58 return SERIALTYPE_INVALID
;
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
;
68 return SERIALTYPE_INVALID
;
71 static const struct SerialTypeInfo
{
72 resourceOwner_e owner
;
73 serialPortIdentifier_e firstId
;
74 int8_t resourceOffset
;
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
) {
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
) {
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) {
127 return identifier
- inf
->firstId
+ inf
->resourceOffset
;