Skip to content

Commit d33c0ab

Browse files
Fix UART configuration to handle length, parity and stop bits (#2834)
1 parent 0edc862 commit d33c0ab

File tree

2 files changed

+135
-66
lines changed

2 files changed

+135
-66
lines changed

targets/AzureRTOS/ST/_nanoCLR/System.IO.Ports/sys_io_ser_native_System_IO_Ports_SerialPort.cpp

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ static void RxChar(UARTDriver *uartp, uint16_t c)
214214

215215
// store this into the UART Rx buffer
216216

217-
// push char to ring buffer
218-
// don't care about the success of the operation, if it's full we are droping the char anyway
217+
// push char to the ring buffer
218+
// ignore the success of the operation, if it's full we are dropping the char anyway.
219219
palUart->RxRingBuffer.Push((uint8_t)c);
220220

221221
// is there a read operation going on?
@@ -243,11 +243,12 @@ static void RxChar(UARTDriver *uartp, uint16_t c)
243243
// no read operation ongoing, so fire an event, if the available bytes are above the threshold
244244
if (palUart->RxRingBuffer.Length() >= palUart->ReceivedBytesThreshold)
245245
{
246-
// post a managed event with the port index and event code (check if this is the watch char or just another
247-
// another)
248-
// TODO: check if callbacks are registered so this is called only if there is anyone listening otherwise
249-
// don't bother for that to happen ChibiOS callback has to accept arg which we would passing the GpioPin
250-
// CLR_RT_HeapBlock (see Gpio handler) check http://www.chibios.com/forum/viewtopic.php?f=36&t=4798
246+
// Post a managed event with the port index and event code (check if there is a watch
247+
// char in the buffer or just any char)
248+
// FIXME: check if callbacks are registered so this is called only if there is anyone listening otherwise
249+
// don't bother.
250+
// TODO: For that to happen ChibiOS callback has to accept arg which we would passing the GpioPin
251+
// Notes: CLR_RT_HeapBlock (Gpio handler) See: http://www.chibios.com/forum/viewtopic.php?f=36&t=4798
251252
PostManagedEvent(
252253
EVENT_SERIAL,
253254
0,
@@ -977,67 +978,99 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeConfig___VOI
977978
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
978979
}
979980

980-
// setup configuration
981+
// Setup configuration
981982

982-
// data bits @ CR1:M1&M0
983+
// Check dataBits validity
983984
switch ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4)
984985
{
985-
// case 5:
986-
// // palUart->Uart_cfg.cr1 |= UART_DATA_5_BITS;
987-
// break;
988-
989-
// case 6:
990-
// // palUart->Uart_cfg.cr1 |= UART_DATA_6_BITS;
991-
// break;
992-
993986
case 7:
994-
// FIXME
995-
// palUart->Uart_cfg.cr1 |= USART_CR1_DATA7;
996-
break;
997-
998987
case 8:
999-
// FIXME
1000-
// palUart->Uart_cfg.cr1 |= USART_CR1_DATA8;
988+
// We handle this along with parity.
1001989
break;
1002990

1003991
default:
1004-
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
992+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
1005993
}
1006994

1007-
// parity
995+
// parity + data bits @ CR1:M1&M0 registers
1008996
switch ((Parity)pThis[FIELD___parity].NumericByRef().s4)
1009997
{
1010998
case Parity_None:
1011999
palUart->Uart_cfg.cr1 &= ~(USART_CR1_PCE | USART_CR1_PS | USART_CR1_M);
1000+
1001+
if ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4 == 7)
1002+
{
1003+
#ifdef USART_CR1_M1
1004+
palUart->Uart_cfg.cr1 |= USART_CR1_M1;
1005+
#else
1006+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
1007+
#endif
1008+
}
10121009
break;
1010+
10131011
case Parity_Even:
1012+
1013+
if ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4 == 8)
1014+
{
10141015
#ifdef USART_CR1_M0
1015-
// cope with F3 and F7 where there are 2 bits in CR1_M
1016-
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
1016+
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
10171017
#else
1018-
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1018+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
10191019
#endif
1020+
}
1021+
else
1022+
{
1023+
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1024+
}
1025+
10201026
palUart->Uart_cfg.cr1 &= ~USART_CR1_PS;
10211027
break;
1028+
10221029
case Parity_Odd:
1023-
// setting USART_CR1_M ensures extra bit is used as parity
1024-
// not last bit of data
1030+
1031+
if ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4 == 8)
1032+
{
10251033
#ifdef USART_CR1_M0
1026-
// cope with F3 and F7 where there are 2 bits in CR1_M
1027-
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
1034+
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
10281035
#else
1029-
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1036+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
10301037
#endif
1038+
}
1039+
else
1040+
{
1041+
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1042+
}
1043+
10311044
palUart->Uart_cfg.cr1 |= USART_CR1_PS;
10321045
break;
1046+
10331047
default:
10341048
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
10351049
}
10361050

1037-
// Check RS485 mode is not selected as currently not supported
1038-
if ((SerialMode)pThis[FIELD___mode].NumericByRef().s4 != SerialMode_Normal)
1051+
// Set the serial mode
1052+
switch ((SerialMode)pThis[FIELD___mode].NumericByRef().s4)
10391053
{
1040-
NANOCLR_SET_AND_LEAVE(CLR_E_NOTIMPL);
1054+
case SerialMode_Normal:
1055+
break;
1056+
1057+
case SerialMode_RS485:
1058+
#ifdef USART_CR3_DEM
1059+
// Set Driver Enable Mode
1060+
palUart->Uart_cfg.cr3 |= USART_CR3_DEM;
1061+
// Set Driver Enable Polarity
1062+
palUart->Uart_cfg.cr3 |= USART_CR3_DEP;
1063+
// Auto-RTS delay - set to maximum
1064+
palUart->Uart_cfg.cr1 |= USART_CR1_DEDT;
1065+
// Auto-RTS delay - set to maximum
1066+
palUart->Uart_cfg.cr1 |= USART_CR1_DEAT;
1067+
#else
1068+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
1069+
#endif
1070+
break;
1071+
1072+
default:
1073+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
10411074
}
10421075

10431076
// stop bits @ CR2:STOP1&STOP0
@@ -1049,9 +1082,11 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeConfig___VOI
10491082
case StopBits_One:
10501083
// already set with the above
10511084
break;
1085+
10521086
case StopBits_OnePointFive:
10531087
palUart->Uart_cfg.cr2 |= USART_CR2_STOP_1 + USART_CR2_STOP_0;
10541088
break;
1089+
10551090
case StopBits_Two:
10561091
palUart->Uart_cfg.cr2 |= USART_CR2_STOP_1;
10571092
break;

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

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -980,67 +980,99 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeConfig___VOI
980980
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
981981
}
982982

983-
// setup configuration
983+
// Setup configuration
984984

985-
// data bits @ CR1:M1&M0
985+
// Check dataBits validity
986986
switch ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4)
987987
{
988-
// case 5:
989-
// // palUart->Uart_cfg.cr1 |= UART_DATA_5_BITS;
990-
// break;
991-
992-
// case 6:
993-
// // palUart->Uart_cfg.cr1 |= UART_DATA_6_BITS;
994-
// break;
995-
996988
case 7:
997-
// FIXME
998-
// palUart->Uart_cfg.cr1 |= USART_CR1_DATA7;
999-
break;
1000-
1001989
case 8:
1002-
// FIXME
1003-
// palUart->Uart_cfg.cr1 |= USART_CR1_DATA8;
990+
// We handle this along with parity.
1004991
break;
1005992

1006993
default:
1007-
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
994+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
1008995
}
1009996

1010-
// parity
997+
// parity + data bits @ CR1:M1&M0 registers
1011998
switch ((Parity)pThis[FIELD___parity].NumericByRef().s4)
1012999
{
10131000
case Parity_None:
10141001
palUart->Uart_cfg.cr1 &= ~(USART_CR1_PCE | USART_CR1_PS | USART_CR1_M);
1002+
1003+
if ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4 == 7)
1004+
{
1005+
#ifdef USART_CR1_M1
1006+
palUart->Uart_cfg.cr1 |= USART_CR1_M1;
1007+
#else
1008+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
1009+
#endif
1010+
}
10151011
break;
1012+
10161013
case Parity_Even:
1014+
1015+
if ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4 == 8)
1016+
{
10171017
#ifdef USART_CR1_M0
1018-
// cope with F3 and F7 where there are 2 bits in CR1_M
1019-
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
1018+
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
10201019
#else
1021-
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1020+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
10221021
#endif
1022+
}
1023+
else
1024+
{
1025+
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1026+
}
1027+
10231028
palUart->Uart_cfg.cr1 &= ~USART_CR1_PS;
10241029
break;
1030+
10251031
case Parity_Odd:
1026-
// setting USART_CR1_M ensures extra bit is used as parity
1027-
// not last bit of data
1032+
1033+
if ((uint16_t)pThis[FIELD___dataBits].NumericByRef().s4 == 8)
1034+
{
10281035
#ifdef USART_CR1_M0
1029-
// cope with F3 and F7 where there are 2 bits in CR1_M
1030-
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
1036+
palUart->Uart_cfg.cr1 |= USART_CR1_M0 | USART_CR1_PCE;
10311037
#else
1032-
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1038+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
10331039
#endif
1040+
}
1041+
else
1042+
{
1043+
palUart->Uart_cfg.cr1 |= USART_CR1_M | USART_CR1_PCE;
1044+
}
1045+
10341046
palUart->Uart_cfg.cr1 |= USART_CR1_PS;
10351047
break;
1048+
10361049
default:
10371050
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
10381051
}
10391052

1040-
// Check RS485 mode is not selected as currently not supported
1041-
if ((SerialMode)pThis[FIELD___mode].NumericByRef().s4 != SerialMode_Normal)
1053+
// Set the serial mode
1054+
switch ((SerialMode)pThis[FIELD___mode].NumericByRef().s4)
10421055
{
1043-
NANOCLR_SET_AND_LEAVE(CLR_E_NOTIMPL);
1056+
case SerialMode_Normal:
1057+
break;
1058+
1059+
case SerialMode_RS485:
1060+
#ifdef USART_CR3_DEM
1061+
// Set Driver Enable Mode
1062+
palUart->Uart_cfg.cr3 |= USART_CR3_DEM;
1063+
// Set Driver Enable Polarity
1064+
palUart->Uart_cfg.cr3 |= USART_CR3_DEP;
1065+
// Auto-RTS delay - set to maximum
1066+
palUart->Uart_cfg.cr1 |= USART_CR1_DEDT;
1067+
// Auto-RTS delay - set to maximum
1068+
palUart->Uart_cfg.cr1 |= USART_CR1_DEAT;
1069+
#else
1070+
NANOCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED);
1071+
#endif
1072+
break;
1073+
1074+
default:
1075+
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
10441076
}
10451077

10461078
// stop bits @ CR2:STOP1&STOP0
@@ -1052,9 +1084,11 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeConfig___VOI
10521084
case StopBits_One:
10531085
// already set with the above
10541086
break;
1087+
10551088
case StopBits_OnePointFive:
10561089
palUart->Uart_cfg.cr2 |= USART_CR2_STOP_1 + USART_CR2_STOP_0;
10571090
break;
1091+
10581092
case StopBits_Two:
10591093
palUart->Uart_cfg.cr2 |= USART_CR2_STOP_1;
10601094
break;
@@ -1171,7 +1205,7 @@ HRESULT Library_sys_io_ser_native_System_IO_Ports_SerialPort::NativeWriteString_
11711205

11721206
bool isNewAllocation = false;
11731207
char *buffer = NULL;
1174-
uint32_t bufferLength;
1208+
uint32_t bufferLength = 0;
11751209
int32_t length = 0;
11761210

11771211
// get a pointer to the managed object instance and check that it's not NULL

0 commit comments

Comments
 (0)