qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Serge Vakulenko <serge.vakulenko@gmail.com>
To: qemu-devel@nongnu.org
Cc: Serge Vakulenko <serge.vakulenko@gmail.com>,
	Leon Alrae <leon.alrae@imgtec.com>,
	Aurelien Jarno <aurelien@aurel32.net>
Subject: [Qemu-devel] [PATCH pic32 v3 11/16] pic32: add file pic32_uart.c
Date: Sun,  5 Jul 2015 23:14:59 -0700	[thread overview]
Message-ID: <1436163304-6167-12-git-send-email-serge.vakulenko@gmail.com> (raw)
In-Reply-To: <1436163304-6167-1-git-send-email-serge.vakulenko@gmail.com>

Implement pic32 UART peripheral interface.

Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
---
 hw/mips/pic32_uart.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 228 insertions(+)
 create mode 100644 hw/mips/pic32_uart.c

diff --git a/hw/mips/pic32_uart.c b/hw/mips/pic32_uart.c
new file mode 100644
index 0000000..34056cf
--- /dev/null
+++ b/hw/mips/pic32_uart.c
@@ -0,0 +1,228 @@
+/*
+ * UART ports.
+ *
+ * Copyright (C) 2014-2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/hw.h"
+#include "hw/char/serial.h"
+#include "sysemu/char.h"
+#include "pic32_peripherals.h"
+
+#include "pic32mz.h"
+
+#define UART_IRQ_ERR    0               /* error irq offset */
+#define UART_IRQ_RX     1               /* receiver irq offset */
+#define UART_IRQ_TX     2               /* transmitter irq offset */
+
+/*
+ * Read of UxRXREG register.
+ */
+unsigned pic32_uart_get_char(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+    unsigned value;
+
+    /* Read a byte from input queue. */
+    value = u->rxbyte;
+    VALUE(u->sta) &= ~PIC32_USTA_URXDA;
+
+    s->irq_clear(s, u->irq + UART_IRQ_RX);
+    return value;
+}
+
+/*
+ * Write to UxTXREG register.
+ */
+void pic32_uart_put_char(pic32_t *s, int unit, unsigned char byte)
+{
+    uart_t *u = &s->uart[unit];
+
+    if (!u->chr) {
+        printf("--- %s(unit = %u) serial port not configured\n",
+            __func__, unit);
+        return;
+    }
+
+    /* Send the byte. */
+    if (qemu_chr_fe_write(u->chr, &byte, 1) != 1) {
+        /* TODO: suspend simulation until serial port ready. */
+        printf("--- %s(unit = %u) failed\n", __func__, unit);
+        return;
+    }
+
+    if ((VALUE(u->mode) & PIC32_UMODE_ON) &&
+        (VALUE(u->sta) & PIC32_USTA_UTXEN))
+    {
+        VALUE(u->sta) |= PIC32_USTA_UTXBF;
+        VALUE(u->sta) &= ~PIC32_USTA_TRMT;
+
+        /* Generate TX interrupt with some delay. */
+        timer_mod(u->transmit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+            get_ticks_per_sec() / 5000);
+        u->oactive = 1;
+    }
+}
+
+/*
+ * Called before reading a value of UxBRG, UxMODE or UxSTA registers.
+ */
+void pic32_uart_poll_status(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+
+    /* Keep receiver idle, transmit shift register always empty. */
+    VALUE(u->sta) |= PIC32_USTA_RIDLE;
+
+    /*printf("<%x>", VALUE(u->sta)); fflush(stdout);*/
+}
+
+/*
+ * Write to UxMODE register.
+ */
+void pic32_uart_update_mode(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+
+    if (!(VALUE(u->mode) & PIC32_UMODE_ON)) {
+        s->irq_clear(s, u->irq + UART_IRQ_RX);
+        s->irq_clear(s, u->irq + UART_IRQ_TX);
+        VALUE(u->sta) &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
+                           PIC32_USTA_PERR | PIC32_USTA_UTXBF);
+        VALUE(u->sta) |= PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    }
+}
+
+/*
+ * Write to UxSTA register.
+ */
+void pic32_uart_update_status(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+
+    if (!(VALUE(u->sta) & PIC32_USTA_URXEN)) {
+        s->irq_clear(s, u->irq + UART_IRQ_RX);
+        VALUE(u->sta) &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
+                           PIC32_USTA_PERR);
+    }
+    if (!(VALUE(u->sta) & PIC32_USTA_UTXEN)) {
+        s->irq_clear(s, u->irq + UART_IRQ_TX);
+        VALUE(u->sta) &= ~PIC32_USTA_UTXBF;
+        VALUE(u->sta) |= PIC32_USTA_TRMT;
+    }
+}
+
+/*
+ * Return a number of free bytes in the receive FIFO.
+ */
+static int uart_can_receive(void *opaque)
+{
+    uart_t *u = opaque;
+    pic32_t *s = u->mcu;        /* used in VALUE() */
+
+    /*printf("--- %s(%p) called\n", __func__, u);*/
+
+    if (!(VALUE(u->mode) & PIC32_UMODE_ON) ||
+        !(VALUE(u->sta) & PIC32_USTA_URXEN)) {
+        /* UART disabled. */
+        return 0;
+    }
+
+    if (VALUE(u->sta) & PIC32_USTA_URXDA) {
+        /* Receive buffer full. */
+        return 0;
+    }
+    return 1;
+}
+
+/*
+ * Process the received data.
+ */
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    uart_t *u = opaque;
+    pic32_t *s = u->mcu;        /* used in VALUE() */
+
+    /*printf("--- %s(%p) called\n", __func__, u);*/
+    if (!(VALUE(u->mode) & PIC32_UMODE_ON) ||
+        !(VALUE(u->sta) & PIC32_USTA_URXEN)) {
+        /* UART disabled. */
+        return;
+    }
+
+    if (VALUE(u->sta) & PIC32_USTA_URXDA) {
+        /* Receive buffer full. */
+        return;
+    }
+
+    u->rxbyte = buf[0];
+    VALUE(u->sta) |= PIC32_USTA_URXDA;
+
+    /* Activate receive interrupt. */
+    s->irq_raise(s, u->irq + UART_IRQ_RX);
+}
+
+/*
+ * Activate the transmit interrupt.
+ */
+static void uart_timeout(void *opaque)
+{
+    uart_t *u = opaque;
+    pic32_t *s = u->mcu;        /* used in VALUE() */
+
+    /*printf("--- %s() called\n", __func__);*/
+    if (u->oactive) {
+        /* Activate transmit interrupt. */
+        /*printf("uart%u: raise tx irq %u\n", unit, u->irq + UART_IRQ_TX);*/
+        if ((VALUE(u->mode) & PIC32_UMODE_ON) &&
+            (VALUE(u->sta) & PIC32_USTA_UTXEN)) {
+            s->irq_raise(s, u->irq + UART_IRQ_TX);
+        }
+        VALUE(u->sta) &= ~PIC32_USTA_UTXBF;
+        VALUE(u->sta) |= PIC32_USTA_TRMT;
+        u->oactive = 0;
+    }
+}
+
+/*
+ * Initialize the UART data structure.
+ */
+void pic32_uart_init(pic32_t *s, int unit, int irq, int sta, int mode)
+{
+    uart_t *u = &s->uart[unit];
+
+    u->mcu = s;
+    u->irq = irq;
+    u->sta = sta;
+    u->mode = mode;
+    u->transmit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uart_timeout, u);
+
+    if (unit >= MAX_SERIAL_PORTS) {
+        /* Cannot instantiate so many serial ports. */
+        u->chr = 0;
+        return;
+    }
+    u->chr = serial_hds[unit];
+
+    /* Setup callback functions. */
+    if (u->chr) {
+        qemu_chr_add_handlers(u->chr, uart_can_receive, uart_receive, NULL, u);
+    }
+}
-- 
2.2.2

  parent reply	other threads:[~2015-07-06  6:17 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-06  6:14 [Qemu-devel] [PATCH pic32 v3 00/16] add support for pic32 microcontrollers Serge Vakulenko
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 01/16] pic32: make the CPU clock frequency configurable per platform Serge Vakulenko
2015-07-06  8:42   ` Aurelien Jarno
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 02/16] pic32: use LCG algorithm for generated random index of TLBWR instruction Serge Vakulenko
2015-07-06  8:43   ` Aurelien Jarno
2015-09-15  9:46   ` Leon Alrae
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 03/16] pic32: add support for external interrupt controller mode (EIC) Serge Vakulenko
2015-07-06  9:34   ` Aurelien Jarno
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 04/16] pic32: add two MIPS processor variants: M4K and microAptivUP Serge Vakulenko
2015-07-06  9:35   ` Aurelien Jarno
2015-10-02 10:37   ` Leon Alrae
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 05/16] pic32: add file pic32_peripherals.h Serge Vakulenko
2015-07-06  8:02   ` Peter Crosthwaite
2015-07-06  9:01   ` Aurelien Jarno
2015-07-06 17:04     ` Peter Crosthwaite
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 06/16] pic32: add file pic32mx.h Serge Vakulenko
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 07/16] pic32: add file pic32mz.h Serge Vakulenko
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 08/16] pic32: add file mips_pic32mx7.c Serge Vakulenko
2015-07-06 11:18   ` Antony Pavlov
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 09/16] pic32: add file mips_pic32mz.c Serge Vakulenko
2015-07-06  6:14 ` [Qemu-devel] [PATCH pic32 v3 10/16] pic32: add file pic32_load_hex.c Serge Vakulenko
2015-07-06  6:14 ` Serge Vakulenko [this message]
2015-07-06  8:08   ` [Qemu-devel] [PATCH pic32 v3 11/16] pic32: add file pic32_uart.c Peter Crosthwaite
2015-07-06  6:15 ` [Qemu-devel] [PATCH pic32 v3 12/16] pic32: add file pic32_gpio.c Serge Vakulenko
2015-07-06  6:15 ` [Qemu-devel] [PATCH pic32 v3 13/16] pic32: add file pic32_spi.c Serge Vakulenko
2015-07-06  7:58   ` Peter Crosthwaite
2015-07-06  6:15 ` [Qemu-devel] [PATCH pic32 v3 14/16] pic32: add file pic32_sdcard.c Serge Vakulenko
2015-07-06  8:05   ` Peter Crosthwaite
2015-07-06  6:15 ` [Qemu-devel] [PATCH pic32 v3 15/16] pic32: add file pic32_ethernet.c Serge Vakulenko
2015-07-06  6:15 ` [Qemu-devel] [PATCH pic32 v3 16/16] pic32: update makefiles to cover pic32 support Serge Vakulenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1436163304-6167-12-git-send-email-serge.vakulenko@gmail.com \
    --to=serge.vakulenko@gmail.com \
    --cc=aurelien@aurel32.net \
    --cc=leon.alrae@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).