-
Notifications
You must be signed in to change notification settings - Fork 8.2k
api: uart: Add configure functions for UART. #11185
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
api: uart: Add configure functions for UART. #11185
Conversation
Mierunski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things that haven't been decided yet.
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is ongoing discussion if flow control, parity, stop, and data bits should be kept as bitmasks or enums.
@galak @tbursztyka
I personally prefer using 4 values with enums here. Configuration will be kept inside driver, and this structure will only exist locally when it is used to extract current configuration, change it, then write it back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm for avoid bitfields for such things since I think it makes the code harder to get right. I say go with u8_t's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 values as 8bits instead of a bitfield in 32bits is same size so go for the enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to u8_t and enums
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, so far I see discussion of bitmasks vs byte-sized fields. Did we consider using true C bitfields, like u32_t parity : 3?
That would save the bits and allow address @erwango's comment below https://github.com/zephyrproject-rtos/zephyr/pull/11185/files#r231818904 (w/o increasing size).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pfalcon we forbid long ago usage of C bitfields in public APIs, for instance i²c (afaik) used to have those for its config and it was changed to bitmasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we forbid long ago usage of C bitfields in public APIs
Really? LOL! Because we should do the opposite - forbid their use in referring to external structures (and we do that a lot using bitfields), and be absolutely free to use them in our APIs with our compilers. (Or with "their" compilers, as long as we intend to keep "userspace and kernelspace is built together" paradigm.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was the issue as far as I remember, app could be built by a different compiler than common zephyr one. This discussion was given almost 3 years ago.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was decided that C bitfields are forbidden and they will not be used in this API. I will stick with u8_t and enums.
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does rx_timeout have any particular meaning (might be held over from other PR)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, +1 to what @galak says - let's leave rx_timeout to the other PR/part of the API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, removed rx_timeout
32d578b to
26e0ee1
Compare
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the use case for that one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if you need get_cfg right now to be able to only modify one param, for example if I want to set just the baudrate, we kinda have a read/modify/write with how the set_cfg api is defined.
Wondering if we should have:
set_baudrate()
set_parity()
etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we should have:
set_baudrate()
I believe this again was discussed, and @tbursztyka suggest to follow how it's done for other comm. interfaces (?, didn't check that myself), and have common structure for all params.
We also should consider a usecase of userspace syscalls (because UART config API of course should be exported to userspace in one or another form). From that PoV, we always should save on # of syscalls. (Can define convenience inline wrappers on top of that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need atomic cfg modifier. Just apply a new config via set_cfg as it is done in other buses. It's not like uart cfg has a lot of fields.
I would rename set_cfg to configure btw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
atomic cfg modifier
I'm not sure I understand context for "atomic" here. The question is still whether we need to provide "get cfg" operation to users, and that seems to be useful. After all, how one would implement POSIX stty for example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pfalcon And what is yours idea about 'u32_t flags' or enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@qianfan-Zhao: That's orthogonal imho. Posted a "new" suggestion here: #11185 (comment) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename set_cfg to configure btw.
Ok, my 2 cents on this. Prior art: spi.h doesn't have configure(), while i2c has i2c_configure(). Thus, for consistency, proposal:
->configure()
->get_config()
IMHO looks not bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks better indeed.
(on spi the reason why there is no configure() is that config is always given to each calls, driver reconfigures if only it's a different one. I2c could have been doing the same actually.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to configure() and get_config()
Codecov Report
@@ Coverage Diff @@
## master #11185 +/- ##
=======================================
Coverage 48.37% 48.37%
=======================================
Files 265 265
Lines 42188 42188
Branches 10137 10137
=======================================
Hits 20408 20408
Misses 17703 17703
Partials 4077 4077Continue to review full report at Codecov.
|
|
@qianfan-Zhao , you might be interested |
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a vendor, or optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in other APIs we try not to expose any vendor specific stuff, the problem is that code using this API would not be guaranteed to behave the same (or work at all) depending on such configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm against adding vendor config, if more options are needed they should be explicitly added as new configuration option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@galak @pfalcon @nordic-krch Any comments on this? Other discussions seem to be resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's leave US-timezone folks time to catch up/reply. I'd be ready to +1 this tomorrow.
P.S. There's a proposed PR process: https://docs.google.com/document/d/1dSLSTckOgCeBh8MrU4AgpjkR6hQ0IikPnreAOO_wWGY/edit
fcbae89 to
85f20b5
Compare
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about make the most commonly used has the value zero?
STOP_BITS_1 and DATA_BITS_8 is the most common used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about make the most commonly used has the value zero?
But why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
en, memset(&cfg, 0, sizeof(cfg)) can set a default mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct uart_config cfg = {
.baud = 115200,
};
something like this can work fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@qianfan-Zhao I am not sure if this is good approach...
You can create a macro for setting default values, you will have more control about what is happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, maybe this is not a good way, but like most things linux did, 0 can hold a default value in a structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think trying to have the default be 0 would be good, since I don't know if there is anyway to enforce the use of a macro for default value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats a bad idea in my opinion, i.e. if we have current-speed = <9600>; in dts then default value of speed is taken from dts or arbitrary value like 115200? I was thinking that we are moving in direction of putting initial setting into dts, so using default values would complicate that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this is good approach...
I'm not sure either. Recently we had an argument with @jukkar regarding numeric values for some symbolic constants, where I advocated position of using "well known" numeric values form well-known system like Linux, which in turn uses the values from a standard like iBCS - all to be able to printf("%d") (also p/x in gdb) that value and see that widely known (in narrow circles) numeric value and not be confused when jumping from system to system.
With the lack of arguments like that, seeing stuff like:
enum uart_config_data_bits {
BITS_8,
BITS_5,
BITS_6,
...
};
- leaves one one impression: it's erratic. Again, printing raw value/seeing it in debugger will only get you confused, as it's not in logical order.
So, sorry, but you should always set all settings explicitly, and always using symbolic value, not relying on any numeric value it has. That's actually argument to ban zero value, and EINVAL on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer explicit settings too
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if there is any value in doing:
UART_CFG_DATA_BITS_5 = 5,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would make it differ from parity and stop bits, I don't see how this approach could be used for stop bits for example
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor, but why is this put on top of existing copyright, instead of on bottom?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just following approach in other API .h files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird, never paid attention. Definitely not how Linux has it, e.g. https://elixir.bootlin.com/linux/latest/source/ipc/sem.c (though not too consistent there too, e.g. 2010 and 2016 swapped in this random example.)
pfalcon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra pass thru docstrings, suggestions for improvements.
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any change to fit "enum" in the description, e.g.:
Parity bit, use enum @ref uart_config_parity
Oh, and it's probably "parity setting", not "parity bit".
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please specify that "<0" means error, and only then describe particular ones, giving clear hint that there can be more. E.g. something like "<0 error, including: -ENOTSUP ...". Can also look thru other docstrings with similar formulations for ideas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to use ENOSYS if function is not implemented, but got some problems, see here #11207
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to use ENOSYS if function is not implemented, but got some problems, see here
Please use whatever other APIs use in this case, and that's ENOTSUP. If you'd like to change it, it should be done consistently across API, and that's a separate task (and quite a task, with a usual RFC phase, etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed docstrings @retval 0 If successful, negative errno code otherwise.
|
@Mierunski, ping, any news on docstrings updates? |
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usually, I see following scheme:
if (/*possible error condition*/) {
return ERR;
}
/*execute valid case*/
but it's rather not used in that file.
85f20b5 to
119f274
Compare
|
@galak ping |
119f274 to
4a2860a
Compare
include/uart.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, we have a mix of API function naming conventions, sometime verb at the end, sometime in the middle, i have no preference, but uart_config_get reads better. We should try and standarize this for new APIs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but uart_config_get reads better.
Well, that's hardly. And within 2 functions added here, there's a consistency: first verb goes, then optional object (noun). (configure is a verb). It's inconsistent with the older API, yeah.
We should try and standarize this for new APIs
We should try to standardize, or should stick for consistency to whatever semi-random and not standardized way it was done before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to uart_config_get
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, that's hardly.
Obviously that is very subjective. Maybe because I read from right to left.
This is how we have thing in the kernel API and in some drivers.
Allow UART configuration to be altered during runtime. Signed-off-by: Mieszko Mierunski <[email protected]>
4a2860a to
89f153d
Compare
|
For those who may miss it, first implementation of these APIs went for review: #11577 |
|
@qianfan-Zhao zephyr/drivers/serial/uart_stm32.c Lines 324 to 327 in 794d382
|
Allow UART configuration to be altered during runtime.
This PR is follow up to #10820 it adds configuration part of it.