[PATCH v2] hw/char/stm32l4x5_usart.c: Support 16-bit writes

Jacob Whitaker Abrams posted 1 patch 5 days, 14 hours ago
There is a newer version of this series
hw/char/stm32l4x5_usart.c          |  4 ++--
tests/qtest/stm32l4x5_usart-test.c | 22 +++++++++++++++++++++-
2 files changed, 23 insertions(+), 3 deletions(-)
[PATCH v2] hw/char/stm32l4x5_usart.c: Support 16-bit writes
Posted by Jacob Whitaker Abrams 5 days, 14 hours ago
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
Re: [PATCH v2] hw/char/stm32l4x5_usart.c: Support 16-bit writes
Posted by Philippe Mathieu-Daudé 5 days, 6 hours ago
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
>       },
>   };