Skip to content

Commit af84129

Browse files
authored
SIYI FR Mini RX as TX (ExpressLRS#746)
* Add FM30_RX_MINI_AS_TX_via_STLINK * Use UART2 for RXasTX, change variant Serial to UART1 * Explicity init UART gpio speed / output type * Defect and ignore UART RX bytes with framing errors * FM30 Mini RX as TX bootloader * HDSEL is set by Serial.setHalfDuplex() * Pin platform version 13 for FM30 mini as TX * Add enableHalfDuplexRx() to native serial mock * Remove redundant line * Add TX/RX_CONFIG_MAGIC * Switch UART2TX to PULLDOWN Since we're inverted we should idle low eh? Fixes T-Lite connection TO handset not working except in bootloader. FROM handset was working. * Set A2 to pulldown, not A1 * Forgot second LL_GPIO_SetPinPull
1 parent 138a42d commit af84129

12 files changed

Lines changed: 107 additions & 33 deletions

File tree

7.9 KB
Binary file not shown.

src/bootloader/src/Src/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ void GPIO_SetupPin(GPIO_TypeDef *regs, uint32_t pos, uint32_t mode, int pullup)
165165
} else {
166166
mode = (mode >> 4) & 0xff;
167167
LL_GPIO_SetPinMode(regs, bit_pos, LL_GPIO_MODE_ALTERNATE);
168+
LL_GPIO_SetPinOutputType(regs, bit_pos, LL_GPIO_OUTPUT_PUSHPULL);
169+
LL_GPIO_SetPinSpeed(regs, bit_pos, LL_GPIO_SPEED_FREQ_LOW);
168170
LL_GPIO_SetPinPull(regs, bit_pos, (0 < pullup ? LL_GPIO_PULL_UP : LL_GPIO_PULL_DOWN));
169171
if (pos & 0x8) {
170172
LL_GPIO_SetAFPin_8_15(regs, bit_pos, mode);

src/bootloader/src/Src/uart.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,15 @@ void uart_flush(void)
171171

172172
void USARTx_IRQ_handler(USART_TypeDef * uart)
173173
{
174-
uint32_t SR = uart->StatReg, CR = uart->CR1;
174+
uint32_t CR = uart->CR1;
175+
uint32_t SR = uart->StatReg;
175176
/* Check for RX data */
176177
if (SR & RX_ISR_LST) {
178+
// Always read even if there is an error bit set, as this resets the error bits
177179
uint8_t data = (uint8_t)LL_USART_ReceiveData8(uart);
178-
if (CR & USART_CR1_RXNEIE) {
180+
// If RX is in interrupt mode, the RX not-empty bit is set, and the received byte
181+
// has no framing errors (framing errors still generate RXNE), add to the RX fifo
182+
if ((CR & USART_CR1_RXNEIE) && (SR & USART_SR_RXNE) && !(SR & USART_ISR_FE)) {
179183
uint8_t next = rx_head;
180184
if ((next + 1) != rx_tail) {
181185
rx_buffer[rx_head++] = data;
@@ -184,9 +188,9 @@ void USARTx_IRQ_handler(USART_TypeDef * uart)
184188
}
185189
}
186190

187-
// Check if TX is enabled and TX Empty IRQ triggered
188-
if ((SR & (USART_SR_TXE)) && (CR & USART_CR1_TXEIE)) {
189-
// Check if data available
191+
// If TX is in interrupt mode, and TX empty bit set
192+
if ((CR & USART_CR1_TXEIE) && (SR & USART_SR_TXE)) {
193+
// Check if data in TX fifo still to send, else switch to RX mode
190194
if (tx_head <= tx_tail)
191195
duplex_state_set(DUPLEX_RX);
192196
else

src/bootloader/src/platformio.ini

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -623,25 +623,39 @@ build_flags =
623623
; -Wl,--defsym=FLASH_OFFSET=0x0
624624
; ${generic.flags}
625625

626-
[env:FM30_MINI]
626+
[fm30_mini_common]
627627
board = eval_f373vc
628628
board_upload.maximum_size = 16384
629-
build_flags =
629+
flags =
630630
-D STM32F3xx # standard board defines STM32F3 only
631631
-D MCU_TYPE=FM30_MINI
632632
-D PIN_LED_RED="B,6"
633633
-D LED_RED_INVERTED=1
634634
-D PIN_LED_GREEN="B,7"
635635
-D LED_GREEN_INVERTED=1
636-
# XMODEM (Betaflight Passthrough)= UART2
637-
-D XMODEM=1
638-
-D UART_RX_PIN="A,3"
639-
-D UART_TX_PIN="A,2"
640-
-D UART_BAUD=420000
641636
-D FLASH_APP_OFFSET=0x4000u
642637
-Wl,--defsym=RAM_SIZE=32K
643638
-Wl,--defsym=FLASH_SIZE=16K
644639
-Wl,--defsym=FLASH_OFFSET=0x0
645640
${generic.flags}
646641

642+
[env:FM30_MINI]
643+
extends = fm30_mini_common
644+
build_flags = ${fm30_mini_common.flags}
645+
# XMODEM (Betaflight Passthrough)= UART2
646+
-D XMODEM=1
647+
-D UART_RX_PIN="A,3"
648+
-D UART_TX_PIN="A,2"
649+
-D UART_BAUD=420000
650+
651+
[env:FM30_MINI_RXTX]
652+
# RX as TX, only difference is the protocol is for OpenTX flashing, not BF passthrough
653+
extends = fm30_mini_common
654+
build_flags = ${fm30_mini_common.flags}
655+
# STK500 (OpenTX)= UART2
656+
-D STK500=1
657+
-D UART_TX_PIN="A,2"
658+
-D UART_BAUD=57600
659+
-D UART_INV=1
660+
647661
# ========================

src/include/native.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class HardwareSerial: public Stream {
4040
void flush() {}
4141
void end() {}
4242
void begin(int baud) {}
43+
void enableHalfDuplexRx() {}
4344

4445
// Print methods
4546
size_t write(uint8_t c) {return 1;}

src/include/targets.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -492,25 +492,29 @@ Designed by NamimnoRC
492492
#define GPIO_PIN_BLUETOOTH_EN PA8 // Bluetooth power on (active low)
493493
#define GPIO_PIN_UART1RX_INVERT PB6 // XOR chip
494494

495-
#elif defined(TARGET_RX_FM30_MINI)
496-
#define GPIO_PIN_NSS PA15 // or PB3?
495+
#elif defined(TARGET_RX_FM30_MINI) || defined(TARGET_TX_FM30_MINI)
496+
#define GPIO_PIN_NSS PA15
497497
#define GPIO_PIN_BUSY PE9
498498
#define GPIO_PIN_DIO1 PE8
499499
#define GPIO_PIN_MOSI PB5
500500
#define GPIO_PIN_MISO PB4
501501
#define GPIO_PIN_SCK PB3
502502
#define GPIO_PIN_RST PB2
503503
#define GPIO_PIN_TX_ENABLE PD8 // CTX on SE2431L
504-
#define GPIO_PIN_ANTENNA_SELECT PA8 // Low for left, high for right
505-
#define GPIO_PIN_RCSIGNAL_RX PA3 // UART2
506-
#define GPIO_PIN_RCSIGNAL_TX PA2 // UART2 NOTE: Not the "OUT" pinheader pad
507504
#define GPIO_PIN_LED_RED PB6
508505
#define GPIO_PIN_LED_GREEN PB7
509506
#define GPIO_PIN_DEBUG_RX PA10 // UART1
510507
#define GPIO_PIN_DEBUG_TX PA9 // UART1
511-
#define timerOffset 0
512508
#define GPIO_LED_RED_INVERTED 1
513509
#define GPIO_LED_GREEN_INVERTED 1
510+
#define GPIO_PIN_RCSIGNAL_TX PA2 // UART2 NOTE: Not the "OUT" pinheader pad
511+
#if defined(TARGET_RX_FM30_MINI)
512+
#define GPIO_PIN_RCSIGNAL_RX PA3 // UART2
513+
#define GPIO_PIN_ANTENNA_SELECT PA8 // Low for left, high for right
514+
#elif defined(TARGET_TX_FM30_MINI)
515+
#define GPIO_PIN_RCSIGNAL_RX PA2 // UART2 (half duplex)
516+
#define GPIO_PIN_ANT_CTRL_2 PA8 // Low for left, high for right
517+
#endif
514518
// Unused pins
515519
#define GPIO_PIN_UART1TX_INVERT PF6
516520

src/lib/CRSF/CRSF.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,29 @@ void CRSF::Begin()
120120
#elif defined(PLATFORM_STM32)
121121
Serial.println("Start STM32 R9M TX CRSF UART");
122122

123+
CRSF::Port.setTx(GPIO_PIN_RCSIGNAL_TX);
124+
CRSF::Port.setRx(GPIO_PIN_RCSIGNAL_RX);
125+
123126
#if defined(GPIO_PIN_BUFFER_OE) && (GPIO_PIN_BUFFER_OE != UNDEF_PIN)
124127
pinMode(GPIO_PIN_BUFFER_OE, OUTPUT);
125128
digitalWrite(GPIO_PIN_BUFFER_OE, LOW ^ GPIO_PIN_BUFFER_OE_INVERTED); // RX mode default
129+
#elif (GPIO_PIN_RCSIGNAL_TX == GPIO_PIN_RCSIGNAL_RX)
130+
CRSF::Port.setHalfDuplex();
126131
#endif
127132

128-
CRSF::Port.setTx(GPIO_PIN_RCSIGNAL_TX);
129-
CRSF::Port.setRx(GPIO_PIN_RCSIGNAL_RX);
130133
CRSF::Port.begin(CRSF_OPENTX_FAST_BAUDRATE);
131134

132135
#if defined(TARGET_TX_GHOST)
133136
USART1->CR1 &= ~USART_CR1_UE;
134137
USART1->CR3 |= USART_CR3_HDSEL;
135-
USART1->CR2 |= USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_SWAP; //inv
138+
USART1->CR2 |= USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_SWAP; //inverted/swapped
136139
USART1->CR1 |= USART_CR1_UE;
140+
#endif
141+
#if defined(TARGET_TX_FM30_MINI)
142+
LL_GPIO_SetPinPull(GPIOA, GPIO_PIN_2, LL_GPIO_PULL_DOWN); // default is PULLUP
143+
USART2->CR1 &= ~USART_CR1_UE;
144+
USART2->CR2 |= USART_CR2_RXINV | USART_CR2_TXINV; //inverted
145+
USART2->CR1 |= USART_CR1_UE;
137146
#endif
138147
Serial.println("STM32 CRSF UART LISTEN TASK STARTED");
139148
CRSF::Port.flush();
@@ -983,6 +992,8 @@ void ICACHE_RAM_ATTR CRSF::duplex_set_RX()
983992
#endif
984993
#elif defined(GPIO_PIN_BUFFER_OE) && (GPIO_PIN_BUFFER_OE != UNDEF_PIN)
985994
digitalWrite(GPIO_PIN_BUFFER_OE, LOW ^ GPIO_PIN_BUFFER_OE_INVERTED);
995+
#elif (GPIO_PIN_RCSIGNAL_TX == GPIO_PIN_RCSIGNAL_RX)
996+
CRSF::Port.enableHalfDuplexRx();
986997
#endif
987998
}
988999

@@ -1001,6 +1012,8 @@ void ICACHE_RAM_ATTR CRSF::duplex_set_TX()
10011012
#endif
10021013
#elif defined(GPIO_PIN_BUFFER_OE) && (GPIO_PIN_BUFFER_OE != UNDEF_PIN)
10031014
digitalWrite(GPIO_PIN_BUFFER_OE, HIGH ^ GPIO_PIN_BUFFER_OE_INVERTED);
1015+
#elif (GPIO_PIN_RCSIGNAL_TX == GPIO_PIN_RCSIGNAL_RX)
1016+
// writing to the port switches the mode
10041017
#endif
10051018
}
10061019

@@ -1043,9 +1056,15 @@ bool CRSF::UARTwdt()
10431056
#if defined(TARGET_TX_GHOST)
10441057
USART1->CR1 &= ~USART_CR1_UE;
10451058
USART1->CR3 |= USART_CR3_HDSEL;
1046-
USART1->CR2 |= USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_SWAP; //inv
1059+
USART1->CR2 |= USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_SWAP; //inverted/swapped
10471060
USART1->CR1 |= USART_CR1_UE;
10481061
#endif
1062+
#if defined(TARGET_TX_FM30_MINI)
1063+
LL_GPIO_SetPinPull(GPIOA, GPIO_PIN_2, LL_GPIO_PULL_DOWN); // default is PULLUP
1064+
USART2->CR1 &= ~USART_CR1_UE;
1065+
USART2->CR2 |= USART_CR2_RXINV | USART_CR2_TXINV; //inverted
1066+
USART2->CR1 |= USART_CR1_UE;
1067+
#endif
10491068
#endif
10501069
UARTcurrentBaud = UARTrequestedBaud;
10511070
duplex_set_RX();

src/src/config.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ TxConfig::Load()
99
m_eeprom->Get(0, m_config);
1010

1111
// Check if version number matches
12-
if (m_config.version != TX_CONFIG_VERSION)
12+
if (m_config.version != (uint32_t)(TX_CONFIG_VERSION | TX_CONFIG_MAGIC))
1313
{
1414
// If not, revert to defaults for this version
1515
Serial.println("EEPROM version mismatch! Resetting to defaults...");
@@ -21,7 +21,7 @@ TxConfig::Load()
2121

2222
void
2323
TxConfig::Commit()
24-
{
24+
{
2525
if (!m_modified)
2626
{
2727
// No changes
@@ -90,7 +90,7 @@ void
9090
TxConfig::SetDefaults()
9191
{
9292
expresslrs_mod_settings_s *const modParams = get_elrs_airRateConfig(RATE_DEFAULT);
93-
m_config.version = TX_CONFIG_VERSION;
93+
m_config.version = TX_CONFIG_VERSION | TX_CONFIG_MAGIC;
9494
SetSSID("");
9595
SetPassword("");
9696
for (int i=0 ; i<64 ; i++) {
@@ -135,7 +135,7 @@ RxConfig::Load()
135135
m_eeprom->Get(0, m_config);
136136

137137
// Check if version number matches
138-
if (m_config.version != RX_CONFIG_VERSION)
138+
if (m_config.version != (uint32_t)(RX_CONFIG_VERSION | RX_CONFIG_MAGIC))
139139
{
140140
// If not, revert to defaults for this version
141141
Serial.println("EEPROM version mismatch! Resetting to defaults...");
@@ -147,7 +147,7 @@ RxConfig::Load()
147147

148148
void
149149
RxConfig::Commit()
150-
{
150+
{
151151
if (!m_modified)
152152
{
153153
// No changes
@@ -205,7 +205,7 @@ RxConfig::SetModelId(uint8_t modelId)
205205
void
206206
RxConfig::SetDefaults()
207207
{
208-
m_config.version = RX_CONFIG_VERSION;
208+
m_config.version = RX_CONFIG_VERSION | RX_CONFIG_MAGIC;
209209
SetIsBound(false);
210210
SetPowerOnCounter(0);
211211
SetModelId(0xFF);

src/src/config.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
#pragma once
1+
#pragma once
22

33
#include "targets.h"
44
#include "elrs_eeprom.h"
55

6+
// CONFIG_MAGIC is ORed with CONFIG_VERSION in the version field
7+
#define TX_CONFIG_MAGIC (0b01 << 30)
8+
#define RX_CONFIG_MAGIC (0b10 << 30)
9+
610
#define TX_CONFIG_VERSION 3
711
#define RX_CONFIG_VERSION 3
812
#define UID_LEN 6

src/src/tx_main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,10 @@ void setup()
844844
pinMode(GPIO_PIN_UART1RX_INVERT, OUTPUT); // RX1 inverter (TX handled in CRSF)
845845
digitalWrite(GPIO_PIN_UART1RX_INVERT, HIGH);
846846
#endif
847+
#if defined(TARGET_TX_FM30_MINI)
848+
pinMode(GPIO_PIN_UART1TX_INVERT, OUTPUT); // TX1 inverter used for debug
849+
digitalWrite(GPIO_PIN_UART1TX_INVERT, LOW);
850+
#endif
847851

848852
#if defined(TARGET_TX_BETAFPV_2400_V1) || defined(TARGET_TX_BETAFPV_900_V1)
849853
button.buttonTriplePress = &EnterBindingMode;

0 commit comments

Comments
 (0)