Skip to content

RFC: UART enhanced settings#10743

Merged
MrKevinWeiss merged 4 commits intoRIOT-OS:masterfrom
yegorich:uart-enhanced-settings
Jan 31, 2019
Merged

RFC: UART enhanced settings#10743
MrKevinWeiss merged 4 commits intoRIOT-OS:masterfrom
yegorich:uart-enhanced-settings

Conversation

@yegorich
Copy link
Copy Markdown
Contributor

@yegorich yegorich commented Jan 10, 2019

Contribution description

As suggested in PR #5899 add a routine uart_mode() that will setup databits, stopbits and parity at runtime.

uart.h provides a set of enums defining these settings and each platform will override them to specify values corresponding to its configuration registers.

The idea behind the enums is to specify default settings i.e. 8N1 through the 0 value item. Invoking uart_mode(uart, 0, 0, 0) will setup 8N1 mode.

9-bit mode was excluded as UART API is working with uin8_t data units.

As a proof of concept uart_mode was implemented for STM32 UART and tested on Nucleo-F411re.

Testing procedure

periph_uart test was extended with mode command that will be invoked directly after init command. Below some examples:

  • mode 1 8 e 1 - configures 8E1 mode, i.e. 8 databits, even parity and 1 stopbit
  • mode 1 7 o 2 - configures 7O2 mode, i.e. 7 databits, odd parity and 2 stopbits

Issues/PRs references

This PR reimplements PR #5899 for general use.

@MrKevinWeiss MrKevinWeiss self-assigned this Jan 10, 2019
@MrKevinWeiss MrKevinWeiss added Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: cpu Area: CPU/MCU ports labels Jan 10, 2019
Copy link
Copy Markdown
Contributor

@MrKevinWeiss MrKevinWeiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things to note, I can test and look deeper tomorrow.

@kaspar030
Copy link
Copy Markdown
Contributor

Did you consider a combined value for all options?

E.g.,

typedef uint16_t uart_mode_t
#define UART_PARITY_OFFSET 0
#define UART_PARITY_MASK 0x3
#define UART_DATABITS_OFFSET 3
#define UART_DATABITS_MASK 0x3

//...
int parity = mode & UART_PARITY_MASK >> UART_PARITY_OFFSET
int databits = mode & UART_DATABITS_MASK >> UART_DATABITS_OFFSET

In addition, define the most used ones as speaking defines:

#define UART_MODE_8N1 (UART_DATABITS_8 << UART_DATABITS_OFFSET | UART_PARITY_N << UART_PARITY_OFFSET ...)

My main reason would be that this way, uart users actually using modes don't need all the fields:

typedef struct  {
 //...
 uint8_t uart_parity;
 uint8_t uart_databits;
 uint8_t uart_stopbits;
} random_driver_params_t;

// vs
typedef struct  {
 //...
 uart_mode_t uart_mode;
} random_driver_params_t;

@yegorich
Copy link
Copy Markdown
Contributor Author

@kaspar030 we already had this discussion here and so I've made this PR according to it.

@yegorich yegorich force-pushed the uart-enhanced-settings branch 2 times, most recently from 484f239 to fefe813 Compare January 16, 2019 10:44
@yegorich yegorich force-pushed the uart-enhanced-settings branch from fefe813 to c9bbadb Compare January 17, 2019 12:14
@yegorich
Copy link
Copy Markdown
Contributor Author

yegorich commented Jan 17, 2019

v2 changes:

  • add support for partial 6-bit and full 7-bit modes to the devices defining USART_CR1_M1
  • add tests for even and odd parity against PHiLIP hardware

TODO: convert uart_mode() to a feature

@yegorich yegorich force-pushed the uart-enhanced-settings branch from c9bbadb to 433693e Compare January 18, 2019 09:20
@MrKevinWeiss MrKevinWeiss added the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Jan 18, 2019
@yegorich yegorich force-pushed the uart-enhanced-settings branch from 433693e to cae00a1 Compare January 18, 2019 10:12
@yegorich
Copy link
Copy Markdown
Contributor Author

v3 changes:

  • convert uart_mode to a feature periph_uart_modecfg
  • move tests to a separate commit

@yegorich
Copy link
Copy Markdown
Contributor Author

@bluephoton could you test this PR with your setup and report the results here? Thanks.

@bluephoton
Copy link
Copy Markdown

@yegorich , I gave it a try but it didn't work! I know that I need to invert RX for my scenario so I added the following code (at the very end before you enable uart):

MODIFY_REG(dev(uart)->CR2, USART_CR2_RXINV_Msk, USART_CR2_RXINV);

but this didn't help!

I'll look bit more tomorrow, in case its something with my environment.

Here is how I initialize (working case):

uart_init_ex(uart, baudrate, UartReceiveCallback, this, false);
uart_configure(uart, UART_9BITS, UART_PARITY_EVEN, UART_STOPBITS_TWO, UART_RX_INVERT);
uart_enable(uart);

Here is with new uart_mode (not working case):

uart_init(uart, baudrate, UartReceiveCallback, this);
uart_mode(uart, UART_DATABITS_8, UART_PARITY_EVEN, UART_STOPBITS_2);

Couple notes on implementation:

  • I'm not an expert in this, but not a fan of starting up device, stopping it to configure, then starting it again.
  • Not sure why we have UART_DATABITS_9 if we are setting this internally (code could use some comment around this as it's not intuitive)

@bluephoton
Copy link
Copy Markdown

bluephoton commented Jan 22, 2019

@yegorich I found the culprit! Two issues:

  • uart_stop() line 171 & 178 should be
cr1 &= ~USART_CR1_UE;   // note the ~ should be there in both cases
  • stopbits seems to be not set correctly, when I change it as follow it works:
// cr2 |= stopbits;
cr2 |= USART_CR2_STOP_1;
  • And of course inverting RX bin was required and you should add while you are at it.

I also recommend replacing all numeric constants with actual macro as defined in CMSIS header file. Also not use _M (mask) and use actual bit value (even if it happen to be the same) like:

if (databits == UART_DATABITS_8) {
            //cr1 |= USART_CR1_M;
            cr1 |= USART_CR1_M0;

Edit: Added comments on the exact code location with changes required

@yegorich yegorich force-pushed the uart-enhanced-settings branch from cae00a1 to ceacf21 Compare January 22, 2019 09:24
@MrKevinWeiss MrKevinWeiss added Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines labels Jan 29, 2019
Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some small findings left, closing in...

@yegorich yegorich force-pushed the uart-enhanced-settings branch from 14bf254 to ba48dba Compare January 29, 2019 15:25
Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One issue left...

@yegorich yegorich force-pushed the uart-enhanced-settings branch 2 times, most recently from a4a66a0 to dc67f4b Compare January 30, 2019 13:01
Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 left, then we can merge.

As suggested in PR#5899 add a routine uart_mode() that will
setup data bits, stop bits and parity at runtime.

uart.h provides a set of enums defining these settings and each
platform will override them to specify values corresponding to
its configuration registers.

The idea behind the enums is to specify default settings i.e. 8N1
through the 0 value item. Invoking uart_mode(uart, 0, 0, 0) will
setup 8N1 mode.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
Add support for specifying data bits, stop bits and parity at
runtime.

Introduce feature periph_uart_modecfg for uart_mode() till all
other CPUs implement it.

STM32 L1, F1, F2, F4 supports following modes:

* 7E1, 7E2
* 7O1, 7O2
* 8N1, 8N2
* 8E1, 8E2
* 8O1, 8O2

STM32 L0, L4, F0, F3, F7 supports following modes:

* 6E1, 6E2
* 6O1, 6O2
* 7E1, 7E2
* 7O1, 7O2
* 7N1, 7N2
* 8N1, 8N2
* 8E1, 8E2
* 8O1, 8O2

Use USART_CR1_M1 macro to detect 7-bit support because
even inside one family there could be devices that don't
support 7-bit mode. So just using a family macro is not
enough.

As stated in the datasheets for L0, L4, F0, F3, F7 devices,
data bits can only be changed when UART is disabled (UE=0).
Introduce uart_stop() routine to satisfy this requirement.

STM32 UART adds parity to the MSB of a byte to send. The same
also applies to the received bytes. As a result this bit must
be masked in order to get the pure data.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
Add command mode that will be used like this:

mode <dev> <data bits> <parity> <stop bits>

This command must be called after init otherwise
the UART won't be fully initialized.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
Add positive and negative tests for data bits, stop bits and parity:

- 7E1, 7O1
- 8E1, 8O1
- 8N2

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
@yegorich yegorich force-pushed the uart-enhanced-settings branch from dc67f4b to 2673b66 Compare January 31, 2019 13:25
Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK from my side.

BUT to make sure: I did not compile or test any of this code, I just did a code quality and style review...

@haukepetersen haukepetersen added Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines labels Jan 31, 2019
@haukepetersen
Copy link
Copy Markdown
Contributor

@MrKevinWeiss could you give this a final test-run? Thx. If you succeed, feel free to merge!

@MrKevinWeiss
Copy link
Copy Markdown
Contributor

Ok hold for retesting

@MrKevinWeiss
Copy link
Copy Markdown
Contributor

Seems good to me. GO!
Nice job @yegorich!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants