/*
 *-----------------------------------------------------------------------------
 * The confidential and proprietary information contained in this file may
 * only be used by a person authorised under and to the extent permitted
 * by a subsisting licensing agreement from ARM Limited.
 *
 *            (C) COPYRIGHT 2010-2017   ARM Limited or its affiliates.
 *                ALL RIGHTS RESERVED
 *
 * This entire notice must be reproduced on all copies of this file
 * and copies of this file may only be made by a person if such person is
 * permitted to do so under the terms of a subsisting license agreement
 * from ARM Limited.
 *
 *      SVN Information
 *
 *      Checked In          : $Date: 2013-04-08 17:48:08 +0100 (Mon, 08 Apr 2013) $
 *
 *      Revision            : $Revision: 366156 $
 *
 *      Release Information : SSE050-r0p1-00rel0
 *-----------------------------------------------------------------------------
 */

// A simple test to check the functionalities of the APB UART


#include "SSE050.h"
#include <stdio.h>
#include <string.h>
#include "uart_stdout.h"
#include "SSE050_driver.h"

#define UART_STATE_TXFULL SSE050_UART_STATE_TXBF_Msk
#define UART_STATE_RXFULL SSE050_UART_STATE_RXBF_Msk
#define UART_STATE_TXOVR  SSE050_UART_STATE_TXOR_Msk
#define UART_STATE_RXOVR  SSE050_UART_STATE_RXOR_Msk

#define UART_CTRL_TXEN         SSE050_UART_CTRL_TXEN_Msk
#define UART_CTRL_RXEN         SSE050_UART_CTRL_RXEN_Msk
#define UART_CTRL_TXIRQEN      SSE050_UART_CTRL_TXIRQEN_Msk
#define UART_CTRL_RXIRQEN      SSE050_UART_CTRL_RXIRQEN_Msk
#define UART_CTRL_TXOVRIRQEN   SSE050_UART_CTRL_TXORIRQEN_Msk
#define UART_CTRL_RXOVRIRQEN   SSE050_UART_CTRL_RXORIRQEN_Msk
#define UART_CTRL_HIGHSPEEDTX  SSE050_UART_CTRL_HSTM_Msk

#define UART_INTSTATE_TX 1
#define UART_INTSTATE_RX 2
#define UART_INTSTATE_TXOVR 4
#define UART_INTSTATE_RXOVR 8

#define BAUDDIV_MASK 0x000FFFFF

#define DISPLAY 1
#define NO_DISPLAY 0

/* peripheral and component ID values */
#define APB_UART_PID4  0x04
#define APB_UART_PID5  0x00
#define APB_UART_PID6  0x00
#define APB_UART_PID7  0x00
#define APB_UART_PID0  0x21
#define APB_UART_PID1  0xB8
#define APB_UART_PID2  0x1B
#define APB_UART_PID3  0x00
#define APB_UART_CID0  0x0D
#define APB_UART_CID1  0xF0
#define APB_UART_CID2  0x05
#define APB_UART_CID3  0xB1
#define HW32_REG(ADDRESS)  (*((volatile unsigned long  *)(ADDRESS)))

/* Global variables */
volatile int uart0_irq_occurred;
volatile int uart1_irq_occurred;
volatile int uart_ovfirq_occurred;
volatile int uart0_irq_expected;
volatile int uart1_irq_expected;
volatile int uart_ovfirq_expected;

/* Function definitions */
int  uart_initial_value_check(SSE050_UART_TypeDef *SSE050_UART);
int  simple_uart_test(SSE050_UART_TypeDef *SSE050_UART, unsigned int bauddiv, int verbose);
int  simple_uart_baud_test(void);
int  simple_uart_baud_test_single(SSE050_UART_TypeDef *SSE050_UART,
                                 unsigned int bauddiv,int verbose);
int  uart_enable_ctrl_test(SSE050_UART_TypeDef *SSE050_UART);
void delay_for_character(void);
int  uart_interrupt_test(SSE050_UART_TypeDef *SSE050_UART);
int  uart1_id_check(void);  /* Detect UART 1 present */

int main (void)
{
  int result=0;

  // UART init
  UartStdOutInit();

  // Test banner message and revision number
  puts("\nSSE-050 - UART Test - revision $Revision: 366156 $\n");

  if ((uart1_id_check()!=0)) {
    puts("** TEST SKIPPED ** UART 1 not available");
    UartEndSimulation();
    return 0;}

  uart0_irq_occurred = 0;
  uart1_irq_occurred = 0;

  uart0_irq_expected = 0;
  uart1_irq_expected = 0;

  uart_ovfirq_occurred = 0;
  uart_ovfirq_expected = 0;

  // UART0, 1 in self loop back */

  // below tests test one UART, in self loop back
  // don't run tests below on UART0 which is used for printf
  result += uart_initial_value_check(SSE050_UART1);
  result += simple_uart_test(SSE050_UART1, 32, DISPLAY);
  result += simple_uart_baud_test();
  result += uart_enable_ctrl_test(SSE050_UART1);

//  puts("\nUART0 interrupt connectivity test\n");
  result += uart_interrupt_test(SSE050_UART0);

//  puts("\nUART1 interrupt connectivity test\n");
  result += uart_interrupt_test(SSE050_UART1);

  if (result==0) {
    printf ("\n** TEST PASSED **\n");
  } else {
    printf ("\n** TEST FAILED ** , Error code = (0x%x)\n", result);
  }
  UartEndSimulation();
  return 0;
}

/* --------------------------------------------------------------- */
/*  UART initial value tests                                       */
/* --------------------------------------------------------------- */
int uart_initial_value_check(SSE050_UART_TypeDef *SSE050_UART){
  int return_val=0;
  int err_code=0;
  unsigned int uart_base;
  unsigned int i;

  if (SSE050_UART!=SSE050_UART1){
    puts ("ERROR: Input parameter invalid in function 'uart_initial_value_check'.");
    return 1;
    }

  puts("- check initial values");
  if (SSE050_UART->DATA     !=0) {err_code += (1<<0);}
  if (SSE050_UART->STATE    !=0) {err_code += (1<<1);}
  if (SSE050_UART->CTRL     !=0) {err_code += (1<<2);}
  if (SSE050_UART->INTSTATUS!=0) {err_code += (1<<3);}
  if (SSE050_UART->BAUDDIV  !=0) {err_code += (1<<4);}

  uart_base = SSE050_UART1_BASE;

  if (HW32_REG(uart_base + 0xFD0) != APB_UART_PID4) {err_code += (1<<5); }
  if (HW32_REG(uart_base + 0xFD4) != APB_UART_PID5) {err_code += (1<<6); }
  if (HW32_REG(uart_base + 0xFD8) != APB_UART_PID6) {err_code += (1<<7); }
  if (HW32_REG(uart_base + 0xFDC) != APB_UART_PID7) {err_code += (1<<8); }
  if (HW32_REG(uart_base + 0xFE0) != APB_UART_PID0) {err_code += (1<<9); }
  if (HW32_REG(uart_base + 0xFE4) != APB_UART_PID1) {err_code += (1<<10); }
  if (HW32_REG(uart_base + 0xFE8) != APB_UART_PID2) {err_code += (1<<11); }
  if (HW32_REG(uart_base + 0xFEC) != APB_UART_PID3) {err_code += (1<<12); }
  if (HW32_REG(uart_base + 0xFF0) != APB_UART_CID0) {err_code += (1<<13); }
  if (HW32_REG(uart_base + 0xFF4) != APB_UART_CID1) {err_code += (1<<14); }
  if (HW32_REG(uart_base + 0xFF8) != APB_UART_CID2) {err_code += (1<<15); }
  if (HW32_REG(uart_base + 0xFFC) != APB_UART_CID3) {err_code += (1<<16); }

  /* test write to PIDs and CIDs - should be ignored */
  for (i=0; i <12; i++) {
    HW32_REG(uart_base + 0xFD0 + (i<<2)) = ~HW32_REG(uart_base + 0xFD0 + (i<<2));
    }

  /* Check read back values again, should not be changed */
  if (HW32_REG(uart_base + 0xFD0) != APB_UART_PID4) {err_code |= (1<<5); }
  if (HW32_REG(uart_base + 0xFD4) != APB_UART_PID5) {err_code |= (1<<6); }
  if (HW32_REG(uart_base + 0xFD8) != APB_UART_PID6) {err_code |= (1<<7); }
  if (HW32_REG(uart_base + 0xFDC) != APB_UART_PID7) {err_code |= (1<<8); }
  if (HW32_REG(uart_base + 0xFE0) != APB_UART_PID0) {err_code |= (1<<9); }
  if (HW32_REG(uart_base + 0xFE4) != APB_UART_PID1) {err_code |= (1<<10); }
  if (HW32_REG(uart_base + 0xFE8) != APB_UART_PID2) {err_code |= (1<<11); }
  if (HW32_REG(uart_base + 0xFEC) != APB_UART_PID3) {err_code |= (1<<12); }
  if (HW32_REG(uart_base + 0xFF0) != APB_UART_CID0) {err_code |= (1<<13); }
  if (HW32_REG(uart_base + 0xFF4) != APB_UART_CID1) {err_code |= (1<<14); }
  if (HW32_REG(uart_base + 0xFF8) != APB_UART_CID2) {err_code |= (1<<15); }
  if (HW32_REG(uart_base + 0xFFC) != APB_UART_CID3) {err_code |= (1<<16); }

  if (err_code != 0) {
    printf ("ERROR : initial value failed (0x%x)\n", err_code);
    return_val =1;
    err_code = 0;
    }

  return(return_val);
}

/* --------------------------------------------------------------- */
/*  UART simple operation test                                     */
/* --------------------------------------------------------------- */
int simple_uart_test(SSE050_UART_TypeDef *SSE050_UART, unsigned int bauddiv, int verbose)
{
  int return_val=0;
  int err_code=0;
  SSE050_UART_TypeDef *UART;
  char        received_text[20];
  const char  transmit_text[20] = "Hello world\n";
  unsigned int tx_count;
  unsigned int rx_count;
  unsigned int str_size;

  puts("Simple test");
  UartPutc('-');
  UartPutc(' ');

  if (SSE050_UART==SSE050_UART1){
    UART = SSE050_UART1;
    }
  else {
    puts ("ERROR: Input parameter invalid in function 'simple_uart_baud_test_single'.");
    return 1;
    }

  UART->BAUDDIV = bauddiv;
  if (UART->BAUDDIV != bauddiv) { err_code += (1<<0);}

  UART->CTRL =   UART->CTRL | UART_CTRL_TXEN | UART_CTRL_RXEN; /* Set TX and RX enable */
  if ((UART->CTRL & UART_CTRL_TXEN)==0) { err_code += (1<<2);}
  if ((UART->CTRL & UART_CTRL_RXEN)==0) { err_code += (1<<3);}

  tx_count = 0;
  rx_count = 0;
  str_size = strlen(transmit_text);
  do { /* test loop for both tx and rx process */
    /* tx process */
    if (((UART->STATE & UART_STATE_TXFULL)==0)&&(tx_count<str_size)) {
      UART->DATA = transmit_text[tx_count];
      tx_count++;
      }
    /* rx process */
    if ((UART->STATE & UART_STATE_RXFULL)!=0) {
      received_text[rx_count] = UART->DATA;
      if (verbose) UartPutc((char) received_text[rx_count]);
      rx_count++;
      }
  } while ( rx_count <str_size);
  received_text[rx_count]=0; /* add NULL termination */

  /* Added 3 additional null chars to overcome X-termination in test
     when reads back X's beyond null char since a load 32-bit word
     happens rather than a byte access. */
  received_text[rx_count+1]=0; /* add NULL termination */
  received_text[rx_count+2]=0; /* add NULL termination */
  received_text[rx_count+3]=0; /* add NULL termination */
  if (strcmp(transmit_text, received_text)!=0){ err_code += (1<<4);}

  UART->CTRL =  0; /* Clear TX and RX enable */

  if (err_code != 0) {
    printf ("ERROR : simple test failed (0x%x)\n", err_code);
    return_val =1;
    err_code = 0;
    }

  return(return_val);
}
/* --------------------------------------------------------------- */
/*  UART baud rate operation test                                  */
/* --------------------------------------------------------------- */
int simple_uart_baud_test(void)
{
  int return_val=0;
  int err_code=0;
  int i;
  short int bauddiv[10] = {
  63, 64, 35, 38, 40, 46, 85, 49, 51, 37};

  puts("Data transfer test\n");

  for (i=0; i<10; i++) {
    if (simple_uart_baud_test_single(SSE050_UART1,
      bauddiv[i], NO_DISPLAY)!=0) err_code |= 0x1;
    if (err_code != 0) {
      printf ("ERROR : Baud rate test failed (0x%x) at loop %d\n", err_code, i);
      return_val = 1;
      err_code   = 0;
      }
    else {
      printf ("- bauddiv = %d done\n", bauddiv[i]);
      }
    }
  SSE050_UART1->CTRL = 0;
  SSE050_UART1->BAUDDIV = 0xFFFFFFFF;
  if (SSE050_UART1->BAUDDIV != (0xFFFFFFFF & BAUDDIV_MASK)) {err_code |= (1<<0);};
  SSE050_UART1->BAUDDIV = 0xFF55AAC3;
  if (SSE050_UART1->BAUDDIV != (0xFF55AAC3 & BAUDDIV_MASK)) {err_code |= (1<<1);};
  SSE050_UART1->BAUDDIV = 0x00000000;
  if (SSE050_UART1->BAUDDIV != (0x00000000 & BAUDDIV_MASK)) {err_code |= (1<<2);};
    if (err_code != 0) {
      printf ("ERROR : Baud rate r/w failed (0x%x)\n", err_code);
      return_val = 1;
      err_code   = 0;
      }


  return(return_val);

}
/* --------------------- */
int simple_uart_baud_test_single(SSE050_UART_TypeDef *SSE050_UART,
                     unsigned int bauddiv,
                     int verbose)
{
  int return_val=0;
  int err_code=0;
  SSE050_UART_TypeDef *UART;
  char        received_text[20];
  const char  transmit_text[20] = "Hello world\n";
  unsigned int tx_count;
  unsigned int rx_count;
  unsigned int str_size;

  if (SSE050_UART==SSE050_UART1){
    UART = SSE050_UART1;
    }
  else {
    puts ("ERROR: Input parameter invalid in function 'simple_uart_baud_test_single'.");
    return 1;
    }

  UART->BAUDDIV = bauddiv;
  if (UART->BAUDDIV != bauddiv) { err_code += (1<<0);}

  UART->CTRL =   UART->CTRL | UART_CTRL_TXEN | UART_CTRL_RXEN;; /* Set TX and RX enable */
  if ((UART->CTRL & UART_CTRL_TXEN)==0) { err_code += (1<<2);}
  if ((UART->CTRL & UART_CTRL_RXEN)==0) { err_code += (1<<3);}

  tx_count = 0;
  rx_count = 0;
  str_size = strlen(transmit_text);
  do { /* test loop for both tx and rx process */
    /* tx process */
    if (((UART->STATE & UART_STATE_TXFULL)==0)&&(tx_count<str_size)) {
      UART->DATA = transmit_text[tx_count];
      tx_count++;
      }
    /* rx process */
    if ((UART->STATE & UART_STATE_RXFULL)!=0) {
      received_text[rx_count] = UART->DATA;
      if (verbose) UartPutc((char) received_text[rx_count]);
      rx_count++;
      }
  } while ( rx_count <str_size);
  received_text[rx_count]=0; /* add NULL termination */

  /* Added 3 additional null chars to overcome X-termination in test
     when reads back X's beyond null char since a load 32-bit word
     happens rather than a byte access. */
  received_text[rx_count+1]=0; /* add NULL termination */
  received_text[rx_count+2]=0; /* add NULL termination */
  received_text[rx_count+3]=0; /* add NULL termination */
  if (strcmp(transmit_text, received_text)!=0){ err_code += (1<<4);}

  UART->CTRL =  0; /* Clear TX and RX enable */

  if (err_code != 0) {
    printf ("ERROR : baud test failed (0x%x)\n", err_code);
    return_val =1;
    err_code = 0;
    }

  return(return_val);
}
/* --------------------------------------------------------------- */
/*  UART enable control test                                       */
/* --------------------------------------------------------------- */
int uart_enable_ctrl_test(SSE050_UART_TypeDef *SSE050_UART)
{
  int return_val=0;
  int err_code=0;
  SSE050_UART_TypeDef *UART;
  char ctmp;

  if (SSE050_UART==SSE050_UART1){
    UART = SSE050_UART1;
    }
  else {
    puts ("ERROR: Input parameter invalid in function 'simple_uart_baud_test_single'.");
    return 1;
    }

  puts ("UART enable test");
  UART->BAUDDIV = 32;
  if (UART->BAUDDIV != 32) { err_code += (1<<0);}

  puts ("- both TX and RX are enabled");
  UART->CTRL =   UART->CTRL | UART_CTRL_TXEN | UART_CTRL_RXEN; /* Set TX and RX enable */
  if ((UART->CTRL & UART_CTRL_TXEN)==0) { err_code += (1<<2);}
  if ((UART->CTRL & UART_CTRL_RXEN)==0) { err_code += (1<<3);}

  if (((UART->STATE & UART_STATE_TXFULL)!=0) ||
      ((UART->STATE & UART_STATE_RXFULL)!=0)) {
      /* Starting state incorrect */
      err_code += (1<<4);}
  UART->DATA = 'A'; /* transmit a character */
  delay_for_character();
  if (((UART->STATE & UART_STATE_TXFULL)!=0) ||
      ((UART->STATE & UART_STATE_RXFULL)==0)) {
      /* complete state incorrect */
      err_code += (1<<5);}
  ctmp = UART->DATA; /* Read received data */
  if ((UART->STATE & UART_STATE_RXFULL)!=0) {
      /* receive buffer should be empty now */
      err_code += (1<<6);}
  if (  ctmp != 'A') { /* received data incorrect */
      err_code += (1<<7);}

  puts ("- TX disabled");
  UART->CTRL =   UART->CTRL & ~UART_CTRL_TXEN; /* Clear TX enable */
  if ((UART->CTRL & UART_CTRL_TXEN)!=0) { err_code += (1<<8);}

  if (((UART->STATE & UART_STATE_TXFULL)!=0) ||
      ((UART->STATE & UART_STATE_RXFULL)!=0)) {
      /* Starting state incorrect */
      err_code += (1<<9);}
  UART->DATA = 'B'; /* transmit a character */

  /* When TX enable is low and a data is written to transmit buffer, the
     data would be lost */
  delay_for_character();
  if ((UART->STATE & UART_STATE_RXFULL)!=0)  {
      /* RX buffer should still be empty*/
      err_code += (1<<10);}
  UART->CTRL =   UART->CTRL | UART_CTRL_TXEN; /* Set TX enable */
  delay_for_character();

  if (((UART->STATE & UART_STATE_TXFULL)!=0) ||
      ((UART->STATE & UART_STATE_RXFULL)!=0)) {
      /* complete state incorrect */
      err_code += (1<<11);}

  puts ("- RX disabled");
  UART->CTRL =   UART->CTRL & ~UART_CTRL_RXEN; /* Clear RX enable */
  if ((UART->CTRL & UART_CTRL_RXEN)!=0) { err_code += (1<<12);}

  UART->DATA = 'C'; /* transmit a character */
  delay_for_character();
  if (((UART->STATE & UART_STATE_TXFULL)!=0) ||
      ((UART->STATE & UART_STATE_RXFULL)!=0)) {
      /* No data should be received. complete state incorrect */
      err_code += (1<<13);}
  UART->CTRL =   UART->CTRL | UART_CTRL_RXEN; /* Set RX enable */
  delay_for_character();
  if (((UART->STATE & UART_STATE_TXFULL)!=0) ||
      ((UART->STATE & UART_STATE_RXFULL)!=0)) {
      /* No data should be received. complete state incorrect */
      err_code += (1<<14);}

  UART->CTRL = 0;
  while ((UART->STATE & UART_STATE_RXFULL)!=0) {
    ctmp=UART->DATA;
    }

  if (err_code != 0) {
    printf ("ERROR : uart enable failed (0x%x)\n", err_code);
    return_val =1;
    err_code = 0;
    }

  return(return_val);
}

/* --------------------------------------------------------------- */
/*  UART 0/1 interrupt connectivity test                         */
/* --------------------------------------------------------------- */
int uart_interrupt_test(SSE050_UART_TypeDef *SSE050_UART){
  int return_val=0;
  int err_code=0;
  int i;

  uart0_irq_expected = 0;
  uart0_irq_occurred = 0;
  uart1_irq_expected = 0;
  uart1_irq_occurred = 0;

  SSE050_UART->BAUDDIV = 0x10; // set baud rate for high speed tx

//  puts ("- UART TX IRQ");
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_TXIRQEN | UART_CTRL_HIGHSPEEDTX;
  if (SSE050_UART == SSE050_UART0) {
    NVIC_EnableIRQ(UART0_IRQn);
    uart0_irq_expected = 1;
  } else if (SSE050_UART == SSE050_UART1) {
    NVIC_EnableIRQ(UART1_IRQn);
    uart1_irq_expected = 1;
  }  else {
    puts ("ERROR: Input parameter invalid in function 'uart_interrupt_test'.");
    return 1;
    }

  SSE050_UART->DATA = '.';
  for (i=0; i<3;i++){ __ISB(); } /* small delay */
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_HIGHSPEEDTX;
  if ((SSE050_UART==SSE050_UART0 && uart0_irq_occurred==0) ||
      (SSE050_UART==SSE050_UART1 && uart1_irq_occurred==0)) { err_code += (1<<0);}
  uart0_irq_occurred = 0;
  uart1_irq_occurred = 0;
  if (SSE050_UART == SSE050_UART0) NVIC_DisableIRQ(UART0_IRQn);
  if (SSE050_UART == SSE050_UART1) NVIC_DisableIRQ(UART1_IRQn);
  uart0_irq_expected = 0;
  uart1_irq_expected = 0;

//  puts ("\n- UART TX overflow IRQ");
  NVIC_EnableIRQ(UARTOVF_IRQn);
  uart_ovfirq_expected = 1;
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_TXOVRIRQEN | UART_CTRL_HIGHSPEEDTX;
  SSE050_UART->DATA = '.';
  SSE050_UART->DATA = '.';
  SSE050_UART->DATA = '.';
  for (i=0; i<3;i++){ __ISB(); } /* small delay */
  if (uart_ovfirq_occurred==0)                         { err_code += (1<<1);}
  uart_ovfirq_occurred = 0;
  NVIC_DisableIRQ(UARTOVF_IRQn);
  uart_ovfirq_expected = 0;

//  puts ("\n- UART RX IRQ");
  if (SSE050_UART == SSE050_UART0) {
    NVIC_EnableIRQ(UART0_IRQn);
    uart0_irq_expected = 1;
  } else if (SSE050_UART == SSE050_UART1) {
    NVIC_EnableIRQ(UART1_IRQn);
    uart1_irq_expected = 1;
  }
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_RXEN | UART_CTRL_RXIRQEN | UART_CTRL_HIGHSPEEDTX;
  SSE050_UART->DATA = '.';
  for (i=0; i<50;i++){ __ISB(); } /* medium delay */
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_RXEN | UART_CTRL_HIGHSPEEDTX;
  if ((SSE050_UART==SSE050_UART0 && uart0_irq_occurred==0) ||
      (SSE050_UART==SSE050_UART1 && uart1_irq_occurred==0)) { err_code += (1<<2);}
  uart0_irq_occurred = 0;
  uart1_irq_occurred = 0;
  if (SSE050_UART == SSE050_UART0) NVIC_DisableIRQ(UART0_IRQn);
  if (SSE050_UART == SSE050_UART1) NVIC_DisableIRQ(UART1_IRQn);
  uart0_irq_expected = 0;
  uart1_irq_expected = 0;

//  puts ("\n- UART RX overflow IRQ");
  NVIC_EnableIRQ(UARTOVF_IRQn);
  uart_ovfirq_expected = 1;
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_RXEN | UART_CTRL_RXOVRIRQEN | UART_CTRL_HIGHSPEEDTX;
  SSE050_UART->DATA = '.';
  SSE050_UART->DATA = '.';
  SSE050_UART->DATA = '.';
  for (i=0; i<50;i++){ __ISB(); } /* medium delay */
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_RXEN | UART_CTRL_HIGHSPEEDTX;
  if (uart_ovfirq_occurred==0)                         { err_code += (1<<4);}
  uart_ovfirq_occurred = 0;
  NVIC_DisableIRQ(UARTOVF_IRQn);
  uart_ovfirq_expected = 0;

  /* clean up */
  SSE050_UART->CTRL = UART_CTRL_TXEN | UART_CTRL_HIGHSPEEDTX;

  if (err_code != 0) {
    printf ("ERROR : interrupt connectivity test failed (0x%x)\n", err_code);
    return_val =1;
    err_code = 0;
    }

  return(return_val);
}
/* --------------------------------------------------------------- */
/*  delay function to provide delay for one character              */
/* --------------------------------------------------------------- */

void delay_for_character(void)
{
  int i;
  for (i=0; i<120;i++){
    __ISB();
    }
  return;
}
/* --------------------------------------------------------------- */
/*  Peripheral ID detection to check if device is present          */
/* --------------------------------------------------------------- */
int uart0_id_check(void)
{
if ((HW32_REG(SSE050_UART0_BASE + 0xFE0) != 0x21) ||
    (HW32_REG(SSE050_UART0_BASE + 0xFE4) != 0xB8))
  return 1; /* part ID does not match */
else
  return 0;
}

int uart1_id_check(void)
{
if ((HW32_REG(SSE050_UART1_BASE + 0xFE0) != 0x21) ||
    (HW32_REG(SSE050_UART1_BASE + 0xFE4) != 0xB8))
  return 1; /* part ID does not match */
else
  return 0;
}

int gpio1_id_check(void)
{
if ((HW32_REG(SSE050_GPIO1_BASE + 0xFE0) != 0x20) ||
    (HW32_REG(SSE050_GPIO1_BASE + 0xFE4) != 0xB8))
  return 1; /* part ID does not match */
else
  return 0;
}
/* --------------------------------------------------------------- */
/*  UART interrupt handlers                                        */
/* --------------------------------------------------------------- */
void UART0_Handler(void)
{
  int err_code = 0;
  if (uart0_irq_expected==0)                           {err_code += (1<<0);}
  if (SSE050_UART0->INTSTATUS==0) {err_code += (1<<1);}
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_TX)!=0)
     SSE050_UART0->INTCLEAR = UART_INTSTATE_TX; // clear TX IRQ
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RX)!=0)
     SSE050_UART0->INTCLEAR = UART_INTSTATE_RX; // clear RX IRQ
  uart0_irq_occurred++;
  if (err_code != 0) {
    printf ("ERROR : UART 0 handler failed (0x%x)\n", err_code);
    UartEndSimulation();
    while(1);
    }
  return;
}

void UART1_Handler(void)
{
  int err_code = 0;
  if (uart1_irq_expected==0)                           {err_code += (1<<0);}
  if (SSE050_UART1->INTSTATUS==0) {err_code += (1<<1);}
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TX)!=0)
     SSE050_UART1->INTCLEAR = UART_INTSTATE_TX; // clear TX IRQ
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RX)!=0)
     SSE050_UART1->INTCLEAR = UART_INTSTATE_RX; // clear RX IRQ
  uart1_irq_occurred++;
  if (err_code != 0) {
    printf ("ERROR : UART 3 handler failed (0x%x)\n", err_code);
    UartEndSimulation();
    while(1);
    }
  return;
}

void UARTOVF_Handler(int uartid)
{
  int err_code = 0;
  if (uart_ovfirq_expected==0)                               {err_code += (1<<0);}
  if (((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)!=0) |
      ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)!=0))
    uart_ovfirq_occurred++;
  if (((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)!=0) |
      ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)!=0))
    uart_ovfirq_occurred++;
  if (((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)!=0) |
      ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)!=0))
    uart_ovfirq_occurred++;
  if (((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)!=0) |
      ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)!=0))
    uart_ovfirq_occurred++;
  if (((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)==0) &
      ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)==0) &
      ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)==0) &
      ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)==0) &
      ((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)==0) &
      ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)==0) &
      ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)==0) &
      ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)==0)) {err_code += (1<<1);}
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)!=0){
    SSE050_UART0->INTCLEAR = UART_STATE_TXOVR; /* Clear TX overrun status */
    }
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)!=0){
    SSE050_UART0->INTCLEAR = UART_STATE_RXOVR; /* Clear RX overrun status */
    }
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)!=0){
    SSE050_UART1->INTCLEAR = UART_STATE_TXOVR; /* Clear TX overrun status */
    }
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)!=0){
    SSE050_UART1->INTCLEAR = UART_STATE_RXOVR; /* Clear RX overrun status */
    }
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)!=0){
    SSE050_UART0->INTCLEAR = UART_STATE_TXOVR; /* Clear TX overrun status */
    }
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)!=0){
    SSE050_UART0->INTCLEAR = UART_STATE_RXOVR; /* Clear RX overrun status */
    }
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)!=0){
    SSE050_UART1->INTCLEAR = UART_STATE_TXOVR; /* Clear TX overrun status */
    }
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)!=0){
    SSE050_UART1->INTCLEAR = UART_STATE_RXOVR; /* Clear RX overrun status */
    }
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)!=0)  {err_code += (1<<2);}
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)!=0)  {err_code += (1<<3);}
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)!=0)  {err_code += (1<<4);}
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)!=0)  {err_code += (1<<5);}
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_TXOVR)!=0)  {err_code += (1<<6);}
  if ((SSE050_UART0->INTSTATUS & UART_INTSTATE_RXOVR)!=0)  {err_code += (1<<7);}
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_TXOVR)!=0)  {err_code += (1<<8);}
  if ((SSE050_UART1->INTSTATUS & UART_INTSTATE_RXOVR)!=0)  {err_code += (1<<9);}
  if (err_code != 0) {
    printf ("ERROR : UART overrun handler failed (0x%x)\n", err_code);
    UartEndSimulation();
    while(1);
    }  return;
}

