Skip to content

Commit 80df4c1

Browse files
authored
Add support for UART signal level inversion (#2249)
1 parent 129c3d9 commit 80df4c1

9 files changed

+270
-2
lines changed

src/System.IO.Ports/sys_io_ser_native.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ static const CLR_RT_MethodHandler method_lookup[] =
4949
NULL,
5050
NULL,
5151
Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_BytesToRead___I4,
52+
Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_InvertSignalLevels___BOOLEAN,
53+
Library_sys_io_ser_native_System_IO_Ports_SerialPort::set_InvertSignalLevels___VOID__BOOLEAN,
5254
NULL,
5355
NULL,
5456
NULL,
@@ -93,9 +95,9 @@ static const CLR_RT_MethodHandler method_lookup[] =
9395
const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_IO_Ports =
9496
{
9597
"System.IO.Ports",
96-
0x564F2452,
98+
0xA67E6317,
9799
method_lookup,
98-
{ 100, 1, 2, 0 }
100+
{ 100, 1, 3, 0 }
99101
};
100102

101103
// clang-format on

src/System.IO.Ports/sys_io_ser_native.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ struct Library_sys_io_ser_native_System_IO_Ports_SerialPort
9494
static const int FIELD___newLine = 18;
9595

9696
NANOCLR_NATIVE_DECLARE(get_BytesToRead___I4);
97+
NANOCLR_NATIVE_DECLARE(get_InvertSignalLevels___BOOLEAN);
98+
NANOCLR_NATIVE_DECLARE(set_InvertSignalLevels___VOID__BOOLEAN);
9799
NANOCLR_NATIVE_DECLARE(Read___I4__SZARRAY_U1__I4__I4);
98100
NANOCLR_NATIVE_DECLARE(ReadExisting___STRING);
99101
NANOCLR_NATIVE_DECLARE(ReadLine___STRING);

src/System.IO.Ports/sys_io_ser_native_System_IO_Ports_SerialPort_stubs.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,29 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_BytesToRead___
1515
NANOCLR_NOCLEANUP();
1616
}
1717

18+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_InvertSignalLevels___BOOLEAN(CLR_RT_StackFrame &stack)
19+
{
20+
NANOCLR_HEADER();
21+
22+
(void)stack;
23+
24+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
25+
26+
NANOCLR_NOCLEANUP();
27+
}
28+
29+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::set_InvertSignalLevels___VOID__BOOLEAN(
30+
CLR_RT_StackFrame &stack)
31+
{
32+
NANOCLR_HEADER();
33+
34+
(void)stack;
35+
36+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
37+
38+
NANOCLR_NOCLEANUP();
39+
}
40+
1841
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::Read___I4__SZARRAY_U1__I4__I4(CLR_RT_StackFrame &stack)
1942
{
2043
NANOCLR_HEADER();

targets/ChibiOS/_nanoCLR/System.IO.Ports/sys_io_ser_native_System_IO_Ports_SerialPort.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,83 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_BytesToRead___
282282
NANOCLR_NOCLEANUP();
283283
}
284284

285+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_InvertSignalLevels___BOOLEAN(CLR_RT_StackFrame &stack)
286+
{
287+
NANOCLR_HEADER();
288+
289+
#if defined(USART_CR2_TXINV) && defined(USART_CR2_RXINV)
290+
291+
NF_PAL_UART *palUart = NULL;
292+
293+
// get a pointer to the managed object instance and check that it's not NULL
294+
CLR_RT_HeapBlock *pThis = stack.This();
295+
FAULT_ON_NULL(pThis);
296+
297+
if (pThis[FIELD___disposed].NumericByRef().u1 != 0)
298+
{
299+
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
300+
}
301+
302+
// get the driver for this SerialDevice
303+
palUart = GetUartPAL((int)pThis[FIELD___portIndex].NumericByRef().s4);
304+
if (palUart == NULL)
305+
{
306+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
307+
}
308+
309+
stack.SetResult_Boolean(palUart->SignalLevelsInverted);
310+
311+
#else
312+
313+
(void)stack;
314+
315+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
316+
317+
#endif
318+
319+
NANOCLR_NOCLEANUP();
320+
}
321+
322+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::set_InvertSignalLevels___VOID__BOOLEAN(
323+
CLR_RT_StackFrame &stack)
324+
{
325+
NANOCLR_HEADER();
326+
327+
#if defined(USART_CR2_TXINV) && defined(USART_CR2_RXINV)
328+
329+
NF_PAL_UART *palUart = NULL;
330+
331+
// get a pointer to the managed object instance and check that it's not NULL
332+
CLR_RT_HeapBlock *pThis = stack.This();
333+
FAULT_ON_NULL(pThis);
334+
335+
if (pThis[FIELD___disposed].NumericByRef().u1 != 0)
336+
{
337+
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
338+
}
339+
340+
// get the driver for this SerialDevice
341+
palUart = GetUartPAL((int)pThis[FIELD___portIndex].NumericByRef().s4);
342+
if (palUart == NULL)
343+
{
344+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
345+
}
346+
347+
palUart->SignalLevelsInverted = (bool)stack.Arg1().NumericByRef().u1;
348+
349+
// call config
350+
NativeConfig___VOID(stack);
351+
#else
352+
353+
(void)stack;
354+
355+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
356+
357+
#endif
358+
359+
NANOCLR_NOCLEANUP();
360+
}
361+
285362
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::Read___I4__SZARRAY_U1__I4__I4(CLR_RT_StackFrame &stack)
286363
{
287364
NANOCLR_HEADER();
@@ -907,6 +984,20 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeConfig___VOI
907984
break;
908985
}
909986

987+
#if defined(USART_CR2_TXINV) && defined(USART_CR2_RXINV)
988+
989+
// configure TX, RX signal levels
990+
if (palUart->SignalLevelsInverted)
991+
{
992+
palUart->Uart_cfg.cr2 |= USART_CR2_TXINV | USART_CR2_RXINV;
993+
}
994+
else
995+
{
996+
palUart->Uart_cfg.cr2 &= ~(USART_CR2_TXINV | USART_CR2_RXINV);
997+
}
998+
999+
#endif
1000+
9101001
// baud rate
9111002
palUart->Uart_cfg.speed = (int)pThis[FIELD___baudRate].NumericByRef().s4;
9121003

targets/ChibiOS/_nanoCLR/System.IO.Ports/sys_io_ser_native_target.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ typedef struct
2525

2626
uint8_t WatchChar;
2727
uint8_t NewLineChar;
28+
29+
bool SignalLevelsInverted;
30+
2831
} NF_PAL_UART;
2932

3033
////////////////////////////////////////////
@@ -115,6 +118,7 @@ extern uint8_t Uart8_RxBuffer[];
115118
Uart##num##_PAL.RxRingBuffer.Initialize(Uart##num##_PAL.RxBuffer, rx_buffer_size); \
116119
Uart##num##_PAL.WatchChar = 0; \
117120
Uart##num##_PAL.NewLineChar = 0; \
121+
Uart##num##_PAL.SignalLevelsInverted = false; \
118122
}
119123

120124
#else
@@ -136,6 +140,7 @@ extern uint8_t Uart8_RxBuffer[];
136140
Uart##num##_PAL.RxRingBuffer.Initialize(Uart##num##_PAL.RxBuffer, rx_buffer_size); \
137141
Uart##num##_PAL.WatchChar = 0; \
138142
Uart##num##_PAL.NewLineChar = 0; \
143+
Uart##num##_PAL.SignalLevelsInverted = false; \
139144
}
140145

141146
#endif

targets/ESP32/_nanoCLR/System.IO.Ports/sys_io_ser_native_System_IO_Ports_SerialPort.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,76 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_BytesToRead___
293293
NANOCLR_NOCLEANUP();
294294
}
295295

296+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_InvertSignalLevels___BOOLEAN(CLR_RT_StackFrame &stack)
297+
{
298+
NANOCLR_HEADER();
299+
300+
NF_PAL_UART *palUart = NULL;
301+
uart_port_t uart_num;
302+
303+
// get a pointer to the managed object instance and check that it's not NULL
304+
CLR_RT_HeapBlock *pThis = stack.This();
305+
FAULT_ON_NULL(pThis);
306+
307+
if (pThis[FIELD___disposed].NumericByRef().u1 != 0)
308+
{
309+
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
310+
}
311+
312+
// Get UART number for serial device
313+
uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[FIELD___portIndex].NumericByRef().s4);
314+
315+
// get pointer to PAL UART
316+
palUart = GetPalUartFromUartNum_sys(uart_num);
317+
if (palUart == NULL)
318+
{
319+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
320+
}
321+
322+
stack.SetResult_Boolean(palUart->SignalLevelsInverted);
323+
324+
NANOCLR_NOCLEANUP();
325+
}
326+
327+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::set_InvertSignalLevels___VOID__BOOLEAN(
328+
CLR_RT_StackFrame &stack)
329+
{
330+
NANOCLR_HEADER();
331+
332+
NF_PAL_UART *palUart = NULL;
333+
uart_port_t uart_num;
334+
335+
// get a pointer to the managed object instance and check that it's not NULL
336+
CLR_RT_HeapBlock *pThis = stack.This();
337+
FAULT_ON_NULL(pThis);
338+
339+
if (pThis[FIELD___disposed].NumericByRef().u1 != 0)
340+
{
341+
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
342+
}
343+
344+
// Get UART number for serial device
345+
uart_num = (uart_port_t)PORT_INDEX_TO_UART_NUM(pThis[FIELD___portIndex].NumericByRef().s4);
346+
347+
// get pointer to PAL UART
348+
palUart = GetPalUartFromUartNum_sys(uart_num);
349+
if (palUart == NULL)
350+
{
351+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
352+
}
353+
354+
// check if UART it's already opened
355+
if (palUart->SerialDevice)
356+
{
357+
// it is opened, so we can't change the signal levels
358+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
359+
}
360+
361+
palUart->SignalLevelsInverted = (bool)stack.Arg1().NumericByRef().u1;
362+
363+
NANOCLR_NOCLEANUP();
364+
}
365+
296366
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::Read___I4__SZARRAY_U1__I4__I4(CLR_RT_StackFrame &stack)
297367
{
298368
NANOCLR_HEADER();
@@ -839,6 +909,7 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeInit___VOID(
839909
palUart->TxOngoingCount = 0;
840910
palUart->RxBytesToRead = 0;
841911
palUart->NewLineChar = 0;
912+
palUart->SignalLevelsInverted = 0;
842913

843914
// Install driver
844915
esp_err = uart_driver_install(
@@ -1017,6 +1088,33 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeConfig___VOI
10171088
ESP_LOGE(TAG, "Failed to set UART parameters configuration");
10181089
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
10191090
}
1091+
1092+
////////////////////////////////////////////////////////////////////////////
1093+
// signal level inversion can only be configured when UART is not running //
1094+
////////////////////////////////////////////////////////////////////////////
1095+
1096+
// default is to not invert
1097+
uart_signal_inv_t inversionMmask = UART_SIGNAL_INV_DISABLE;
1098+
1099+
// get pointer to PAL UART
1100+
NF_PAL_UART *palUart = GetPalUartFromUartNum_sys(uart_num);
1101+
if (palUart == NULL)
1102+
{
1103+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
1104+
}
1105+
1106+
// check if signal levels are to be inverted
1107+
if (palUart->SignalLevelsInverted)
1108+
{
1109+
inversionMmask = (uart_signal_inv_t)(UART_SIGNAL_RXD_INV | UART_SIGNAL_TXD_INV);
1110+
}
1111+
1112+
// config signal inversion (or not)
1113+
if (uart_set_line_inverse(uart_num, inversionMmask) != ESP_OK)
1114+
{
1115+
ESP_LOGE(TAG, "Failed to set UART parameters configuration");
1116+
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
1117+
}
10201118
}
10211119

10221120
if (EnableXonXoff)

targets/ESP32/_nanoCLR/System.IO.Ports/sys_io_ser_native_target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef struct
2525
uint16_t RxBytesToRead;
2626

2727
bool IsLongRunning;
28+
bool SignalLevelsInverted;
2829

2930
uint8_t NewLineChar;
3031
} NF_PAL_UART;

targets/FreeRTOS/NXP/_nanoCLR/System.IO.Ports/sys_io_ser_native_System_IO_Ports_SerialPort.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,29 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_BytesToRead___
182182
NANOCLR_NOCLEANUP();
183183
}
184184

185+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_InvertSignalLevels___BOOLEAN(CLR_RT_StackFrame &stack)
186+
{
187+
NANOCLR_HEADER();
188+
189+
(void)stack;
190+
191+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
192+
193+
NANOCLR_NOCLEANUP();
194+
}
195+
196+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::set_InvertSignalLevels___VOID__BOOLEAN(
197+
CLR_RT_StackFrame &stack)
198+
{
199+
NANOCLR_HEADER();
200+
201+
(void)stack;
202+
203+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
204+
205+
NANOCLR_NOCLEANUP();
206+
}
207+
185208
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::Read___I4__SZARRAY_U1__I4__I4(CLR_RT_StackFrame &stack)
186209
{
187210
NANOCLR_HEADER();

targets/TI_SimpleLink/_nanoCLR/System.IO.Ports/sys_io_ser_native_System_IO_Ports_SerialPort.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,29 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_BytesToRead___
206206
NANOCLR_NOCLEANUP();
207207
}
208208

209+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::get_InvertSignalLevels___BOOLEAN(CLR_RT_StackFrame &stack)
210+
{
211+
NANOCLR_HEADER();
212+
213+
(void)stack;
214+
215+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
216+
217+
NANOCLR_NOCLEANUP();
218+
}
219+
220+
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::set_InvertSignalLevels___VOID__BOOLEAN(
221+
CLR_RT_StackFrame &stack)
222+
{
223+
NANOCLR_HEADER();
224+
225+
(void)stack;
226+
227+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
228+
229+
NANOCLR_NOCLEANUP();
230+
}
231+
209232
HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::Read___I4__SZARRAY_U1__I4__I4(CLR_RT_StackFrame &stack)
210233
{
211234
NANOCLR_HEADER();

0 commit comments

Comments
 (0)