-
-
Notifications
You must be signed in to change notification settings - Fork 39.6k
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
[Core] Unite half-duplex and full-duplex serial drivers #13081
Conversation
Targets #11930 -- might end up cherry-picking it into that PR, given the prerequisite. |
d39c3c3
to
e775dd6
Compare
e775dd6
to
e47b9fd
Compare
ab0cf21
to
9d205a7
Compare
I was able to save quite a few cycles for the half-duplex implementation by discarding the bytes from the input queue after transmitting without actually reading them back. Also sdClear (which is now called usart_reset) is only called in case of transmission errors on the slave side and on every iteration on the master side. Also it just hard resets the input queue. With these changes the full-duplex and half-duplex driver are within a few hundred matrix scans, full-duplex still being slightly faster. |
Responding to a comment from #13089 (that's more relevant here). Main topic is the custom serial driver I implemented for porting Ergodox Infinity over to using split_common.
@KarlK90 I think that's about it. The serial driver is already configurable ( The initialization code in my driver (here and here) is taken directly from the corresponding code in serial_link (currently only used by Ergodox Infinity), not entirely sure what it actually does. :P |
So I just pushed some changes that make the driver much more configurable and STM32 independent.
SerialDriver* serial_driver = &SERIAL_USART_DRIVER;
/**
* @brief Overridable master specific initializations.
*/
__attribute__((weak)) void usart_master_init(void) { usart_init(); }
/**
* @brief Overridable slave specific initializations.
*/
__attribute__((weak)) void usart_slave_init(void) { usart_init(); }
#if defined(SERIAL_USART_CONFIG)
static SerialConfig serial_config = SERIAL_USART_CONFIG;
#else
static SerialConfig serial_config = {
.speed = (SERIAL_USART_SPEED), /* speed - mandatory */
.cr1 = (SERIAL_USART_CR1),
.cr2 = (SERIAL_USART_CR2),
# if !defined(SERIAL_USART_FULL_DUPLEX)
.cr3 = ((SERIAL_USART_CR3) | USART_CR3_HDSEL) /* activate half-duplex mode */
# else
.cr3 = (SERIAL_USART_CR3)
# endif
};
#endif |
7e190fe
to
c17b99d
Compare
In practice, since that is a static variable, can I really change its value from code outside that file? 🤔
Technically, it's the STM32 config that's non-standard. The only standardized field in SerialConfig is the speed. https://chibiforge.org/doc/19.1/full_rm/struct_serial_config.html#details 😉 |
c17b99d
to
414789b
Compare
You're right I have dropped the static qualifier. Maybe QMK standard 😛 |
Another solution would have been to send a pointer to the variable as an argument to |
So, I've gotten this to work on Ergodox Infinity now. Prototype code here. However, due to incompatible code in Also, I realized I also added some code to my custom serial driver to make it possible to use a master half without a slave connected (since the constant wait for serial read timeout make the scan rate unusably slow otherwise). I would not at all call it perfect, but with Not sure how relevant that feature is, it's definitely not a requirement. I partly implemented it for fun, and partly because I thought more than once that the firmware was broken while porting Ergodox Infinity to split_common (the Infinity uses the same USB-C/micro B port for USB input from host to master and serial input from master to slave, so you need to disconnect the slave from the master to be able to flash the slave, making disconnects a bit more common than for other split boards). |
Alright, I guarded that stm32 specific init code behind a define and added a info message about the necessity to init the pins yourself. In the future this can be expanded to support specific ports like Kinetis quite easily. The driver is now static again and the side specific init functions get a pointer passed to it. The connect/disconnect feature is really cool, but IMHO should go in a more universal spot. I think the scan logic would be a good fit as it already has a error disconnect counter. Do the changes fix your compile issues? Haven't tested with a real compilation on non stm32 platforms. |
I think the main issue is that there are often more than one transaction per scan cycle (for LED/RGB Matrix, WPM, etc.), and I think stopping all of them would be quite messy if not done somewhere within the actual transport/transaction code (i.e. in
Haven't tried yet, but it looks like they should. I'll try it out later today or during the weekend. |
aa97b2c
to
cefc73a
Compare
This is my attempt to support disconnected peripheral sides.. But you are right, this should probably set a global flag and stop all transactions regardless where they are started from. I also think that could be done in a rather clean way, should attempt that after the split transactions PR is merged. The other reason why I'm opposed to do this in the driver is that this would have to be done for all drivers like serial and i2c which is duplicated efforts as well and it is in the hot-path of the application which should do as little logic as possible. 🤔 |
That is a good point. I didn't think that much about where it should be implemented since I put it in a completely custom driver when I came up with it. It might be an idea to implement it in a driver-independent wrapper around |
* Unite half-duplex and full-duplex serial driver. * Add full duplex operation mode to the interrupt based driver * Delete DMA UART based full duplex driver * The new driver targets qmk#11930 * Fix freezes with failing transactions in half-duplex * Increase default serial TX/RX buffer size to 128 bytes * Correctly use bool instead of size_t Co-authored-by: Nick Brassel <nick@tzarc.org>
* Unite half-duplex and full-duplex serial driver. * Add full duplex operation mode to the interrupt based driver * Delete DMA UART based full duplex driver * The new driver targets qmk#11930 * Fix freezes with failing transactions in half-duplex * Increase default serial TX/RX buffer size to 128 bytes * Correctly use bool instead of size_t Co-authored-by: Nick Brassel <nick@tzarc.org>
Description
So this is a follow-up on #9842 with a plot twist as it removes the DMA backed full duplex driver and adds the full duplex functionality to the existing interrupt based driver. There are multiple reasons for this change:
The benefits of this Implementation:
Tested on GD32VF103 and STM32F303 in both half-duplex and full-duplex configuration.
Types of Changes
Issues Fixed or Closed by This PR
Checklist