view src/g23m-aci/uart/uart_rxf.c @ 222:79cb194284ca

doc/Freerunner-Howto: update for the TCS2/TCS3 hybrid development
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 16 Oct 2016 00:26:26 +0000
parents 53929b40109c
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :
|  Modul   :
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This modul is part of the entity UART and implements all
|             procedures and functions as described in the
|             SDL-documentation (RX-statemachine)
+-----------------------------------------------------------------------------
*/

#ifndef UART_RXF_C
#define UART_RXF_C
#endif /* !UART_RXF_C */

#define ENTITY_UART

#ifndef FF_MULTI_PORT
/*==== INCLUDES =============================================================*/

#ifdef WIN32
#include "nucleus.h"
#endif /* WIN32 */
#include "typedefs.h"   /* to get Condat data types */
#include "vsi.h"        /* to get a lot of macros */
#include "macdef.h"     /* to get a lot of macros */
#include "custom.h"
#include "gsm.h"        /* to get a lot of macros */
#include "cnf_uart.h"   /* to get cnf-definitions */
#include "mon_uart.h"   /* to get mon-definitions */
#include "prim.h"       /* to get the definitions of used SAP and directions */
#ifdef DTILIB
#include "dti.h"        /* to get dti lib */
#endif /* DTILIB */
#include "pei.h"        /* to get PEI interface */
#ifdef _TARGET_
#include "uart/serialswitch.h"
#include "uart/traceswitch.h"
#else /* _TARGET_ */
#include "serial_dat.h" /* to get definitions of serial driver */
#endif /* _TARGET_ */
#include "uart.h"       /* to get the global entity definitions */

#ifdef _SIMULATION_
#include <stdio.h>      /* to get sprintf */
#endif /* _SIMULATION_ */
#include <string.h>    /* JK, delete warnings: to get memcpy */

/*==== CONST ================================================================*/

/*==== LOCAL VARS ===========================================================*/

/*==== PRIVATE FUNCTIONS ====================================================*/

/*==== PUBLIC FUNCTIONS =====================================================*/



/*
+------------------------------------------------------------------------------
| Function    : rx_proc_input
+------------------------------------------------------------------------------
| Description : The function rx_proc_input() is the actual callback function
|               to read data from the receive buffer.
|
| Parameters  : uart_device - database for the affected UART device
|
+------------------------------------------------------------------------------
*/
LOCAL void rx_proc_input (T_UART_DATA* uart_device)
{
  USHORT  i, len;
  T_DLC   *dlc;               /* used Data Link Connection */
  UBYTE   *source;            /* Data source pointer */
  UBYTE   *destination;       /* Data destination pointer */
  UBYTE   temp_field;         /* multi purpose value */
  BOOL    channels_complete;  /* indicator of complete reception */
  SHORT   error_code;         /* error code returned from a function */

  TRACE_FUNCTION( "rx_proc_input" );

  /*
   * read data only if we have read permission
   */
  if(uart_device->rx.read_permission)
  {
    if(uart_device->rx.dlc_instance EQ UART_EMPTY_INSTANCE)
      dlc = &uart_device->dlc_table[UART_CONTROL_INSTANCE];
    else
      dlc = &uart_device->dlc_table[uart_device->rx.dlc_instance];
    destination = &dlc->receive_data->buffer[dlc->receive_pos];
#ifdef _SIMULATION_
{
  char buf[80];
  sprintf(buf,"uart_device->rx.dlc_instance: %d", uart_device->rx.dlc_instance);
  TRACE_EVENT(buf);
}
#endif /* _SIMULATION_ */
    if(uart_device->rx.dlc_instance EQ UART_EMPTY_INSTANCE)
    {
      /*
       * Raw data
       */
      /*
       * Is a data descriptor allocated and
       * is the channel ready to receive
       */
      if((dlc->receive_process EQ UART_RX_PROCESS_READY) &&
         (dlc->receive_data))
      {
        for (i=0; i < uart_device->rx.nsource; i++)
        {
          /*
           * are there still data in the ring buffer segment and
           * are there still space in the data descriptor
           */
          if ((uart_device->rx.size[i] > 0) &&
              (dlc->receive_size > dlc->receive_pos))
          {
            len = dlc->receive_size - dlc->receive_pos;
            if (len > uart_device->rx.size[i])
              len = uart_device->rx.size[i];

            memcpy(&dlc->receive_data->buffer[dlc->receive_pos],
                   uart_device->rx.source[i],
                   len);

            uart_device->rx.size[i] -= len;
            dlc->receive_pos        += len;
            dlc->receive_data->len   = dlc->receive_pos;
          }
        }
        dlc->receive_process = UART_RX_PROCESS_COMPLETE;
      }
    }
    else
    {
      channels_complete = FALSE;
      /*
       * for each fragment
       */
      for (i=0; i < uart_device->rx.nsource; i++)
      {
        /*
         * while there is still data in buffer and
         * not yet all channels are processed
         */
        source = uart_device->rx.source[i];
        while((uart_device->rx.size[i] > 0) && (channels_complete NEQ TRUE))
        {
          /*
           * detect HDLC flag
           */
          if(*source EQ UART_HDLC_FLAG)
          {
            switch(uart_device->rx.analyze_state)
            {
              case UART_RX_ERROR:
                /*
                 * begin of frame detected
                 */
                uart_device->rx.analyze_state = UART_RX_BEGIN;
                /* fall through */
              case UART_RX_BEGIN:
                /*
                 * initialize new packet
                 */
                uart_device->rx.stored_len    = 0;
                uart_device->rx.address_field = 0;
                uart_device->rx.fcs           = UART_INITFCS;
                uart_device->rx.escape        = FALSE;
                uart_device->rx.analyze_state = UART_RX_ADDRESS;
                break;

              default:
                /*
                 * detect HDLC flag
                 */
                if(uart_device->rx.stored_len > 0)
                {
                  /*
                   * determine whether FCS already calculated
                   */
                  if(uart_device->rx.analyze_state NEQ UART_RX_FCS)
                  {
                    /*
                     * UART_RX_INFORMATION_...
                     */
                    destination--;
#ifdef _SIMULATION_
                    uart_device->rx.fcs = *destination;
#else /* _SIMULATION_ */
                    uart_device->rx.fcs = uart_device->
                                        fcstab[uart_device->rx.fcs ^ *destination];
#endif /* _SIMULATION_ */
                    /*
                     * remove FCS from data stream
                     */
                    dlc->receive_pos--;
                    uart_data->rx.stored_len--;
                  }
                  if(uart_device->rx.fcs EQ UART_GOODFCS)
                  {
                    /*
                     * no error occured, frame complete
                     */
                    dlc->receive_data->len        = dlc->receive_pos;
                    dlc->receive_process          = UART_RX_PROCESS_COMPLETE;
                    uart_device->rx.analyze_state = UART_RX_END;
                    break;
                  }
                }
                /*
                 * remove receiced frame because of an error
                 */
                switch(uart_device->rx.analyze_state)
                {
                  case UART_RX_INFORMATION:
                  case UART_RX_FCS:
                    if(uart_data->rx.dlc_instance EQ UART_CONTROL_INSTANCE)
                      dlc->receive_pos-= 2;
                    dlc->receive_pos    -= uart_data->rx.stored_len;
                    dlc->receive_process = UART_RX_PROCESS_READY;
                    break;
                  default:
                    /*
                     * Other states are not handeled here
                     */
                    break;
                }
                uart_device->rx.analyze_state = UART_RX_END;
                break;
            }
          }
          else if((*source EQ UART_HDLC_ESCAPE) &&
                  (uart_device->rx.escape NEQ TRUE))
          {
            /*
             * detect Control Escape octet
             */
            uart_device->rx.escape = TRUE;
          }
          else
          {
            /*
             * bit 5 complement for the octet followed by Control Escape
             */
            if(uart_device->rx.escape EQ TRUE)
            {
              *source             ^= 0x20;
              uart_device->rx.escape = FALSE;
            }
            /*
             * store the packet and determine the protocol
             */
            switch(uart_device->rx.analyze_state)
            {
              case UART_RX_ERROR:
                /*
                 * wait for next HDLC flag
                 */
                break;

              case UART_RX_ADDRESS:
                if((*source & UART_EA) EQ UART_EA)
                {
                  /*
                   * FCS calculation
                   */
#ifdef _SIMULATION_
                  uart_device->rx.fcs = *source;
#else /* _SIMULATION_ */
                  uart_device->rx.fcs = uart_device->
                                      fcstab[uart_device->rx.fcs ^ *source];
#endif /* _SIMULATION_ */
                  /*
                   * store Address field
                   */
                  uart_device->rx.address_field = *source;
                  uart_device->rx.analyze_state = UART_RX_CONTROL;
                }
                else
                {
                  /*
                   * invalid frame detected
                   */
                  uart_device->rx.analyze_state = UART_RX_ERROR;
                }
                break;

              case UART_RX_CONTROL:
                switch(*source)
                {
                  case UART_UIH_DATA_FRAME:
                    /*
                     * Data frame detected
                     */
                    temp_field = uart_device->rx.address_field >> UART_DLCI_POS;
                    /*
                     * if it is an existing channel, but not control channel
                     */
                    if((temp_field NEQ UART_DLCI_CONTROL) &&
                       (uart_device->dlc_instance[temp_field] NEQ
                          UART_EMPTY_INSTANCE))
                    {
                      uart_device->rx.dlc_instance =
                        uart_device->dlc_instance[temp_field];
                      dlc = &uart_device->dlc_table[uart_device->rx.dlc_instance];
#ifdef _SIMULATION_
                      TRACE_EVENT_P2("Addressfield found DLCI: 0x%02X \
                                     (dlc_instance 0x%02X)",
                                     temp_field, uart_device->rx.dlc_instance);
#endif /* _SIMULATION_ */
                      if(dlc->receive_process EQ UART_RX_PROCESS_READY)
                      {
                        /*
                         * reception Data channel found
                         * FCS calculation
                         */
#ifdef _SIMULATION_
                        uart_device->rx.fcs = *source;
#else /* _SIMULATION_ */
                        uart_device->rx.fcs = uart_device->
                                            fcstab[uart_device->
                                            rx.fcs ^ *source];
#endif /* _SIMULATION_ */
                        destination = &dlc->receive_data->
                                       buffer[dlc->receive_pos];
                        uart_device->rx.analyze_state = UART_RX_INFORMATION;
                        break;
                      }
                      else if(dlc->receive_process EQ UART_RX_PROCESS_COMPLETE)
                      {
                        channels_complete = TRUE;
                        break;
                      }
                    }
                    /* fall through */
                  case UART_SABM_FRAME:
                  case UART_UA_FRAME:
                  case UART_DM_DATA_FRAME:
                  case UART_DM_CONTROL_FRAME:
                  case UART_DISC_FRAME:
                  case UART_UIH_CONTROL_FRAME:
                    /*
                     * Control frame detected
                     */
                    dlc = &uart_device->dlc_table[UART_CONTROL_INSTANCE];
                    uart_device->rx.dlc_instance = UART_CONTROL_INSTANCE;
                    if(dlc->receive_process EQ UART_RX_PROCESS_READY)
                    {
                      /*
                       * reception Control channel found
                       * FCS calculation
                       */
#ifdef _SIMULATION_
                      uart_device->rx.fcs = *source;
#else /* _SIMULATION_ */
                      uart_device->rx.fcs = uart_device->
                                          fcstab[uart_device->
                                          rx.fcs ^ *source];
#endif /* _SIMULATION_ */
                      destination = &dlc->receive_data->
                                     buffer[dlc->receive_pos];
                      uart_device->rx.analyze_state = UART_RX_INFORMATION;
                      /*
                       * store Address and Control field
                       */
                      *destination = uart_device->rx.address_field;
                      destination++;
                      dlc->receive_pos++;
                      *destination = *source;
                      destination++;
                      dlc->receive_pos++;
                    }
                    else if(dlc->receive_process EQ UART_RX_PROCESS_COMPLETE)
                    {
                      channels_complete = TRUE;
                    }
                    else
                      /*
                       * discard frame, because it is unexpected
                       */
                      uart_device->rx.analyze_state = UART_RX_ERROR;
                    break;
                  default:
                    /*
                     * invalid frame detected
                     */
                    uart_device->rx.analyze_state = UART_RX_ERROR;
                    break;
                }
                break;

              case UART_RX_INFORMATION:
                if(uart_device->rx.stored_len < uart_device->n1)
                {
                  *destination = *source;
                  /*
                   * increase destination pointer
                   */
                  destination++;
                  uart_device->rx.stored_len++;
                  dlc->receive_pos++;
                }
                else
                {
                  /*
                   * FCS calculation
                   */
#ifdef _SIMULATION_
                  uart_device->rx.fcs = *source;
#else /* _SIMULATION_ */
                  uart_device->rx.fcs = uart_device->
                                      fcstab[uart_device->rx.fcs ^ *source];
#endif /* _SIMULATION_ */
                  uart_device->rx.analyze_state = UART_RX_FCS;
                }
                break;

              case UART_RX_FCS:
                /*
                 * remove receiced packet because its to long
                 */
                if(uart_data->rx.dlc_instance EQ UART_CONTROL_INSTANCE)
                  dlc->receive_pos-= 2;
                dlc->receive_pos             -= uart_data->rx.stored_len;
                dlc->receive_process          = UART_RX_PROCESS_READY;
                uart_device->rx.analyze_state = UART_RX_ERROR;
                break;

              default:
                /*
                 * wrong analyze state
                 */
                uart_device->rx.analyze_state = UART_RX_ERROR;
                break;
            }
          }
          if(uart_device->rx.analyze_state EQ UART_RX_END)
            uart_device->rx.analyze_state = UART_RX_BEGIN;
          /*
           * don't move source pointer
           * if each possible channel was processed
           * In this case analyze_state should be UART_RX_CONTROL.
           * The Control field must be analyzed again in next call of
           * this function.
           */
          else if(channels_complete NEQ TRUE)
          {
            /*
             * increase source pointer
             */
            source++;
            uart_device->rx.size[i]--;
          }
        }
      }
    }
  }

  PSIGNAL(hCommUART, UART_DRIVER_RECEIVED_IND, uart_device);

  *uart_device->rx.reInstall = rm_noInstall;

  /*
   * update pointer in UART driver
   */
  if((error_code = UF_InpAvail (uart_device->device)) < 0 )
  {
    TRACE_ERROR_P2("UF Driver: DataPointerUpdate failed, [%d], uart_rxf.c(%d)",
                                                         error_code, __LINE__);
  }
} /* rx_proc_input() */



/*
+------------------------------------------------------------------------------
| Function    : rx_init
+------------------------------------------------------------------------------
| Description : The function rx_init() initializes the RX service
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void rx_init ()
{
#ifndef _SIMULATION_
#ifdef WIN32
#ifndef _TARGET_
  char    buf[80];
#endif /* !_TARGET_ */
  STATUS  sts;
#endif /* WIN32 */
#endif /* !_SIMULATION_ */

  TRACE_FUNCTION( "rx_init" );

#ifndef _SIMULATION_
#ifdef WIN32
  sts = NU_Create_HISR (&uart_data->rx.rx_HISR,
                        "RX_HISR",
                        rx_proc_input,
                        2,
                        uart_data->HISR_stack,
                        HISR_STACK_SIZE);
#ifndef _TARGET_
  sprintf (buf, "NU_Create_HISR(RX) = %d", sts);
  TRACE_EVENT (buf);
#endif /* _TARGET_ */
#endif /* WIN32 */
#endif /* !_SIMULATION_ */

  uart_data->rx.read_permission = FALSE;
  uart_data->rx.prev_lines      = 0;
  uart_data->rx.dlc_instance    = UART_EMPTY_INSTANCE;
  uart_data->rx.escape          = FALSE;
  uart_data->rx.analyze_state   = UART_RX_ERROR;
  uart_data->rx.receive_state   = UART_RX_NOT_RECEIVING;
  uart_data->rx.fcs             = UART_INITFCS;
  uart_data->rx.address_field   = 0;
  uart_data->rx.stored_len      = 0;

  INIT_STATE( UART_SERVICE_RX , RX_DEAD );
} /* rx_init() */



/*
+------------------------------------------------------------------------------
| Function    : rx_readOutFunc_0
+------------------------------------------------------------------------------
| Description : The function rx_readOutFunc_0() is the official callback
|               function to read data from the receive buffer of UART device 0.
|               It just copies the parameters and calls then the actual
|               function.
|
| Parameters  : cldFromIrq - called from interrupt
|               reInstall  - reinstallation mode
|               nsource    - number of source pointers
|               source     - array of source pointers
|               size       - array of sizes for every source pointer
|               state      - state of V.24 lines
|
+------------------------------------------------------------------------------
*/
GLOBAL void rx_readOutFunc_0 (BOOL           cldFromIrq,
                              T_reInstMode  *reInstall,
                              UBYTE          nsource,
                              UBYTE         *source[],
                              USHORT        *size,
                              ULONG          state)
{
#ifndef _SIMULATION_
#ifndef _TARGET_
  char buf[40];
#endif /* !_TARGET_ */
#endif /* !_SIMULATION_ */
  T_UART_DATA* uart_device;

  TRACE_FUNCTION( "rx_readOutFunc_0" );

  /*
   * select UART device 0
   */
  uart_device = &(uart_data_base[0]);

  /*
   * store parameters
   */
  uart_device->rx.cldFromIrq = cldFromIrq;
  uart_device->rx.nsource    = nsource;
  uart_device->rx.source[0]  = source[0];
  uart_device->rx.source[1]  = source[1];
  uart_device->rx.size       = size;
  uart_device->rx.lines      = state;
  uart_device->rx.reInstall  = reInstall;

#ifndef _SIMULATION_
#ifdef WIN32
  if (cldFromIrq)
  {
    STATUS sts;
    /*
     * interrupt context of the UART driver -> activate the HISR
     */
    sts = NU_Activate_HISR (&uart_device->rx.rx_HISR);
#ifndef _TARGET_
    sprintf (buf, "NU_Activate_HISR(RX) = %d", sts);
    TRACE_EVENT (buf);
#endif /* !_TARGET_ */
  }
  else
#endif /* WIN32 */
#endif /* !_SIMULATION_ */
  {
#ifdef _SIMULATION_
    UBYTE*  trace_source[2];
    USHORT  trace_size[2];
    USHORT  i;
    USHORT  pos;
    char    buf[90];

    trace_source[0] = source[0];
    trace_source[1] = source[1];

    trace_size[0] = size[0];
    trace_size[1] = size[1];

    /*
     * trace input
     */
    if((nsource) &&
       (uart_device->rx.read_permission))
    {

      TRACE_EVENT("==== INRAW");
      i   = 0;
      pos = 0;
      while(pos < trace_size[0])
      {
        i+= sprintf(&buf[i], "0x%02x, ", trace_source[0][pos]);
        pos++;
        if(i > 80)
        {
          TRACE_EVENT( buf );
          i = 0;
        }
        else if(pos >= trace_size[0])
        {
          TRACE_EVENT( buf );
        }
      }
      if(nsource > 1)
      {
        i   = 0;
        pos = 0;
        while(pos < trace_size[1])
        {
          i+= sprintf(&buf[i], "0x%02x, ", trace_source[1][pos]);
          pos++;
          if(i > 80)
          {
            TRACE_EVENT( buf );
            i = 0;
          }
          else if(pos >= trace_size[1])
          {
            TRACE_EVENT( buf );
          }
        }
      }
    }
#endif /* _SIMULATION_ */

    /*
     * normal callback from UF_ReadData
     */
    rx_proc_input(uart_device);
  }

} /* rx_readOutFunc_0() */



#ifdef FF_TWO_UART_PORTS
/*
+------------------------------------------------------------------------------
| Function    : rx_readOutFunc_1
+------------------------------------------------------------------------------
| Description : The function rx_readOutFunc_1() is the official callback
|               function to read data from the receive buffer of UART device 1.
|               It just copies the parameters and calls then the actual
|               function.
|
| Parameters  : cldFromIrq - called from interrupt
|               reInstall  - reinstallation mode
|               nsource    - number of source pointers
|               source     - array of source pointers
|               size       - array of sizes for every source pointer
|               state      - state of V.24 lines
|
+------------------------------------------------------------------------------
*/
GLOBAL void rx_readOutFunc_1 (BOOL           cldFromIrq,
                              T_reInstMode  *reInstall,
                              UBYTE          nsource,
                              UBYTE         *source[],
                              USHORT        *size,
                              ULONG          state)
{
#ifndef _SIMULATION_
#ifndef _TARGET_
  char buf[40];
#endif /* !_TARGET_ */
#endif /* !_SIMULATION_ */
  T_UART_DATA* uart_device;

  TRACE_FUNCTION( "rx_readOutFunc_1" );

  /*
   * select UART device 1
   */
  uart_device = &(uart_data_base[1]);

  /*
   * store parameters
   */
  uart_device->rx.cldFromIrq = cldFromIrq;
  uart_device->rx.nsource    = nsource;
  uart_device->rx.source[0]  = source[0];
  uart_device->rx.source[1]  = source[1];
  uart_device->rx.size       = size;
  uart_device->rx.lines      = state;
  uart_device->rx.reInstall  = reInstall;

#ifndef _SIMULATION_
#ifdef WIN32
  if (cldFromIrq)
  {
    STATUS sts;
    /*
     * interrupt context of the UART driver -> activate the HISR
     */
    sts = NU_Activate_HISR (&uart_device->rx.rx_HISR);
#ifndef _TARGET_
    sprintf (buf, "NU_Activate_HISR(RX) = %d", sts);
    TRACE_EVENT (buf);
#endif /* !_TARGET_ */
  }
  else
#endif /* WIN32 */
#endif /* !_SIMULATION_ */
  {
#ifdef _SIMULATION_
    UBYTE*  trace_source[2];
    USHORT  trace_size[2];
    USHORT  i;
    USHORT  pos;
    char    buf[90];

    trace_source[0] = source[0];
    trace_source[1] = source[1];

    trace_size[0] = size[0];
    trace_size[1] = size[1];

    /*
     * trace input
     */
    if((nsource) &&
       (uart_device->rx.read_permission))
    {

      TRACE_EVENT("==== INRAW");
      i   = 0;
      pos = 0;
      while(pos < trace_size[0])
      {
        i+= sprintf(&buf[i], "0x%02x, ", trace_source[0][pos]);
        pos++;
        if(i > 80)
        {
          TRACE_EVENT( buf );
          i = 0;
        }
        else if(pos >= trace_size[0])
        {
          TRACE_EVENT( buf );
        }
      }
      if(nsource > 1)
      {
        i   = 0;
        pos = 0;
        while(pos < trace_size[1])
        {
          i+= sprintf(&buf[i], "0x%02x, ", trace_source[1][pos]);
          pos++;
          if(i > 80)
          {
            TRACE_EVENT( buf );
            i = 0;
          }
          else if(pos >= trace_size[1])
          {
            TRACE_EVENT( buf );
          }
        }
      }
    }
#endif /* _SIMULATION_ */

    /*
     * normal callback from UF_ReadData
     */
    rx_proc_input(uart_device);
  }

} /* rx_readOutFunc_1() */
#endif /* FF_TWO_UART_PORTS */
#endif /* !FF_MULTI_PORT */