-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebSerial not getting enough time to write to SerialPort #21581
Comments
Can you add a I imagine what is happening here is that the webserial API requires you to return to event loop in order to do what i needs to do. BTW is this code running in on the main browser thread? If so I guess you have to be returning to the event loops anyway. As always, could you share the full set of link flags you are using? |
Thank you for your reply! First I'll give some more context, I am porting avrdude to webassembly, and yes it runs on the main browser thread, but I get the same results using pthread. Here are my flags for with pthread:
And without:
My first thought was also that the write_data function was completed later or something but it is not sadly. But here is the updated code and respective output just to make sure. EM_ASYNC_JS(void, write_data, (EM_VAL data), {
data = new Uint8Array(Emval.toValue(data));
console.log("Sending: ", data);
const port = window.activePort;
await window.writeStream.ready;
await window.writeStream.write(data);
await window.writeStream.ready;
console.log("Data sent");
});
void serialPortWrite(const unsigned char *buf, size_t len) {
std::vector<unsigned char> data(buf, buf + len);
write_data(val(typed_memory_view(data.size(), data.data())).as_handle());
printf("Data sent from C\n");
emscripten_sleep(0);
} Output: |
What is your program doing right after the |
It runs some more webassembly code it sends the 48,32 packet three times to my arduino. When it is done with those operations it will read the return data of the arduino. EM_ASYNC_JS(void, read_data, (int timeoutMs), {
const reader = window.activePort.readable.getReader();
console.log("Reading data");
async function receive() {
const { value } = await reader.read();
return value;
}
async function timeout(timeoutMs) {
await new Promise(resolve => setTimeout(resolve, timeoutMs));
return "timeout";
}
var returnBuffer = new Uint8Array();
while (true) {
let result = await Promise.race([receive(), timeout(timeoutMs)]);
if (result instanceof Uint8Array) {
// check if it is twice the same data so check if the first half is the same as the second half if so remove the second half
let firstHalf = result.slice(0, result.length / 2);
let secondHalf = result.slice(result.length / 2, result.length);
if (firstHalf.every((value, index) => value === secondHalf[index])) {
result = firstHalf;
}
console.log("Received: ", result);
const ptr = window.funcs._malloc(result.length * Uint8Array.BYTES_PER_ELEMENT);
window.funcs.HEAPU8.set(result, ptr);
// Call the C++ function with the pointer and the length of the array
window.funcs._dataCallback(ptr, result.length);
break;
} else {
console.log("Timeout", result);
break;
}
}
reader.releaseLock();
return;
});
int serialPortRecv(unsigned char *buf, size_t len, int timeoutMs) {
std::vector<unsigned char> data = {};
data.reserve(len);
// check if there is leftover data from previous reads
if (!readBuffer.empty()) {
if (readBuffer.size() >= len) {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.begin() + len);
readBuffer.erase(readBuffer.begin(), readBuffer.begin() + len);
std::copy(data.begin(), data.end(), buf);
return 0;
} else {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.end());
readBuffer.clear();
}
}
read_data(timeoutMs);
if (!readBuffer.empty()) {
// check how much data is needed and add that much to the buffer
if (readBuffer.size() >= len) {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.begin() + len);
readBuffer.erase(readBuffer.begin(), readBuffer.begin() + len);
} else {
data = std::vector<unsigned char>(readBuffer.begin(), readBuffer.end());
readBuffer.clear();
}
}
if (data.empty()) {
// fill data buf with 1s if no data was received
printf("No data received\n");
return -1;
} else {
std::copy(data.begin(), data.end(), buf);
}
return 0;
} |
Some more testing reveals that the requirement is 300ms which works fine, but makes this code incredibly slow. |
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56 (cf90417)
clang version 19.0.0git (https:/github.com/llvm/llvm-project 34ba90745fa55777436a2429a51a3799c83c6d4c)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/koen/Documents/emsdk/upstream/bin
So I am using WebSerial in WebAssembly, when I try to write things like this my Arduino doesn't show any data recieved, but when I make the
emscripten_sleep
delay bigger, say 1000 it works fine. I suspect that JavaScript doesn't have enough time to process the write. How can I make sure JS does have that time?The text was updated successfully, but these errors were encountered: