hw/char/stm32l4x5_usart.c | 4 ++-- tests/qtest/stm32l4x5_usart-test.c | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-)
Official STM32CubeL4 drivers use and require support for 16-bit writes to
UART registers for proper function despite datasheet claims.
Signed-off-by: Jacob Whitaker Abrams <satur9nine@gmail.com>
---
v2:
- Remove all changes other than supporting 16-bit writes UART regs
hw/char/stm32l4x5_usart.c | 4 ++--
tests/qtest/stm32l4x5_usart-test.c | 22 +++++++++++++++++++++-
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
index dd1b099195..3b9883bb23 100644
--- a/hw/char/stm32l4x5_usart.c
+++ b/hw/char/stm32l4x5_usart.c
@@ -521,12 +521,12 @@ static const MemoryRegionOps stm32l4x5_usart_base_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
.max_access_size = 4,
- .min_access_size = 4,
+ .min_access_size = 2,
.unaligned = false
},
.impl = {
.max_access_size = 4,
- .min_access_size = 4,
+ .min_access_size = 2,
.unaligned = false
},
};
diff --git a/tests/qtest/stm32l4x5_usart-test.c b/tests/qtest/stm32l4x5_usart-test.c
index a72c5a685d..3c6437e75d 100644
--- a/tests/qtest/stm32l4x5_usart-test.c
+++ b/tests/qtest/stm32l4x5_usart-test.c
@@ -332,6 +332,26 @@ static void test_ack(void)
qtest_quit(qts);
}
+static void test_16bit_access(void)
+{
+ QTestState *qts = qtest_init("-M b-l475e-iot01a");
+
+ /* GTPR is declared uint16_t in the official STM driver. */
+ qtest_writew(qts, USART1_BASE_ADDR + A_GTPR, 0xABCD);
+ uint16_t gtpr16 = qtest_readw(qts, USART1_BASE_ADDR + A_GTPR);
+ g_assert_cmpuint(gtpr16, ==, 0xABCD);
+
+ /* TDR is uint16_t and r/w, register is 9-bits */
+ qtest_writew(qts, USART1_BASE_ADDR + A_TDR, 0x01CD);
+ uint16_t tdr16 = qtest_readw(qts, USART1_BASE_ADDR + A_TDR);
+ g_assert_cmpuint(tdr16, ==, 0x01CD);
+
+ /* RDR is uint16_t and read only, register is 9-bits */
+ qtest_writew(qts, USART1_BASE_ADDR + A_RDR, 0x01FA);
+
+ qtest_quit(qts);
+}
+
static void check_clock(QTestState *qts, const char *path, uint32_t rcc_reg,
uint32_t reg_offset)
{
@@ -370,6 +390,6 @@ int main(int argc, char **argv)
qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
qtest_add_func("stm32l4x5/usart/ack", test_ack);
qtest_add_func("stm32l4x5/usart/clock_enable", test_clock_enable);
+ qtest_add_func("stm32l4x5/usart/16bit_access", test_16bit_access);
return g_test_run();
}
-
--
2.43.0
Hi Jacob,
On 21/9/26 07:09, Jacob Whitaker Abrams wrote:
> Official STM32CubeL4 drivers use and require support for 16-bit writes to
> UART registers for proper function despite datasheet claims.
[*]
>
> Signed-off-by: Jacob Whitaker Abrams <satur9nine@gmail.com>
> ---
> v2:
> - Remove all changes other than supporting 16-bit writes UART regs
>
> hw/char/stm32l4x5_usart.c | 4 ++--
> tests/qtest/stm32l4x5_usart-test.c | 22 +++++++++++++++++++++-
> 2 files changed, 23 insertions(+), 3 deletions(-)
>
> diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
> index dd1b099195..3b9883bb23 100644
> --- a/hw/char/stm32l4x5_usart.c
> +++ b/hw/char/stm32l4x5_usart.c
> @@ -521,12 +521,12 @@ static const MemoryRegionOps stm32l4x5_usart_base_ops = {
> .endianness = DEVICE_NATIVE_ENDIAN,
> .valid = {
> .max_access_size = 4,
> - .min_access_size = 4,
> + .min_access_size = 2,
Can we replicate the description comment here?
> .unaligned = false
> },
> .impl = {
> .max_access_size = 4,
> - .min_access_size = 4,
> + .min_access_size = 2,
This files defines addresses using the REG32() macro, and
the read/write handlers switch over these 32-bit addresses.
Why change the implementation minimum access size to 16-bit?
> .unaligned = false
> },
> };
© 2016 - 2026 Red Hat, Inc.