[rtems commit] dev/serial: Lazy update of NS16550 settings
Sebastian Huber
sebh at rtems.org
Wed Oct 18 06:52:49 UTC 2017
Module: rtems
Branch: master
Commit: 67015b617e68c97e73266d625bea0edccfa42d44
Changeset: http://git.rtems.org/rtems/commit/?id=67015b617e68c97e73266d625bea0edccfa42d44
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Wed Oct 18 07:18:57 2017 +0200
dev/serial: Lazy update of NS16550 settings
Updates of the line control and baud divisor while transfers are in
progress may lead to unpredictable behaviour on some chips. Perform the
updates only if necessary.
Close #3198.
---
c/src/libchip/serial/ns16550-context.c | 14 +++++++++++---
c/src/libchip/serial/ns16550.h | 2 ++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c
index 8901590..3c41978 100644
--- a/c/src/libchip/serial/ns16550-context.c
+++ b/c/src/libchip/serial/ns16550-context.c
@@ -148,6 +148,7 @@ bool ns16550_probe(rtems_termios_device_context *base)
/* Set the divisor latch and set the baud rate. */
ulBaudDivisor = NS16550_GetBaudDivisor(ctx, ctx->initial_baud);
+ ctx->baud_divisor = ulBaudDivisor;
ucDataByte = SP_LINE_DLAB;
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
@@ -161,6 +162,7 @@ bool ns16550_probe(rtems_termios_device_context *base)
/* Clear the divisor latch and set the character size to eight bits */
/* with one stop bit and no parity checking. */
ucDataByte = EIGHT_BITS;
+ ctx->line_control = ucDataByte;
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
/* Enable and reset transmit and receive FIFOs. TJA */
@@ -585,7 +587,6 @@ static bool ns16550_set_attributes(
uint8_t ucLineControl;
uint32_t baud_requested;
ns16550_set_reg setReg;
- rtems_interrupt_lock_context lock_context;
pNS16550 = ctx->port;
setReg = ctx->set_reg;
@@ -642,7 +643,13 @@ static bool ns16550_set_attributes(
* Now actually set the chip
*/
- rtems_termios_device_lock_acquire(base, &lock_context);
+ if (ulBaudDivisor != ctx->baud_divisor || ucLineControl != ctx->line_control) {
+ rtems_interrupt_lock_context lock_context;
+
+ ctx->baud_divisor = ulBaudDivisor;
+ ctx->line_control = ucLineControl;
+
+ rtems_termios_device_lock_acquire(base, &lock_context);
/*
* Set the baud rate
@@ -661,7 +668,8 @@ static bool ns16550_set_attributes(
*/
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
- rtems_termios_device_lock_release(base, &lock_context);
+ rtems_termios_device_lock_release(base, &lock_context);
+ }
return true;
}
diff --git a/c/src/libchip/serial/ns16550.h b/c/src/libchip/serial/ns16550.h
index 19ac3f1..4f1b98b 100644
--- a/c/src/libchip/serial/ns16550.h
+++ b/c/src/libchip/serial/ns16550.h
@@ -70,6 +70,8 @@ typedef struct {
uint32_t initial_baud;
bool has_fractional_divider_register;
uint8_t modem_control;
+ uint8_t line_control;
+ uint32_t baud_divisor;
size_t out_total;
size_t out_remaining;
size_t out_current;
More information about the vc
mailing list