From 28513e23773d9ff15db48f765797b9b494230a28 Mon Sep 17 00:00:00 2001
From: Gregory Nutt <gnutt@nuttx.org>
Date: Tue, 24 Feb 2015 17:23:56 -0600
Subject: [PATCH] PIC32MZ:  Add low level UART support

---
 arch/mips/src/pic32mz/Make.defs            |   2 +-
 arch/mips/src/pic32mz/chip/pic32mz-timer.h |  22 +-
 arch/mips/src/pic32mz/chip/pic32mz-uart.h  |  33 +-
 arch/mips/src/pic32mz/pic32mz-lowconsole.c | 352 +++++++++++++++++++++
 4 files changed, 392 insertions(+), 17 deletions(-)
 create mode 100644 arch/mips/src/pic32mz/pic32mz-lowconsole.c

diff --git a/arch/mips/src/pic32mz/Make.defs b/arch/mips/src/pic32mz/Make.defs
index b893fdfd2f..f15b7b0627 100644
--- a/arch/mips/src/pic32mz/Make.defs
+++ b/arch/mips/src/pic32mz/Make.defs
@@ -65,6 +65,6 @@ endif
 
 CHIP_ASRCS  =
 CHIP_CSRCS  = pic32mz-lowinit.c pic32mz-exception.c pic32mz-decodeirq.c
-CHIP_CSRCS += pic32mz-irq.c pic32mz-timerisr.c
+CHIP_CSRCS += pic32mz-irq.c pic32mz-timerisr.c pic32mz-lowconsole.c
 
 # Configuration-dependent PIC32MZ files
diff --git a/arch/mips/src/pic32mz/chip/pic32mz-timer.h b/arch/mips/src/pic32mz/chip/pic32mz-timer.h
index 9545e17fbf..4cc12eacf0 100644
--- a/arch/mips/src/pic32mz/chip/pic32mz-timer.h
+++ b/arch/mips/src/pic32mz/chip/pic32mz-timer.h
@@ -52,7 +52,7 @@
  ************************************************************************************/
 /* Timer Peripheral Offsets *********************************************************/
 
-#define PIC32MZ_TIMER_OFFSET(n)    ((n) << 9)
+#define PIC32MZ_TIMERn_OFFSET(n)   ((n) << 9)
 #  define PIC32MZ_TIMER1_OFFSET    0x0000
 #  define PIC32MZ_TIMER2_OFFSET    0x0200
 #  define PIC32MZ_TIMER3_OFFSET    0x0400
@@ -82,16 +82,16 @@
 
 /* Timer Peripheral Addresses *******************************************************/
 
-#define PIC32MZ_TIMERn_K1BASE(n)   (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER_OFFSET(n))
-#define PIC32MZ_TIMER1_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER1_OFFSET)
-#define PIC32MZ_TIMER2_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER2_OFFSET)
-#define PIC32MZ_TIMER3_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER3_OFFSET)
-#define PIC32MZ_TIMER4_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER4_OFFSET)
-#define PIC32MZ_TIMER5_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER5_OFFSET)
-#define PIC32MZ_TIMER6_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER6_OFFSET)
-#define PIC32MZ_TIMER7_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER7_OFFSET)
-#define PIC32MZ_TIMER8_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER8_OFFSET)
-#define PIC32MZ_TIMER9_K1BASE      (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER9_OFFSET)
+#define PIC32MZ_TIMERn_K1BASE(n)   (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMERn_OFFSET(n))
+#  define PIC32MZ_TIMER1_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER1_OFFSET)
+#  define PIC32MZ_TIMER2_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER2_OFFSET)
+#  define PIC32MZ_TIMER3_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER3_OFFSET)
+#  define PIC32MZ_TIMER4_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER4_OFFSET)
+#  define PIC32MZ_TIMER5_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER5_OFFSET)
+#  define PIC32MZ_TIMER6_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER6_OFFSET)
+#  define PIC32MZ_TIMER7_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER7_OFFSET)
+#  define PIC32MZ_TIMER8_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER8_OFFSET)
+#  define PIC32MZ_TIMER9_K1BASE    (PIC32MZ_TIMER_K1BASE+PIC32MZ_TIMER9_OFFSET)
 
 /* Register Addresses ***************************************************************/
 
diff --git a/arch/mips/src/pic32mz/chip/pic32mz-uart.h b/arch/mips/src/pic32mz/chip/pic32mz-uart.h
index 9b3dc3286b..37affc2b89 100644
--- a/arch/mips/src/pic32mz/chip/pic32mz-uart.h
+++ b/arch/mips/src/pic32mz/chip/pic32mz-uart.h
@@ -1,5 +1,5 @@
 /************************************************************************************
- * arch/mips/src/pic32mx/pic32mx-uart.h
+ * arch/mips/src/pic42mz/pic42mz-uart.h
  *
  *   Copyright (C) 2015 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gnutt@nuttx.org>
@@ -43,11 +43,21 @@
 #include <nuttx/config.h>
 
 #include <arch/pic32mz/chip.h>
-#include "pic32mx-memorymap.h"
+#include "chip/pic32mz-memorymap.h"
 
 /************************************************************************************
  * Pre-processor Definitions
  ************************************************************************************/
+/* UART Peripheral Offsets **********************************************************/
+
+#define PIC32MZ_UARTn_OFFSET(n)     ((n) << 9)
+#  define PIC32MZ_UART1_OFFSET      0x0000
+#  define PIC32MZ_UART2_OFFSET      0x0200
+#  define PIC32MZ_UART3_OFFSET      0x0400
+#  define PIC32MZ_UART4_OFFSET      0x0600
+#  define PIC32MZ_UART5_OFFSET      0x0800
+#  define PIC32MZ_UART6_OFFSET      0x0a00
+
 /* Register Offsets *****************************************************************/
 
 #define PIC32MZ_UART_MODE_OFFSET    0x0000 /* UARTx mode register */
@@ -68,6 +78,19 @@
 #define PIC32MZ_UART_BRGSET_OFFSET  0x0048 /* UARTx baud rate set register */
 #define PIC32MZ_UART_BRGINV_OFFSET  0x004c /* UARTx baud rate invert register */
 
+/* Timer Peripheral Addresses *******************************************************/
+
+#define PIC32MZ_UARTn_K1BASE(n)     (PIC32MZ_UART_K1BASE+PIC32MZ_UARTn_OFFSET(n))
+#  define PIC32MZ_UART1_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART1_OFFSET)
+#  define PIC32MZ_UART2_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART2_OFFSET)
+#  define PIC32MZ_UART3_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART3_OFFSET)
+#  define PIC32MZ_UART4_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART4_OFFSET)
+#  define PIC32MZ_UART5_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART5_OFFSET)
+#  define PIC32MZ_UART6_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART6_OFFSET)
+#  define PIC32MZ_UART7_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART7_OFFSET)
+#  define PIC32MZ_UART8_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART8_OFFSET)
+#  define PIC32MZ_UART9_K1BASE      (PIC32MZ_UART_K1BASE+PIC32MZ_UART9_OFFSET)
+
 /* Register Addresses ****************************************************************/
 
 #if CHIP_NUARTS > 0
@@ -209,9 +232,9 @@
 #define UART_STA_ADDEN              (1 << 5)  /* Bit 5: Address character detect */
 #define UART_STA_URXISEL_SHIFT      (6)       /* Bits: 6-7: Receive interrupt mode selection */
 #define UART_STA_URXISEL_MASK       (3 << UART_STA_URXISEL_SHIFT)
-#define UART_STA_URXISEL_RECVD      (0 << UART_STA_URXISEL_SHIFT) /* Character received */
-#define UART_STA_URXISEL_RXB50      (1 << UART_STA_URXISEL_SHIFT) /* RX buffer 1/2 full */
-#define UART_STA_URXISEL_RXB75      (2 << UART_STA_URXISEL_SHIFT) /* RX buffer 3/4 full */
+#  define UART_STA_URXISEL_RECVD    (0 << UART_STA_URXISEL_SHIFT) /* Character received */
+#  define UART_STA_URXISEL_RXB50    (1 << UART_STA_URXISEL_SHIFT) /* RX buffer 1/2 full */
+#  define UART_STA_URXISEL_RXB75    (2 << UART_STA_URXISEL_SHIFT) /* RX buffer 3/4 full */
 #define UART_STA_UTRMT              (1 << 8)  /* Bit 8: Transmit shift register is empty */
 #define UART_STA_UTXBF              (1 << 9)  /* Bit 9: Transmit buffer full status */
 #define UART_STA_UTXEN              (1 << 10) /* Bit 10: Transmit enable */
diff --git a/arch/mips/src/pic32mz/pic32mz-lowconsole.c b/arch/mips/src/pic32mz/pic32mz-lowconsole.c
new file mode 100644
index 0000000000..2cd91de6ba
--- /dev/null
+++ b/arch/mips/src/pic32mz/pic32mz-lowconsole.c
@@ -0,0 +1,352 @@
+/******************************************************************************
+ * arch/mips/src/pic32mz/pic32mz-lowconsole.c
+ *
+ *   Copyright (C) 2015 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ * Included Files
+ ******************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "pic32mz-config.h"
+#include "chip/pic32mz-uart.h"
+
+/******************************************************************************
+ * Pre-processor Definitions
+ ******************************************************************************/
+
+/* Select UART parameters for the selected console */
+
+#ifdef HAVE_SERIAL_CONSOLE
+#  if defined(CONFIG_UART1_SERIAL_CONSOLE)
+#    define PIC32MZ_CONSOLE_BASE     PIC32MZ_UART1_K1BASE
+#    define PIC32MZ_CONSOLE_BAUD     CONFIG_UART1_BAUD
+#    define PIC32MZ_CONSOLE_BITS     CONFIG_UART1_BITS
+#    define PIC32MZ_CONSOLE_PARITY   CONFIG_UART1_PARITY
+#    define PIC32MZ_CONSOLE_2STOP    CONFIG_UART1_2STOP
+#  elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+#    define PIC32MZ_CONSOLE_BASE     PIC32MZ_UART2_K1BASE
+#    define PIC32MZ_CONSOLE_BAUD     CONFIG_UART2_BAUD
+#    define PIC32MZ_CONSOLE_BITS     CONFIG_UART2_BITS
+#    define PIC32MZ_CONSOLE_PARITY   CONFIG_UART2_PARITY
+#    define PIC32MZ_CONSOLE_2STOP    CONFIG_UART2_2STOP
+#  elif defined(CONFIG_UART3_SERIAL_CONSOLE)
+#    define PIC32MZ_CONSOLE_BASE     PIC32MZ_UART3_K1BASE
+#    define PIC32MZ_CONSOLE_BAUD     CONFIG_UART3_BAUD
+#    define PIC32MZ_CONSOLE_BITS     CONFIG_UART3_BITS
+#    define PIC32MZ_CONSOLE_PARITY   CONFIG_UART3_PARITY
+#    define PIC32MZ_CONSOLE_2STOP    CONFIG_UART3_2STOP
+#  elif defined(CONFIG_UART4_SERIAL_CONSOLE)
+#    define PIC32MZ_CONSOLE_BASE     PIC32MZ_UART4_K1BASE
+#    define PIC32MZ_CONSOLE_BAUD     CONFIG_UART4_BAUD
+#    define PIC32MZ_CONSOLE_BITS     CONFIG_UART4_BITS
+#    define PIC32MZ_CONSOLE_PARITY   CONFIG_UART4_PARITY
+#    define PIC32MZ_CONSOLE_2STOP    CONFIG_UART4_2STOP
+#  elif defined(CONFIG_UART5_SERIAL_CONSOLE)
+#    define PIC32MZ_CONSOLE_BASE     PIC32MZ_UART5_K1BASE
+#    define PIC32MZ_CONSOLE_BAUD     CONFIG_UART5_BAUD
+#    define PIC32MZ_CONSOLE_BITS     CONFIG_UART5_BITS
+#    define PIC32MZ_CONSOLE_PARITY   CONFIG_UART5_PARITY
+#    define PIC32MZ_CONSOLE_2STOP    CONFIG_UART5_2STOP
+#  elif defined(CONFIG_UART6_SERIAL_CONSOLE)
+#    define PIC32MZ_CONSOLE_BASE     PIC32MZ_UART6_K1BASE
+#    define PIC32MZ_CONSOLE_BAUD     CONFIG_UART6_BAUD
+#    define PIC32MZ_CONSOLE_BITS     CONFIG_UART6_BITS
+#    define PIC32MZ_CONSOLE_PARITY   CONFIG_UART6_PARITY
+#    define PIC32MZ_CONSOLE_2STOP    CONFIG_UART6_2STOP
+#  else
+#    error "No CONFIG_UARTn_SERIAL_CONSOLE Setting"
+#  endif
+#endif
+
+/******************************************************************************
+ * Private Types
+ ******************************************************************************/
+
+/******************************************************************************
+ * Private Function Prototypes
+ ******************************************************************************/
+
+/******************************************************************************
+ * Global Variables
+ ******************************************************************************/
+
+/******************************************************************************
+ * Private Variables
+ ******************************************************************************/
+
+/******************************************************************************
+ * Private Functions
+ ******************************************************************************/
+
+/******************************************************************************
+ * Name: pic32mz_putreg
+ *
+ * Description:
+ *   Write a value to a UART register
+ *
+ ******************************************************************************/
+
+#ifdef HAVE_UART_DEVICE
+static inline void pic32mz_putreg(uintptr_t uart_base, unsigned int offset,
+                                      uint32_t value)
+{
+  putreg32(value, uart_base + offset);
+}
+#endif
+
+/******************************************************************************
+ * Name: pic32mz_getreg
+ *
+ * Description:
+ *   Get a value from a UART register
+ *
+ ******************************************************************************/
+
+#ifdef HAVE_UART_DEVICE
+static inline uint32_t pic32mz_getreg(uintptr_t uart_base,
+                                          unsigned int offset)
+{
+  return getreg32(uart_base + offset);
+}
+#endif
+
+/******************************************************************************
+ * Name: pic32mz_uartsetbaud
+ *
+ * Description:
+ *   Configure the UART baud rate.
+ *
+ *   With BRGH=0
+ *     BAUD = PBCLK2 / 16 / (BRG+1)
+ *     BRG  = PBCLK2 / 16 / BAUD - 1
+ *   With BRGH=1
+ *     BAUD = PBCLK2 / 4 / (BRG+1)
+ *     BRG  = PBCLK2 / 4 / BAUD - 1
+ *
+ *
+ ******************************************************************************/
+
+#ifdef HAVE_UART_DEVICE
+static void pic32mz_uartsetbaud(uintptr_t uart_base, uint32_t baudrate)
+{
+  uint32_t tmp;
+  uint32_t brg;
+  unsigned int mode;
+
+  /* We want the largest value of BRG divisor possible (for the best accuracy).
+   * Subject to BRG <= 65536.
+   */
+
+  tmp = BOARD_PBCLK2 / baudrate;
+
+  /* Try BRGH=1 first.  This will select the 4x divisor and will produce the
+   * larger BRG divisor, given all other things equal.
+   */
+
+  brg  = (tmp + 2) >> 2;
+  mode = PIC32MZ_UART_MODESET_OFFSET;
+
+  if (brg > 65536)
+    {
+      /* Nope, too big.. try BRGH=0 */
+
+      brg  = (tmp + 8) >> 4;
+      mode = PIC32MZ_UART_MODECLR_OFFSET;
+    }
+  DEBUGASSERT(brg <= 65536);
+
+  /* Set the BRG divisor */
+
+  pic32mz_putreg(uart_base, mode, UART_MODE_BRGH);
+  pic32mz_putreg(uart_base, PIC32MZ_UART_BRG_OFFSET, brg);
+}
+#endif
+
+/******************************************************************************
+ * Public Functions
+ ******************************************************************************/
+
+/******************************************************************************
+ * Name: pic32mz_uartreset
+ *
+ * Description:
+ *   Reset hardware and disable Rx and Tx.
+ *
+ ******************************************************************************/
+
+#ifdef HAVE_UART_DEVICE
+void pic32mz_uartreset(uintptr_t uart_base)
+{
+  /* Doesn't reset the hardware... just shuts it down */
+
+  pic32mz_putreg(uart_base, PIC32MZ_UART_STACLR_OFFSET,
+                 UART_STA_UTXEN | UART_STA_URXEN);
+  pic32mz_putreg(uart_base, PIC32MZ_UART_MODECLR_OFFSET, UART_MODE_ON);
+}
+#endif
+
+/******************************************************************************
+ * Name: pic32mz_uartconfigure
+ *
+ * Description:
+ *   Configure a UART as a RS-232 UART.
+ *
+ ******************************************************************************/
+
+#ifdef HAVE_UART_DEVICE
+void pic32mz_uartconfigure(uintptr_t uart_base, uint32_t baudrate,
+                           unsigned int parity, unsigned int nbits, bool stop2)
+{
+  /* Clear mode and sta bits */
+
+  pic32mz_putreg(uart_base, PIC32MZ_UART_MODECLR_OFFSET,
+                 UART_MODE_STSEL    | UART_MODE_PDSEL_MASK  | UART_MODE_BRGH   |
+                 UART_MODE_RXINV    | UART_MODE_WAKE        | UART_MODE_LPBACK |
+                 UART_MODE_UEN_MASK | UART_MODE_RTSMD       | UART_MODE_IREN   |
+                 UART_MODE_SIDL     | UART_MODE_ON);
+
+  /* Configure the FIFOs:
+   *
+   *   RX: Interrupt at 75% FIFO full (6 of 8 for 8-deep FIFO)
+   *   TX: Interrupt on FIFO empty
+   *   Invert transmit polarity.
+   *
+   * NOTE that there are not many options on trigger TX interrupts.  The FIFO not
+   * full might generate better through-put but with a higher interrupt rate.  FIFO
+   * empty should lower the interrupt rate but result in a burstier output.  If
+   * you change this, please read the comment for acknowledging the interrupt in
+   * pic32mz-serial.c
+   */
+
+  pic32mz_putreg(uart_base, PIC32MZ_UART_STACLR_OFFSET,
+                 UART_STA_UTXINV | UART_STA_UTXISEL_TXBE | UART_STA_URXISEL_RXB75);
+
+  /* Configure the FIFO interrupts */
+
+  pic32mz_putreg(uart_base, PIC32MZ_UART_STASET_OFFSET,
+                 UART_STA_UTXISEL_TXBNF  | UART_STA_URXISEL_RECVD);
+
+  /* Configure word size and parity */
+
+  if (nbits == 9)
+    {
+      DEBUGASSERT(parity == 0);
+      pic32mz_putreg(uart_base, PIC32MZ_UART_MODESET_OFFSET,
+                     UART_MODE_PDSEL_9NONE);
+    }
+  else
+    {
+      DEBUGASSERT(nbits == 8);
+      if (parity == 1)
+        {
+          pic32mz_putreg(uart_base, PIC32MZ_UART_MODESET_OFFSET,
+                         UART_MODE_PDSEL_8ODD);
+        }
+      else if (parity == 2)
+        {
+          pic32mz_putreg(uart_base, PIC32MZ_UART_MODESET_OFFSET,
+                         UART_MODE_PDSEL_8EVEN);
+        }
+    }
+
+  /* Configure 1 or 2 stop bits */
+
+  if (stop2)
+    {
+      pic32mz_putreg(uart_base, PIC32MZ_UART_MODESET_OFFSET,
+                     UART_MODE_STSEL);
+    }
+
+  /* Set the BRG divisor */
+
+  pic32mz_uartsetbaud(uart_base, baudrate);
+
+  /* Enable the UART */
+
+  pic32mz_putreg(uart_base, PIC32MZ_UART_STASET_OFFSET,
+                 UART_STA_UTXEN | UART_STA_URXEN);
+  pic32mz_putreg(uart_base, PIC32MZ_UART_MODESET_OFFSET,
+                 UART_MODE_ON);
+}
+#endif
+
+/******************************************************************************
+ * Name: pic32mz_consoleinit
+ *
+ * Description:
+ *   Initialize a low-level console for debug output.  This function is called
+ *   very early in the initialization sequence to configure the serial console
+ *   UART (only).
+ *
+ ******************************************************************************/
+
+#ifdef HAVE_SERIAL_CONSOLE
+void pic32mz_consoleinit(void)
+{
+  pic32mz_uartconfigure(PIC32MZ_CONSOLE_BASE, PIC32MZ_CONSOLE_BAUD,
+                        PIC32MZ_CONSOLE_PARITY, PIC32MZ_CONSOLE_BITS,
+                        PIC32MZ_CONSOLE_2STOP);
+}
+#endif
+
+/******************************************************************************
+ * Name: up_lowputc
+ *
+ * Description:
+ *   Output one byte on the serial console.
+ *
+ ******************************************************************************/
+
+void up_lowputc(char ch)
+{
+#ifdef HAVE_SERIAL_CONSOLE
+  /* Wait for the transmit buffer not full */
+
+  while ((pic32mz_getreg(PIC32MZ_CONSOLE_BASE, PIC32MZ_UART_STA_OFFSET) & UART_STA_UTXBF) != 0);
+
+  /* Then write the character to the TX data register */
+
+  pic32mz_putreg(PIC32MZ_CONSOLE_BASE, PIC32MZ_UART_TXREG_OFFSET, (uint32_t)ch);
+#endif
+}