diff src/cs/drivers/drv_core/uart/serialswitch_core.c @ 0:b6a5e36de839

src/cs: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:39:26 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/drivers/drv_core/uart/serialswitch_core.c	Sun Jul 15 04:39:26 2018 +0000
@@ -0,0 +1,1479 @@
+/*******************************************************************************
+ *
+ * SERIALSWITCH_CORE.C
+ *
+ * This module allows managing the use of the serial ports of TI GSM Evaluation
+ * Boards.
+ * An application may have to send several serial data flows. The board on which
+ * the application is running may have one or several devices. The purpose of
+ * this module is to establish connections between the serial data flows and the
+ * serial devices at runtime, when the application is started.
+ *
+ * (C) Texas Instruments 1999 - 2003
+ *
+ ******************************************************************************/
+/*
+ * 17/12/03
+ * Duplication of serialswitch.c for L1 standalone only
+ *
+ ******************************************************************************/
+
+#define __SERIALSWITCH_CORE_C__
+
+#define __STANDARD_H__ /* Avoid to define UBYTE, SYS_UWORD16 and UINT32. */
+
+#include "l1sw.cfg"
+#include "chipset.cfg"
+
+
+#if (OP_L1_STANDALONE == 0)
+  #include "main/sys_types.h"
+#else
+  #include "sys_types.h"
+#endif
+
+#include "nucleus.h"
+
+#include "traceswitch.h"
+#include "serialswitch_core.h" 
+
+#include "uart/uart.h"
+
+#include "memif/mem.h" 
+
+#define DUMMY_DEVICE (0)
+
+#define IIR (0x02) /* UART interrupt ident. register - Read only  */
+#define SCR (0x10) /* UART suppl. control register   - Read/Write */
+#define SSR (0x11) /* UART suppl. status register    - Read only  */
+
+/*
+ * Interrupt identification register.
+ * Bit 0 is set to 0 if an IT is pending.
+ * Bits 1 and 2 are used to identify the IT.
+ */
+
+#define IIR_BITS_USED  (0x07)
+#define IT_NOT_PENDING (0x01)
+
+/*
+ * Supplementary Control Register
+ */
+
+#define RX_CTS_WAKE_UP_ENABLE_BIT (4)
+
+/*
+ * Supplementary Status Register
+ */
+
+#define RX_CTS_WAKE_UP_STS (0x02) /* Wake-up interrupt occurred  */
+
+/*
+ * This macro allows to read an UART register.
+ */
+
+#define READ_UART_REGISTER(UART,REG) \
+            *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG)))
+
+
+/*
+ * This macro allows to disable the UART's wake-up interrupt.
+ */
+
+#define DISABLE_WAKE_UP_INTERRUPT(UART) \
+            *((volatile SYS_UWORD8 *) ((UART)->base_address + SCR)) &= \
+                ~(1 << (RX_CTS_WAKE_UP_ENABLE_BIT)); 
+
+/*
+ * Wake-up time duration in seconds and in number of TDMAs.
+ * 1 TDMA = (6 / 1300) s = 0.004615 s (= 4.615 ms).
+ */
+
+#define WAKE_UP_TIME_DURATION (10)  /* 10 seconds */
+#define WAKE_UP_TIME_IN_TDMA  (WAKE_UP_TIME_DURATION * 1300 / 6)
+
+
+/*
+ * Global uartswitch variable as read from FFS.
+ * It is supposed that NUMBER_OF_TR_UART, NUMBER_OF_FD_UART
+ * and NUMBER_OF_BT_UART have the same values.
+ */
+
+#define DUMMY             ('0')
+#define G23_PANEL         ('G')
+#define RIVIERA_TRACE_MUX ('R')
+#define FD_AT_COMMAND     ('D')
+#define BLUETOOTH_HCI     ('B')
+
+#if (CHIPSET == 12)
+  char ser_cfg_info[NUMBER_OF_TR_UART] = {DUMMY, DUMMY, DUMMY};
+#else
+  char ser_cfg_info[NUMBER_OF_TR_UART] = {DUMMY, DUMMY};
+#endif
+static SYS_UWORD16 serial_cfg = 0x0048; /* All dummies */
+
+/*
+ * Types of flows supported.
+ */
+
+typedef enum {
+    TRACE_FLOW
+#if (OP_L1_STANDALONE == 0)
+    , FAX_DATA_FLOW,
+    BLUETOOTH_HCI_FLOW
+#endif
+} t_flow_type;
+
+/*
+ * For each serial data flow, a set of function pointers allows calling the
+ * functions associated to a serial device.
+ */
+
+typedef struct s_tr_functions {
+
+    T_tr_UartId   device;
+    
+    void (*tr_Init) (T_tr_UartId device,
+                     T_tr_Baudrate baudrate,
+                     void (callback_function (void)));
+                         
+    SYS_UWORD32 (*tr_ReadNChars) (T_tr_UartId device,
+                                  char *buffer,
+                                  SYS_UWORD32 chars_to_read);
+
+    SYS_UWORD32 (*tr_ReadNBytes) (T_tr_UartId device,
+                                  char *buffer,
+                                  SYS_UWORD32 chars_to_read,
+                                  SYS_BOOL *eof_detected);
+
+    SYS_UWORD32 (*tr_WriteNChars) (T_tr_UartId device,
+                                   char *buffer,
+                                   SYS_UWORD32 chars_to_write);
+
+    SYS_UWORD32 (*tr_EncapsulateNChars) (T_tr_UartId device,
+                                         char *buffer,
+                                         SYS_UWORD32 chars_to_write);
+
+    SYS_UWORD32 (*tr_WriteNBytes) (T_tr_UartId device,
+                                   SYS_UWORD8 *buffer,
+                                   SYS_UWORD32 chars_to_write);
+
+    void  (*tr_WriteChar) (T_tr_UartId device,
+                           char character);
+
+    void  (*tr_WriteString) (T_tr_UartId device,
+                             char *buffer);
+
+    SYS_BOOL (*tr_EnterSleep) (T_tr_UartId device);
+
+    void (*tr_WakeUp) (T_tr_UartId device);
+
+} t_tr_functions;
+
+
+/*
+ * Prototypes of dummy functions.
+ * Dummy functions for Trace.
+ */
+
+static void dummy_tr_Init (T_tr_UartId device,
+                           T_tr_Baudrate baudrate,
+                           void (callback_function (void)));
+ 
+static SYS_UWORD32 dummy_tr_ReadNChars (T_tr_UartId device,
+                                        char *buffer,
+                                        SYS_UWORD32 chars_to_read);
+
+static SYS_UWORD32 dummy_tr_ReadNBytes (T_tr_UartId device,
+                                        char *buffer,
+                                        SYS_UWORD32 chars_to_read,
+                                        SYS_BOOL *eof_detected);
+ 
+static SYS_UWORD32 dummy_tr_WriteNChars (T_tr_UartId device,
+                                         char *buffer,
+                                         SYS_UWORD32 chars_to_write);
+ 
+static SYS_UWORD32 dummy_tr_EncapsulateNChars (T_tr_UartId device,
+                                               char *buffer,
+                                               SYS_UWORD32 chars_to_write);
+ 
+static SYS_UWORD32 dummy_tr_WriteNBytes (T_tr_UartId device,
+                                         SYS_UWORD8 *buffer,
+                                         SYS_UWORD32 chars_to_write);
+ 
+static void dummy_tr_WriteChar (T_tr_UartId device,
+                                char character);
+ 
+static void dummy_tr_WriteString (T_tr_UartId device,
+                                  char *buffer);
+ 
+static SYS_BOOL dummy_tr_EnterSleep (T_tr_UartId device);
+ 
+static void dummy_tr_WakeUp (T_tr_UartId device);
+ 
+
+ 
+
+/*
+ * Constants tables representing the various possible configurations
+ * for Trace, Fax & Data and Bluetooth HCI according to the different devices.
+ * Constant table for Trace using no device.
+ */
+
+static const t_tr_functions dummy_trace = {
+
+    (T_tr_UartId) DUMMY_DEVICE,
+    dummy_tr_Init,
+    dummy_tr_ReadNChars,
+    dummy_tr_ReadNBytes,
+    dummy_tr_WriteNChars,
+    dummy_tr_EncapsulateNChars,
+    dummy_tr_WriteNBytes,
+    dummy_tr_WriteChar,
+    dummy_tr_WriteString,
+    dummy_tr_EnterSleep,
+    dummy_tr_WakeUp
+};
+
+/*
+ * Constant table for Trace using UART IrDA.
+ */
+
+static const t_tr_functions uart_irda_trace = {
+
+    UA_UART_0,
+    UA_Init,
+    UA_ReadNChars,
+    UA_ReadNBytes,
+    UA_WriteNChars,
+    UA_EncapsulateNChars,
+    UA_WriteNBytes,
+    UA_WriteChar,
+    UA_WriteString,
+    UA_EnterSleep,
+    UA_WakeUp
+};
+
+/*
+ * Constant table for Trace using UART Modem.
+ */
+
+static const t_tr_functions uart_modem_trace = {
+
+    UA_UART_1,
+    UA_Init,
+    UA_ReadNChars,
+    UA_ReadNBytes,
+    UA_WriteNChars,
+    UA_EncapsulateNChars,
+    UA_WriteNBytes,
+    UA_WriteChar,
+    UA_WriteString,
+    UA_EnterSleep,
+    UA_WakeUp
+};
+
+#if (CHIPSET == 12)
+  /*
+   * Constant table for Trace using UART Modem2.
+   */
+
+  static const t_tr_functions uart_modem2_trace = {
+
+      UA_UART_2,
+      UA_Init,
+      UA_ReadNChars,
+      UA_ReadNBytes,
+      UA_WriteNChars,
+      UA_EncapsulateNChars,
+      UA_WriteNBytes,
+      UA_WriteChar,
+      UA_WriteString,
+      UA_EnterSleep,
+      UA_WakeUp
+  };
+#endif
+
+
+
+/*
+ * UART structure used for UARTs.
+ */
+ 
+typedef struct s_uart {
+    
+    SYS_UWORD32 base_address;
+    SYS_BOOL    device_used;
+    SYS_BOOL    deep_sleep_set_up;
+    t_flow_type flow_type;
+    SYS_WORD16  flow_id;
+    void (*interrupt_handler) (int uart_id,
+                               SYS_UWORD8 interrupt_status);
+    
+} t_uart;
+
+static const t_tr_functions *tr_functions[SER_MAX_NUMBER_OF_FLOWS];
+
+
+/*
+ * Timer used for duration control when UARTs are waked up by an interrupt or
+ * each time any new incoming characters are received; This timer prevents the
+ * system to enter deep sleep mode.
+ */
+
+static NU_TIMER uart_sleep_timer;
+       SYS_BOOL uart_sleep_timer_enabled;
+
+/*
+ * HISR used to reset and restart the sleep timer from an UART use by a Trace
+ * flow in case of incoming characters.
+ */
+
+#define TIMER_HISR_PRIORITY      (2)
+#define TIMER_HISR_STACK_SIZE  (512) /* Bytes. */ 
+
+static NU_HISR timer_hisr_ctrl_block;
+static char    timer_hisr_stack[TIMER_HISR_STACK_SIZE];
+
+/*
+ * For next arrays, it is supposed that NUMBER_OF_TR_UART, NUMBER_OF_FD_UART
+ * and NUMBER_OF_BT_UART have the same values.
+ * An index on an internal uart for trace, fax & data or bluetooth hci reffers
+ * to the same uart device.
+ */
+ 
+static t_uart int_uart[NUMBER_OF_TR_UART];
+
+#if ((CHIPSET == 2) || (CHIPSET == 3))
+  static SYS_UWORD32 uart_spurious_interrupts;
+#elif ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12))
+  static SYS_UWORD32 uart_modem_spurious_interrupts;
+  static SYS_UWORD32 uart_irda_spurious_interrupts;
+#endif
+#if (CHIPSET == 12)
+  static SYS_UWORD32 uart_modem2_spurious_interrupts;
+#endif
+
+static const SYS_UWORD32 uart_base_address[NUMBER_OF_TR_UART] =
+{
+    MEM_UART_IRDA,
+    MEM_UART_MODEM
+    #if (CHIPSET == 12)
+      , MEM_UART_MODEM2
+    #endif
+};
+
+ 
+/*******************************************************************************
+ *
+ *                              dummy_tr_Init
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_Init.
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+ 
+static void
+dummy_tr_Init (T_tr_UartId device,
+               T_tr_Baudrate baudrate,
+               void (callback_function (void)))
+{
+    /*
+     * No action.
+     */
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_ReadNChars
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_ReadNChars.
+ *
+ * Return: 0
+ *
+ ******************************************************************************/
+ 
+static SYS_UWORD32
+dummy_tr_ReadNChars (T_tr_UartId device,
+                     char *buffer,
+                     SYS_UWORD32 chars_to_read)
+{
+    return (0);
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_ReadNBytes
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_ReadNBytes.
+ *
+ * Return: 0
+ *
+ ******************************************************************************/
+ 
+static SYS_UWORD32
+dummy_tr_ReadNBytes (T_tr_UartId device,
+                     char *buffer,
+                     SYS_UWORD32 chars_to_read,
+                     SYS_BOOL *eof_detected)
+{
+    return (0);
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_WriteNChars
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_WriteNChars.
+ *
+ * Return: The number of character to write.
+ *
+ ******************************************************************************/
+ 
+static SYS_UWORD32
+dummy_tr_WriteNChars (T_tr_UartId device,
+                      char *buffer,
+                      SYS_UWORD32 chars_to_write)
+{
+    return (chars_to_write);
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_EncapsulateNChars
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_EncapsulateNChars.
+ *
+ * Return: The number of character to write.
+ *
+ ******************************************************************************/
+ 
+static SYS_UWORD32
+dummy_tr_EncapsulateNChars (T_tr_UartId device,
+                      char *buffer,
+                      SYS_UWORD32 chars_to_write)
+{
+    return (chars_to_write);
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_WriteNBytes
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_WriteNBytes.
+ *
+ * Return: The number of byte to write.
+ *
+ ******************************************************************************/
+ 
+static SYS_UWORD32
+dummy_tr_WriteNBytes (T_tr_UartId device,
+                      SYS_UWORD8 *buffer,
+                      SYS_UWORD32 chars_to_write)
+{
+    return (chars_to_write);
+}
+
+/*******************************************************************************
+ *
+ *                              dummy_tr_WriteChar
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_WriteChar.
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+ 
+static void
+dummy_tr_WriteChar (T_tr_UartId device,
+                    char character)
+{
+    /*
+     * No action.
+     */
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_WriteString
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_WriteString.
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+ 
+static void
+dummy_tr_WriteString (T_tr_UartId device,
+                      char *buffer)
+{
+    /*
+     * No action.
+     */
+}
+
+/*******************************************************************************
+ *
+ *                          dummy_tr_EnterSleep
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_EnterSleep.
+ *
+ * Return: 1
+ *
+ ******************************************************************************/
+ 
+static SYS_BOOL
+dummy_tr_EnterSleep (T_tr_UartId device)
+{
+    return (1);
+}
+
+/*******************************************************************************
+ *
+ *                           dummy_tr_WakeUp
+ *
+ * Purpose: No action.
+ *
+ * Parameters: See SER_tr_WakeUp.
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+ 
+static void
+dummy_tr_WakeUp (T_tr_UartId device)
+{
+    /*
+     * No action.
+     */
+}
+
+
+
+/*******************************************************************************
+ *
+ *                     analyze_uart_sleep_timer_expiration
+ * 
+ * Purpose  : The timer has just expired. If requested, UARTs can again be set
+ *            up to enter Deep Sleep.
+ *
+ * Arguments: In : id: parameter not used.
+ *            Out: none
+ *
+ * Returns  : none 
+ *
+ ******************************************************************************/
+
+static VOID
+analyze_uart_sleep_timer_expiration (UNSIGNED id)
+{
+    /*
+     * Timer has expired.
+     * UARTs can again be set up for Deep Sleep.
+     */
+
+    (void) NU_Control_Timer (&uart_sleep_timer,
+                             NU_DISABLE_TIMER);
+      
+    uart_sleep_timer_enabled = 0;
+}
+
+/*******************************************************************************
+ *
+ *                          start_uart_sleep_timer
+ * 
+ * Purpose  : Starts the sleep timer once UARTs have been waked-up by an
+ *            interrupt or if new incoming characters have been received.
+ *
+ * Arguments: In : none
+ *            Out: none
+ *
+ * Returns  : none 
+ *
+ ******************************************************************************/
+
+static void
+start_uart_sleep_timer (void)
+{
+    /*
+     * UART sleep timer is started.
+     * UARTs can't no more be set up for Deep Sleep until the timer expires.
+     */
+
+    (void) NU_Reset_Timer (&uart_sleep_timer,
+                           &analyze_uart_sleep_timer_expiration,
+                           WAKE_UP_TIME_IN_TDMA,
+                           0, /* The timer expires once. */
+                           NU_DISABLE_TIMER);
+
+    (void) NU_Control_Timer (&uart_sleep_timer,
+                             NU_ENABLE_TIMER);
+}
+
+/*******************************************************************************
+ *
+ *                              set_flow_functions
+ *
+ * Purpose: Initializes a serial data flow functions set with the set of
+ *          functions of the selected device.
+ *
+ * Parameters: In : flow         : index of the serial data flow
+ *                  serial_driver: allows knowing which set of functions must
+ *                                 be selected
+ *             Out: none
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+
+static void
+set_flow_functions (int flow,
+                    T_SerialDriver serial_driver)
+{
+
+    switch (serial_driver) {
+
+    case UART_IRDA_TRACE:
+    case UART_MODEM_TRACE:
+    #if (CHIPSET == 12)
+      case UART_MODEM2_TRACE:
+    #endif
+
+        if (serial_driver == UART_IRDA_TRACE)
+            tr_functions[flow] = &uart_irda_trace;
+        else {
+          #if (CHIPSET == 12)
+            if (serial_driver == UART_MODEM2_TRACE)
+                tr_functions[flow] = &uart_modem2_trace;
+            else
+          #endif
+                tr_functions[flow] = &uart_modem_trace;
+        }
+
+        int_uart[tr_functions[flow]->device].device_used = 1;
+        int_uart[tr_functions[flow]->device].flow_type   = TRACE_FLOW;
+        int_uart[tr_functions[flow]->device].flow_id     = flow;
+        int_uart[tr_functions[flow]->device].interrupt_handler =
+                                      UA_InterruptHandler;
+        break;
+
+    case DUMMY_TRACE:
+
+        tr_functions[flow] = &dummy_trace;
+        break;
+
+    }
+}
+
+/*******************************************************************************
+ *
+ *                          SER_InitSerialConfig
+ *
+ * Purpose: The parameter serial_info allows knowing all serial information
+ *          necessary to set up the serial configuration of an application.
+ *          From this information, the function is able to determine if the
+ *          current serial configuration read out from the flash memory is
+ *          valid. If it does not correspond to an allowed configuration, the
+ *          default configuration is selected. This function must be called at
+ *          the application's initialization, but never after.
+ *
+ * Parameters: In : serial_info: application serial information like the default
+ *                               configuration and all allowed configurations.
+ *             Out: none
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+
+void
+SER_InitSerialConfig (T_AppliSerialInfo *serial_info)
+{
+    int            uart_id;
+    int            flow;
+    T_SerialDriver serial_driver;
+    SYS_UWORD16    *allowed_config;
+    SYS_UWORD8     nb_allowed_config;
+    SYS_BOOL       valid_config_selected;
+    SYS_BOOL       uart_used;
+    SYS_BOOL       uart_used_for_trace;
+    SYS_UWORD16    current_config;
+    SYS_UWORD16    *pt_current_config = &(current_config);
+
+    /*
+	 * Basic UARTs initializations.
+	 */
+
+    for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) {
+
+        int_uart[uart_id].base_address = uart_base_address[uart_id];
+        int_uart[uart_id].device_used = 0;
+        int_uart[uart_id].deep_sleep_set_up = 0;
+    }
+						  
+#if ((CHIPSET == 2) || (CHIPSET == 3))
+    uart_spurious_interrupts = 0;
+#elif ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12))
+    uart_modem_spurious_interrupts = 0;
+    uart_irda_spurious_interrupts = 0;
+#endif
+#if (CHIPSET == 12)
+    uart_modem2_spurious_interrupts = 0;
+#endif
+    uart_sleep_timer_enabled = 0;
+
+    /*
+     * Compute the current serial configuration.
+     */
+
+    for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) {
+
+        switch (ser_cfg_info[uart_id]) { 
+
+            case G23_PANEL:
+                serial_cfg = serial_cfg +
+                    ((uart_id + 1) << (12 - (4 * SER_PROTOCOL_STACK)));
+                break;
+
+            case RIVIERA_TRACE_MUX:
+                serial_cfg = serial_cfg +
+                    ((uart_id + 1) << (12 - (4 * SER_LAYER_1)));
+                break;
+
+            case FD_AT_COMMAND:
+                serial_cfg = serial_cfg +
+                    ((uart_id + 1) << (12 - (4 * SER_FAX_DATA)));
+                break;
+
+            case BLUETOOTH_HCI:
+                serial_cfg = serial_cfg +
+                    ((uart_id + 1) << (12 - (4 * SER_BLUETOOTH_HCI)));
+                break;
+
+            case DUMMY:
+                break;
+        }
+    }
+
+    current_config = serial_cfg;
+    valid_config_selected = 0;
+    nb_allowed_config = serial_info->num_config;
+
+    /*
+     * Checks if the current serial config is one of the allowed.
+     */
+     
+    while ((nb_allowed_config > 0) && !valid_config_selected) {
+        
+        nb_allowed_config--;
+        allowed_config = (SYS_UWORD16 *)
+                          &(serial_info->allowed_config[nb_allowed_config]);
+        
+        if (*pt_current_config == *allowed_config)
+            valid_config_selected = 1;
+    }
+
+    /*
+	 * If not, the default configuration is selected.
+	 */
+
+    if (!valid_config_selected) {
+
+        pt_current_config = (SYS_UWORD16 *)&(serial_info->default_config);
+
+    }
+
+    /*
+     * The serial data flow functions set is initialized.
+     */
+
+    flow = 0;
+    while (flow < SER_MAX_NUMBER_OF_FLOWS) {
+        
+        serial_driver = (T_SerialDriver)
+                            (((*pt_current_config) >> (12 - flow * 4)) & 0x000F);
+
+        set_flow_functions (flow, serial_driver);
+        flow++;
+    }
+    
+    /*
+     * Checks if both UARTs are used.
+     * If not, performs minimum initialization including Sleep Mode.
+     * Checks also if at least one UART is used by a Trace flow.
+     * If so, create a HISR in order to reset and restart the sleep timer
+     * in case of incoming characters.
+     */
+
+    uart_used = 0;
+    uart_used_for_trace = 0;
+    for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) {
+
+        if (!(int_uart[uart_id].device_used))
+		    initialize_uart_sleep ((T_tr_UartId) uart_id);
+
+        else { /* if (int_uart[uart_id].device_used) */
+
+            uart_used = 1;  /* At least one UART is used */
+
+            if (int_uart[uart_id].flow_type == TRACE_FLOW) {
+
+                /* At least one UART used by a Trace flow */
+                uart_used_for_trace = 1;
+            }
+        }
+    }
+
+    /*
+     * If at least one uart is used, create a timer to figure out if the system
+     * can enter deep sleep mode regarding the UARTs.
+     */
+
+    if (uart_used) {
+
+        (void) NU_Create_Timer (
+                   &uart_sleep_timer,
+                   "Sleep",
+                   &analyze_uart_sleep_timer_expiration,
+                   0, /* Parameter supplied to the routine: not used. */
+                   WAKE_UP_TIME_IN_TDMA,
+                   0, /* The timer expires once. */
+                   NU_DISABLE_TIMER);
+
+        /*
+         * If at least one uart is used by a Trace flow, create a HISR to reset
+         * and restart the sleep timer.
+         */
+
+        if (uart_used_for_trace) {
+
+            /*
+             * The HISR entry function is the same function than the one called
+             * by the Rx HISR of the UARTFAX, since the only aim is to reset
+             * and restart the sleep timer in case of incoming characters on
+             * the Trace UART.
+             */
+
+            (void) NU_Create_HISR (
+                       &timer_hisr_ctrl_block,
+                       "Tim_HISR",
+                       SER_restart_uart_sleep_timer,
+                       TIMER_HISR_PRIORITY,
+                       &(timer_hisr_stack[0]),
+                       TIMER_HISR_STACK_SIZE);
+        }
+    }
+}
+
+
+
+/*******************************************************************************
+ *
+ * All functions SER_tr_xxx and SER_fd_xxx call a function of the UART trace
+ * driver or the UART fax & data driver.
+ * All functions SER_bt_xxx call a function of the UART Bluetooth HCI driver.
+ * See the function call for parameters and return values.
+ *
+ ******************************************************************************/
+ 
+void
+SER_tr_Init (int serial_data_flow,
+             T_tr_Baudrate baudrate,
+             void (callback_function (void)))
+{
+    tr_functions[serial_data_flow]->tr_Init (
+                tr_functions[serial_data_flow]->device, baudrate, callback_function);
+}
+
+SYS_UWORD32
+SER_tr_ReadNChars (int serial_data_flow,
+                   char *buffer,
+                   SYS_UWORD32 chars_to_read)
+{
+    return (tr_functions[serial_data_flow]->tr_ReadNChars (
+                tr_functions[serial_data_flow]->device, buffer, chars_to_read));
+}
+
+SYS_UWORD32
+SER_tr_ReadNBytes (int serial_data_flow,
+                   char *buffer,
+                   SYS_UWORD32 chars_to_read,
+                   SYS_BOOL *eof_detected)
+{
+    return (tr_functions[serial_data_flow]->tr_ReadNBytes (
+                tr_functions[serial_data_flow]->device, buffer, chars_to_read, eof_detected));
+}
+
+SYS_UWORD32
+SER_tr_WriteNChars (int serial_data_flow,
+                    char *buffer,
+                    SYS_UWORD32 chars_to_write)
+{
+    return (tr_functions[serial_data_flow]->tr_WriteNChars (
+                tr_functions[serial_data_flow]->device, buffer, chars_to_write));
+}
+
+SYS_UWORD32
+SER_tr_EncapsulateNChars (int serial_data_flow,
+                          char *buffer,
+                          SYS_UWORD32 chars_to_write)
+{
+    return (tr_functions[serial_data_flow]->tr_EncapsulateNChars (
+                tr_functions[serial_data_flow]->device, buffer, chars_to_write));
+}
+
+SYS_UWORD32
+SER_tr_WriteNBytes (int serial_data_flow,
+                    SYS_UWORD8 *buffer,
+                    SYS_UWORD32 chars_to_write)
+{
+    return (tr_functions[serial_data_flow]->tr_WriteNBytes (
+                tr_functions[serial_data_flow]->device, buffer, chars_to_write));
+}
+
+void
+SER_tr_WriteChar (int serial_data_flow,
+                  char character)
+{
+    tr_functions[serial_data_flow]->tr_WriteChar (
+                tr_functions[serial_data_flow]->device, character);
+}
+
+void
+SER_tr_WriteString (int serial_data_flow,
+                    char *buffer)
+{
+    tr_functions[serial_data_flow]->tr_WriteString (
+                tr_functions[serial_data_flow]->device, buffer);
+}
+
+SYS_BOOL
+SER_tr_EnterSleep (int serial_data_flow)
+{
+    return (tr_functions[serial_data_flow]->tr_EnterSleep (
+                tr_functions[serial_data_flow]->device));
+}
+
+void
+SER_tr_WakeUp (int serial_data_flow)
+{
+    tr_functions[serial_data_flow]->tr_WakeUp (
+                tr_functions[serial_data_flow]->device);
+}
+
+
+
+/*******************************************************************************
+ *
+ *                          SER_UartSleepStatus
+ *
+ * Purpose: This function checks if both UARTs are ready to enter Deep Sleep. 
+ *
+ * Parameters: In : none
+ *             Out: none 
+ *
+ * Return: 0	 : Deep Sleep is not possible.
+ *         >= 1  : Deep Sleep is possible.
+ *
+ ******************************************************************************/
+
+SYS_BOOL
+SER_UartSleepStatus (void)
+{
+    t_uart   *uart;
+    int      uart_id;
+    SYS_BOOL status;
+
+    /*
+     * Check first if the sleep timer is active or if a Dynamic Switch is
+     * being processed. A return is used to simplify the code.
+     */
+
+    if (uart_sleep_timer_enabled)
+	    return (0);
+
+    /*
+     * Check if both UARTs are ready to enter Deep Sleep.
+     */
+
+    status = 1;
+    uart_id = 0;
+    while ((uart_id < NUMBER_OF_TR_UART) &&
+           (status)) {
+
+           uart = &(int_uart[uart_id]);
+
+           /*
+            * Check if the specified UART is actually used.
+            */
+
+           if (uart->device_used) {
+
+               /*
+                * Check if the specified UART is used by a Trace or
+                * by a Fax & Data flow.
+                */
+
+               if (uart->flow_type == TRACE_FLOW)
+                   status = SER_tr_EnterSleep (uart->flow_id);
+
+               else
+                   status = 0;
+
+               if (status) {
+
+                   /*
+    	            * The specified UART is now set up for Deep Sleep.
+    	            */
+
+                   uart->deep_sleep_set_up = 1;
+
+               }
+           }
+
+           uart_id++;
+    }
+
+    /*
+     * Check if Deep Sleep is finally possible.
+     * If not revert eventual Deep Sleep settings.
+     */
+
+    if (!status) {
+
+        for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) {
+
+            uart = &(int_uart[uart_id]);
+
+            /*
+             * If the specified used UART has already been set up for
+             * Deep Sleep, revert these settings.
+             */
+
+            if ((uart->device_used) &&
+                (uart->deep_sleep_set_up)) {
+				
+                /*
+                 * Check if the specified UART is used by a Trace or
+                 * by a Fax & Data flow.
+                 * Bluetooth HCI can not yet handled Deep Sleep Mode.
+                 */
+
+                if (uart->flow_type == TRACE_FLOW)
+                    SER_tr_WakeUp (uart->flow_id);
+
+                uart->deep_sleep_set_up = 0;
+
+            }
+        }
+    }
+
+    return (status);
+}
+
+
+/*******************************************************************************
+ *
+ *                            SER_WakeUpUarts
+ *
+ * Purpose: This function wakes up used UARTs after Deep Sleep.
+ *
+ * Parameters: In : none
+ *             Out: none 
+ *
+ * Return: none
+ *
+ ******************************************************************************/
+
+void
+SER_WakeUpUarts (void)
+{
+    t_uart   *uart;
+    int      uart_id;
+
+    if (uart_sleep_timer_enabled)
+        start_uart_sleep_timer ();
+
+    for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) {
+
+        uart = &(int_uart[uart_id]);
+
+        /*
+         * Check if the specified UART is actually used, and has not yet
+		 * been waked up.
+         */
+
+        if ((uart->device_used) &&
+            (uart->deep_sleep_set_up)) {
+
+            /*
+             * Check if the specified UART is used by a Trace or
+             * by a Fax & Data flow.
+             * Bluetooth HCI can not yet handled Deep Sleep Mode.
+             */
+
+            if (uart->flow_type == TRACE_FLOW)
+                SER_tr_WakeUp (uart->flow_id);
+
+            /*
+             * The specified UART is no more set up for Deep Sleep.
+             */
+
+            uart->deep_sleep_set_up = 0;
+
+        }
+    }
+}
+
+
+/*******************************************************************************
+ *
+ *                         SER_restart_uart_sleep_timer
+ * 
+ * Purpose  : Resets and restarts the sleep timer each time some characters are
+ *            received.
+ *
+ * Arguments: In : none
+ *            Out: none
+ *
+ * Returns  : none
+ *
+ ******************************************************************************/
+
+void
+SER_restart_uart_sleep_timer (void)
+{
+    /*
+     * First disable the timer.
+     */
+
+    (void) NU_Control_Timer (&uart_sleep_timer,
+                             NU_DISABLE_TIMER);
+
+    /*
+     * Then start again this timer for a new period.
+     */
+
+    start_uart_sleep_timer ();
+}
+
+
+/*******************************************************************************
+ *
+ *                            SER_activate_timer_hisr
+ * 
+ * Purpose  : Activates the timer HISR to reset and restart the sleep timer
+ *            each time some characters are received.
+ *
+ * Arguments: In : none
+ *            Out: none
+ *
+ * Returns  : none
+ *
+ ******************************************************************************/
+
+void
+SER_activate_timer_hisr (void)
+{
+    (void) NU_Activate_HISR (&timer_hisr_ctrl_block);
+}
+
+
+#if ((CHIPSET == 2) || (CHIPSET == 3))
+
+/*******************************************************************************
+ *
+ *                                SER_uart_handler
+ * 
+ * Purpose  : UART interrupt handler.
+ *
+ * Arguments: In : none
+ *            Out: none
+ *
+ * Returns  : none
+ *
+ ******************************************************************************/
+
+void
+SER_uart_handler (void)
+{
+    SYS_UWORD8 interrupt_status;
+    t_uart     *uart;
+    int        uart_id;
+    SYS_BOOL   it_identified;
+
+    it_identified = 0;
+
+    /*
+     * Check first for a wake-up interrupt.
+     */
+
+    uart_id = 0;
+    while ((uart_id < NUMBER_OF_TR_UART) &&
+           (!it_identified)) {
+
+           uart = &(int_uart[uart_id]);
+           interrupt_status = READ_UART_REGISTER (uart, SSR);
+
+           if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */
+
+               it_identified = 1;
+               uart_sleep_timer_enabled = 1;
+			   DISABLE_WAKE_UP_INTERRUPT (uart);
+           }
+
+           uart_id++;
+    }
+
+    /*
+     * If no wake-up interrupt has been detected, check then systematically
+     * both UARTs for other interrupt causes.
+     */
+
+    if (!it_identified) {
+
+        for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) {
+
+            uart = &(int_uart[uart_id]);
+            interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED;
+
+            if (!(interrupt_status & IT_NOT_PENDING)) {
+
+                it_identified = 1;
+                (*(uart->interrupt_handler)) (uart_id, interrupt_status);
+
+            } else {
+
+                if ((uart_id == UA_UART_1) && (!it_identified))
+                uart_spurious_interrupts++;
+            }
+        }
+    }
+}
+
+#elif ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12))
+
+/*******************************************************************************
+ *
+ *                                SER_uart_modem_handler
+ * 
+ * Purpose  : UART MODEM interrupt handler.
+ *
+ * Arguments: In : none
+ *            Out: none
+ *
+ * Returns  : none
+ *
+ ******************************************************************************/
+
+void
+SER_uart_modem_handler (void)
+{
+    SYS_UWORD8 interrupt_status;
+    t_uart     *uart;
+    SYS_BOOL   it_wakeup_identified;
+
+    it_wakeup_identified = 0;
+    uart = &(int_uart[UA_UART_1]);
+
+    /*
+     * Check first for a wake-up interrupt.
+     */
+
+    interrupt_status = READ_UART_REGISTER (uart, SSR);
+
+    if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */
+
+        it_wakeup_identified = 1;
+        uart_sleep_timer_enabled = 1;
+        DISABLE_WAKE_UP_INTERRUPT (uart);
+    }
+
+    /*
+     * If no wake-up interrupt has been detected, check UART for other
+     * interrupt causes.
+     */
+
+    if (!it_wakeup_identified) {
+
+        interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED;
+
+        if (!(interrupt_status & IT_NOT_PENDING))
+            (*(uart->interrupt_handler)) (UA_UART_1, interrupt_status);
+
+        else
+            uart_modem_spurious_interrupts++;
+    }
+}
+
+
+/*******************************************************************************
+ *
+ *                                SER_uart_irda_handler
+ * 
+ * Purpose  : UART IrDA interrupt handler.
+ *
+ * Arguments: In : none
+ *            Out: none
+ *
+ * Returns  : none
+ *
+ ******************************************************************************/
+
+void
+SER_uart_irda_handler (void)
+{
+    SYS_UWORD8 interrupt_status;
+    t_uart     *uart;
+    SYS_BOOL   it_wakeup_identified;
+
+    it_wakeup_identified = 0;
+    uart = &(int_uart[UA_UART_0]);
+
+    /*
+     * Check first for a wake-up interrupt.
+     */
+
+    interrupt_status = READ_UART_REGISTER (uart, SSR);
+
+    if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */
+
+        it_wakeup_identified = 1;
+        uart_sleep_timer_enabled = 1;
+        DISABLE_WAKE_UP_INTERRUPT (uart);
+    }
+
+    /*
+     * If no wake-up interrupt has been detected, check UART for other
+     * interrupt causes.
+     */
+
+    if (!it_wakeup_identified) {
+
+        interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED;
+
+        if (!(interrupt_status & IT_NOT_PENDING))
+            (*(uart->interrupt_handler)) (UA_UART_0, interrupt_status);
+
+        else
+            uart_irda_spurious_interrupts++;
+    }
+}
+
+#endif
+
+#if (CHIPSET == 12)
+  /*******************************************************************************
+   *
+   *                                SER_uart_modem2_handler
+   * 
+   * Purpose  : UART IrDA interrupt handler.
+   *
+   * Arguments: In : none
+   *            Out: none
+   *
+   * Returns  : none
+   *
+   ******************************************************************************/
+
+  void
+  SER_uart_modem2_handler (void)
+  {
+      SYS_UWORD8 interrupt_status;
+      t_uart     *uart;
+      SYS_BOOL   it_wakeup_identified;
+
+      it_wakeup_identified = 0;
+      uart = &(int_uart[UA_UART_2]);
+
+      /*
+       * Check first for a wake-up interrupt.
+       */
+
+      interrupt_status = READ_UART_REGISTER (uart, SSR);
+
+      if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */
+
+          it_wakeup_identified = 1;
+          uart_sleep_timer_enabled = 1;
+          DISABLE_WAKE_UP_INTERRUPT (uart);
+      }
+
+      /*
+       * If no wake-up interrupt has been detected, check UART for other
+       * interrupt causes.
+       */
+
+      if (!it_wakeup_identified) {
+
+          interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED;
+
+          if (!(interrupt_status & IT_NOT_PENDING))
+              (*(uart->interrupt_handler)) (UA_UART_2, interrupt_status);
+        
+          else
+              uart_modem2_spurious_interrupts++;
+      }
+  }
+
+#endif
+
+/*
+ * Temporary functions. 
+ */
+
+void
+UT_Init (int device_id,
+         T_tr_Baudrate baudrate,
+         void (callback_function (void)))
+{
+    SER_tr_Init (SER_PROTOCOL_STACK, baudrate, callback_function);
+}
+
+SYS_UWORD32
+UT_ReadNChars (int device_id,
+               char *buffer,
+               SYS_UWORD32 chars_to_read)
+{
+    return (SER_tr_ReadNChars (SER_PROTOCOL_STACK, buffer, chars_to_read));
+}
+
+SYS_UWORD32
+UT_WriteNChars (int device_id,
+                char *buffer,
+                SYS_UWORD32 chars_to_write)
+{
+    return (SER_tr_WriteNChars (SER_PROTOCOL_STACK, buffer, chars_to_write));
+}
+
+void
+UT_WriteChar (int device_id,
+              char character)
+{
+    SER_tr_WriteChar (SER_PROTOCOL_STACK, character);
+}
+
+void
+UT_WriteString (int device_id,
+                char *buffer)
+{
+    SER_tr_WriteString (SER_PROTOCOL_STACK, buffer);
+}