-
-
Notifications
You must be signed in to change notification settings - Fork 61
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
pbdrv/legodev: Refactor LEGO device abstraction. #174
Conversation
687e0b3
to
c502e89
Compare
Getting somewhere on this one now. Remaining tasks:
|
caef8a4
to
6ab4d3f
Compare
All checks are passing now. This will probably need some more testing before we can merge, particularly on more/all hubs. There was one spurious bug earlier today where a motor would not sync up or start, but I can't seem to reproduce it now. If nothing is immediately found, my vote would be to merge it on Thursday or Friday and fix any bugs encountered later on. |
I am occasionally able to reproduce it. It appears that setting the default mode (immediately after syncing up) does not always succeed, and we currently don't retry. So maybe we should wait briefly before setting the default mode, or retry if a mode switch hasn't succeeded. |
We should put a logic analyzer on it to see what is actually going over the wire. |
Nice. I have an idea that would take care of this issue and also make the general mode setting and data setting code easier to follow and more robust. Basically, we could modify this existing loop: while (data->status == PBDRV_LEGODEV_PUP_UART_STATUS_DATA) {
// await send keep alive on EV3_UART_IO_TIMEOUT
} to: while (data->status == PBDRV_LEGODEV_PUP_UART_STATUS_DATA) {
// wait until any of following conditions, then
// await send keep alive if EV3_UART_IO_TIMEOUT
// await set mode if requested (unsets request)
// await set data if requested (unsets request)
} This avoids clashes between setting stuff and sending keep alive (theoretically possible since #169 although never happened) by keeping all sending in one place. But it also lets us simplify the main process loop: while (true) {
for (i = 0; i < PBDRV_CONFIG_LEGODEV_PUP_UART_NUM_DEV; i++) {
port_data = &dev_data[i];
pbdrv_legodev_pup_uart_update(port_data);
if (port_data->status == PBDRV_LEGODEV_PUP_UART_STATUS_DATA) {
pbdrv_legodev_pup_uart_receive_data(port_data);
}
// CAN DROP: this was a hack to handle awaited mode/data sets
pbdrv_legodev_pup_uart_handle_write_end(port_data);
// CAN DROP: handled simpler above
if (port_data->status == PBDRV_LEGODEV_PUP_UART_STATUS_DATA) {
pbdrv_legodev_pup_uart_handle_data_set_start(port_data);
}
}
PROCESS_WAIT_EVENT();
} I've just tried the mode setting part (still need to do data set), and this seems to work well. It also has the benefit of retrying automatically in case of failure. |
Above issue is fixed, and did some more code consolidation to save on size. This PR saves us another 700 bytes so we have a whole 1KB to spare again which should cover us on bug fixes for a while. 🚀 |
9b3bc7b
to
1116dd2
Compare
This is a major overhaul of the lego device interface to clean up many longstanding hacks and simplify maintenance of present and future platforms, including EV3 and NXT. It is also a first step towards generalizing ioports, of which legodev will be one mode.
This handles all writing in one place to avoid clashes and makes the code easier to follow. This also retries setting the mode if it failed.
There were several write_begin and write_end calls used in a similar way. There was already a PT_THREAD for pbdrv_legodev_pup_uart_send_speed_msg, which we can generalize and use for other messages too. This saves on build size. Because write operations are all handled in the same place, we also don't need the tx_busy mutex anymore.
If a device was busy on program exit, the check for power requirements returns ERROR_AGAIN as expected. But this caused the device capabilities not to be read, thus turning off the power to the ultrasonic sensor if the light was being set.
This is a draft to revise how we deal with lego devices at the low and high level.
This large change is based on findings from the past years. Instead of trying to have an all-encompassing
iodev
abstraction (which ended up being hard-coded for LEGO devices), we have an interface specifically for LEGO devices, separate from port I/O.In the future, this may play the role of LEGO-mode on a port (alongside raw UART/I2C modes, etc.).
The interface is platform agnostic, but there will be platform-specific implementations for:
The following sums it up quite well -- this pull request goes a long way to get rid of technical debt like this:
It also adds an option to exclude some
pup_uart
functionality to reduce build size on Move Hub by about 500 bytes.