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_USART1
&& identifier
< SERIAL_PORT_USART1
+ SERIAL_UART_MAX
) {
40 const unsigned idx
= identifier
- SERIAL_PORT_USART1
;
41 if (BIT(idx
) & SERIAL_UART_MASK
) {
42 return SERIALTYPE_UART
;
44 // no other type in this range
45 return SERIALTYPE_INVALID
;
50 if (identifier
>= SERIAL_PORT_LPUART1
&& identifier
< SERIAL_PORT_LPUART1
+ SERIAL_LPUART_MAX
) {
51 const unsigned idx
= identifier
- SERIAL_PORT_LPUART1
;
52 if (BIT(idx
) & SERIAL_LPUART_MASK
) {
53 return SERIALTYPE_LPUART
;
55 // no other type in this range
56 return SERIALTYPE_INVALID
;
61 if (identifier
>= SERIAL_PORT_SOFTSERIAL1
&& identifier
< SERIAL_PORT_SOFTSERIAL1
+ SERIAL_SOFTSERIAL_MAX
) {
62 // sotserials always start from 1, without holes
63 return SERIALTYPE_SOFTSERIAL
;
66 return SERIALTYPE_INVALID
;
69 static const struct SerialTypeInfo
{
70 resourceOwner_e owner
;
71 serialPortIdentifier_e firstId
;
72 int8_t resourceOffset
;
74 [SERIALTYPE_USB_VCP
] = { OWNER_FREE
/* no owner*/, SERIAL_PORT_USB_VCP
, -1 },
75 [SERIALTYPE_UART
] = { OWNER_SERIAL_TX
, SERIAL_PORT_USART1
, RESOURCE_UART_OFFSET
},
76 [SERIALTYPE_LPUART
] = { OWNER_LPUART_TX
, SERIAL_PORT_LPUART1
, RESOURCE_LPUART_OFFSET
},
77 [SERIALTYPE_SOFTSERIAL
] = { OWNER_SOFTSERIAL_TX
, SERIAL_PORT_SOFTSERIAL1
, RESOURCE_SOFTSERIAL_OFFSET
},
80 STATIC_ASSERT(ARRAYLEN(serialTypeMap
) == SERIALTYPE_COUNT
, "type table mismatch");
82 static const struct SerialTypeInfo
* serialTypeInfo(serialPortIdentifier_e identifier
)
84 const serialType_e type
= serialType(identifier
);
85 if (type
== SERIALTYPE_INVALID
) {
88 return serialTypeMap
+ type
;
91 // resourceOwner_e for this serial (UART/LPUART/SOFTSERIAL/..)
92 // Used together with serialOwnerIndex to identify claimed resources
93 // Tx member is returned, Rx is always Tx + 1
94 // OWNER_FREE is returned for serials without owner (VCP)
95 resourceOwner_e
serialOwnerTxRx(serialPortIdentifier_e identifier
)
97 const struct SerialTypeInfo
* inf
= serialTypeInfo(identifier
);
98 return inf
? inf
->owner
: OWNER_FREE
;
101 // return index used to claim given resource. Returned value is 1 based, for IOInit and similar
102 // 0 is returned when given port is not defined or if it is singleton port (USB)
103 int serialOwnerIndex(serialPortIdentifier_e identifier
)
105 const struct SerialTypeInfo
* inf
= serialTypeInfo(identifier
);
106 if (!inf
|| inf
->owner
== OWNER_FREE
) {
109 return RESOURCE_INDEX(identifier
- inf
->firstId
);
112 // map identifier into index used to store port resources:
113 // pins(RX,TX), external inversion, port DMA configuration
114 // order is UART, LPUART, SOFTSERIAL, with each group using index
115 // coresponding to port name (UART1 -> 0, UART5 -> 4, but LPUART -> 5 if
116 // there is no UART6 and higher on given target.
117 // -1 is returned if given port is not defined or is not using resources
118 // some code uses this ordering for optimizations, be carefull if reordering is necessary
119 int serialResourceIndex(serialPortIdentifier_e identifier
)
121 const struct SerialTypeInfo
* inf
= serialTypeInfo(identifier
);
122 if (!inf
|| inf
->resourceOffset
< 0) {
125 return identifier
- inf
->firstId
+ inf
->resourceOffset
;