From f9eaa685adf96b18612d23b320c666adb7f62664 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 16 Jan 2024 08:17:51 +0000 Subject: [PATCH 1/4] hosted/serial_win: Added some documentation to serial_open() --- src/platforms/hosted/serial_win.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/platforms/hosted/serial_win.c b/src/platforms/hosted/serial_win.c index 8c7b5c4fa74..874b215ae9e 100644 --- a/src/platforms/hosted/serial_win.c +++ b/src/platforms/hosted/serial_win.c @@ -173,12 +173,14 @@ static char *find_bmp_device(const bmda_cli_options_s *const cl_opts, const char bool serial_open(const bmda_cli_options_s *const cl_opts, const char *const serial) { + /* Figure out what the device node is for the requested device */ char *const device = find_bmp_device(cl_opts, serial); if (!device) { DEBUG_ERROR("Unexpected problems finding the device!\n"); return false; } + /* Try and open the node so we can start communications with the the device */ port_handle = CreateFile(device, /* NT path to the device */ GENERIC_READ | GENERIC_WRITE, /* Read + Write */ 0, /* No Sharing */ @@ -188,11 +190,13 @@ bool serial_open(const bmda_cli_options_s *const cl_opts, const char *const seri NULL); /* Do not use a template file */ free(device); + /* If opening the device node failed for any reason, error out early */ if (port_handle == INVALID_HANDLE_VALUE) { handle_dev_error(port_handle, "opening device"); return false; } + /* Get the current device state from the device */ DCB serial_params = {0}; serial_params.DCBlength = sizeof(serial_params); if (!GetCommState(port_handle, &serial_params)) { @@ -200,6 +204,7 @@ bool serial_open(const bmda_cli_options_s *const cl_opts, const char *const seri return false; } + /* Adjust the device state to enable communications to work and be in the right mode */ serial_params.fParity = FALSE; serial_params.fOutxCtsFlow = FALSE; serial_params.fOutxDsrFlow = FALSE; @@ -268,7 +273,6 @@ static ssize_t bmda_read_more_data(const uint32_t end_time) } /* XXX: We should either return size_t or bool */ -/* XXX: This needs documenting that it can abort the program with exit(), or the error handling fixed */ int platform_buffer_read(void *const data, const size_t length) { char *const buffer = (char *)data; From f1c715d676959a1b6fc0dd2f2ef51806189a46d7 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 16 Jan 2024 08:18:43 +0000 Subject: [PATCH 2/4] hosted/serial_win: Make sure that the receive buffer is empty at the conclusion of serial_open() --- src/platforms/hosted/serial_win.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platforms/hosted/serial_win.c b/src/platforms/hosted/serial_win.c index 874b215ae9e..bcafe07f8ba 100644 --- a/src/platforms/hosted/serial_win.c +++ b/src/platforms/hosted/serial_win.c @@ -230,6 +230,9 @@ bool serial_open(const bmda_cli_options_s *const cl_opts, const char *const seri handle_dev_error(port_handle, "setting communication timeouts for device"); return false; } + + /* Having adjusted the line state, discard anything sat in the receive buffer */ + PurgeComm(port_handle, PURGE_RXCLEAR); return true; } From 3a6022dd682057b411f424bd9b5aa3a979b12020 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 16 Jan 2024 08:19:12 +0000 Subject: [PATCH 3/4] hosted/serial_win: Fixed and documented the `COMMTIMEOUTS` configuration --- src/platforms/hosted/serial_win.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/platforms/hosted/serial_win.c b/src/platforms/hosted/serial_win.c index bcafe07f8ba..759dce7d48e 100644 --- a/src/platforms/hosted/serial_win.c +++ b/src/platforms/hosted/serial_win.c @@ -221,11 +221,19 @@ bool serial_open(const bmda_cli_options_s *const cl_opts, const char *const seri } COMMTIMEOUTS timeouts = {0}; - timeouts.ReadIntervalTimeout = 10; - timeouts.ReadTotalTimeoutConstant = 10; - timeouts.ReadTotalTimeoutMultiplier = 10; - timeouts.WriteTotalTimeoutConstant = 10; - timeouts.WriteTotalTimeoutMultiplier = 10; + /* + * Turn off read timeouts so that ReadFill() instantly returns even if there's no data waiting + * (we implement our own mechanism below for that case as we only want to wait if we get no data) + */ + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + /* + * Configure an exactly 100ms write timeout - we want this triggering to be fatal as something + * has gone very wrong if we ever hit this. + */ + timeouts.WriteTotalTimeoutConstant = 100; + timeouts.WriteTotalTimeoutMultiplier = 0; if (!SetCommTimeouts(port_handle, &timeouts)) { handle_dev_error(port_handle, "setting communication timeouts for device"); return false; From f528849813f31060bf6e68946ba1ea2557a95845 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 16 Jan 2024 08:19:56 +0000 Subject: [PATCH 4/4] hosted/serial_win: Fixed the bmda_read_more_data() logic now we've eliminated read timeouts from the ReadFile() behaviour --- src/platforms/hosted/serial_win.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platforms/hosted/serial_win.c b/src/platforms/hosted/serial_win.c index 759dce7d48e..59522e3c4a7 100644 --- a/src/platforms/hosted/serial_win.c +++ b/src/platforms/hosted/serial_win.c @@ -266,6 +266,11 @@ bool platform_buffer_write(const void *const data, const size_t length) static ssize_t bmda_read_more_data(const uint32_t end_time) { + // Try to wait for up to 100ms for data to become available + if (WaitForSingleObject(port_handle, 100) != WAIT_OBJECT_0) { + DEBUG_ERROR("Timeout while waiting for BMP response: %lu\n", GetLastError()); + return -4; + } DWORD bytes_received = 0; /* Try to fill the read buffer, and if that fails, bail */ if (!ReadFile(port_handle, read_buffer, READ_BUFFER_LENGTH, &bytes_received, NULL)) { @@ -291,7 +296,7 @@ int platform_buffer_read(void *const data, const size_t length) const uint32_t end_time = start_time + cortexm_wait_timeout; /* Drain the buffer for the remote till we see a start-of-response byte */ for (char response = 0; response != REMOTE_RESP;) { - if (read_buffer_offset == read_buffer_fullness) { + while (read_buffer_offset == read_buffer_fullness) { const ssize_t result = bmda_read_more_data(end_time); if (result < 0) return result;