summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/char/stm32f2xx_usart.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c
index 07b462d4b6..032b5fda13 100644
--- a/hw/char/stm32f2xx_usart.c
+++ b/hw/char/stm32f2xx_usart.c
@@ -96,12 +96,10 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
switch (addr) {
case USART_SR:
retvalue = s->usart_sr;
- s->usart_sr &= ~USART_SR_TC;
qemu_chr_fe_accept_input(&s->chr);
return retvalue;
case USART_DR:
DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
- s->usart_sr |= USART_SR_TXE;
s->usart_sr &= ~USART_SR_RXNE;
qemu_chr_fe_accept_input(&s->chr);
qemu_set_irq(s->irq, 0);
@@ -137,7 +135,9 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
switch (addr) {
case USART_SR:
if (value <= 0x3FF) {
- s->usart_sr = value;
+ /* I/O being synchronous, TXE is always set. In addition, it may
+ only be set by hardware, so keep it set here. */
+ s->usart_sr = value | USART_SR_TXE;
} else {
s->usart_sr &= value;
}
@@ -151,8 +151,12 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
+ /* XXX I/O are currently synchronous, making it impossible for
+ software to observe transient states where TXE or TC aren't
+ set. Unlike TXE however, which is read-only, software may
+ clear TC by writing 0 to the SR register, so set it again
+ on each write. */
s->usart_sr |= USART_SR_TC;
- s->usart_sr &= ~USART_SR_TXE;
}
return;
case USART_BRR: