⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shmuartsio.c

📁 ge公司的dv4av4信号处理板的bsp源代码
💻 C
字号:
/* shmuartSio.c - shared memory serial I/O driver */

/*

  $RCSfile: shmuartSio.c $

  Copyright 2002 by Dy-4 Systems, Inc.  All Rights Reserved.

  $Revision: 1.8 $

  $Name: AV4-ISP-R1.2-1 AV4-ISP-R1.2-0 HMTST2 HMTST1 DVT_AV4_4.101 AV4-VSP-R1.0-2 AV4-VSP-R1.0 CT-ISP-1.1 AV4 ISP 1.1 CT_R0.1_AV4/CAV4 champtools2.22 CAV4_CP1 CHAMPtools FW 3.0 champtools2.21_1215 champtools2.21 champ221_build1 champtools2.2 CHAMPtools_2.1.1_AV3 CHAMPtools_2.1_106 CHAMPtools_2.0_AV3 $  $State: Developmental $  $Locker: $

  $Source: L:/SWRND/champAV2/src/vx/src/drv/sio/rcs/shmuartSio.c $

  Target: CHAMP-AV II

  Description: Serial I/O for the ppc74xx is performed using
	shared memory.

  Usage:

  $Log: shmuartSio.c $
  Revision 1.8  2003/08/05 16:33:13Z  esaunder
  Modified to utilize the AV3 timer resource management functions
  (bslTimerAlloc); the timer is allocated under the name "shmuart".
   
  Revision 1.7  2003/05/27 19:11:57  dsessler
  corrected compile error for sioCallbackInstall
  Revision 1.6  2003/05/21 21:01:38  dsessler
  T2.2 fix for paths of included files under the bsp
  Revision 1.5  2002/05/28 14:41:15  coopertr
  Revision 1.4  2002/05/21 11:49:17  coopertr
  Revision 1.3  2002/03/25 12:57:29  coopertr
  Revision 1.2  2002/03/21 12:28:31  coopertr

*/


/*
USAGE

The driver is typically called only by the BSP. The directly callable
routines in this module are sioDevInit(), sioDevInit2(), sioIntRcv(), 
and sioIntTx().

The BSP calls sioDevInit() to initialize or reset the device.
It connects the driver's interrupt handlers using intConnect().
After connecting the interrupt handlers, the BSP calls sioDevInit2()
to inform the driver that interrupt mode operation is now possible.

*/

#include "vxWorks.h"
#include "sioLib.h"
#include "intLib.h"
#include "errno.h"
#include "bsl.h"
#include "bslBoardInfo.h"
#include "bslSio.h"
#include "h/drv/sio/shmuartSio.h"


/* for backward compatibility */
#ifndef	SIO_HUP
#   define SIO_OPEN	0x100A	/* open channel, raise DTR, RTS */
#   define SIO_HUP	0x100B	/* hang-up, lower DTR, RTS */
#endif

#define SHMUART_ACTIVE_FREQ   19200
#define SHMUART_IDLE_FREQ     50

static const char  sioTimer[] = "shmuart";


/* forward static declarations */

LOCAL int    shmuartSioPollInput   (SIO_CHAN *pSioChan, char *thisChar);
LOCAL int    shmuartSioPollOutput  (SIO_CHAN *pSioChan, char outChar);
LOCAL int    shmuartSioTxStartup   (SIO_CHAN *pSioChan);
LOCAL int    shmuartSioIoctl       (SIO_CHAN *pSioChan, int request, void *arg);

LOCAL int    shmuartSioGenCallbackInstall (SIO_CHAN *pSioChan, int callbackType,
                                    STATUS (*callback)(void *, ...), void *callbackArg);

LOCAL STATUS shmuartDummyCallback     (void);

/* local variables */

LOCAL SIO_DRV_FUNCS shmuartSioDrvFuncs =      	/* for shmuart devices */
    {
    shmuartSioIoctl,
    shmuartSioTxStartup,
    (void *)shmuartSioGenCallbackInstall,
    shmuartSioPollInput,
    shmuartSioPollOutput
    };


LOCAL BOOL shmuartSioIntrMode   = FALSE;	/* interrupt mode allowed flag */
LOCAL int  shmuartTimerId = -1;


/******************************************************************************
*
* shmuartSioDevInit - initialize a SHMUART_PORT
*
* This routine initializes the driver function pointers and clears the
* shmuart buffers. 
*
* RETURNS: N/A
* NOMANUAL
*/

void shmuartSioDevInit
    (
    SHMUART_PORT * pChan
    )
    {

    int procId;
    int shmuartSize;
    boardInfoStruct *pBi;

    /* install dummy driver callbacks */

    pChan->getTxChar     = shmuartDummyCallback;
    pChan->putRcvChar 	 = shmuartDummyCallback;


    /* get shmuart base addresses */
    
    procId = bslProcGetId ();
    pBi    = bslBoardGetBoardInfo ();
    
    pChan->txShmuart  = bslShmuartGetAddr (procId, SHMUART_TX);
    pChan->rcvShmuart = bslShmuartGetAddr (procId, SHMUART_RX);
    shmuartSize = pBi->shmuartSize;


    /* If shmuarts are present, reset them.  */
    
    if (pChan->txShmuart != 0)
        bslShmuartInit (pChan->txShmuart, shmuartSize);
        
    if (pChan->rcvShmuart != 0)    
        bslShmuartInit (pChan->rcvShmuart, shmuartSize);


    /* Install device entry points */
    
    pChan->pDrvFuncs = &shmuartSioDrvFuncs;


    /* set to polled mode;  OS will later change to int mode */

    pChan->txEnabled = 0;
    
    sioIoctl ((SIO_CHAN *) pChan, SIO_MODE_SET, (void *)SIO_MODE_POLL);
    }



/******************************************************************************
*
* shmuartSioDevInit2 - initialize the serial driver, part 2
*
* This routine is called by the BSP after interrupts have been connected.
* The driver can now operate in interrupt mode.  Before this routine is
* called only polled mode operations are allowed.
*
* RETURNS: N/A
* NOMANUAL
*/

void shmuartSioDevInit2
    (
    SHMUART_PORT * pChan	/* device to initialize */
    )
    {
      
    shmuartSioIntrMode = TRUE;

    (void) bslTimerAlloc( sioTimer, EXCL, &shmuartTimerId );
    
    /*  Connect and enable timer interrupt  */
    
    intConnect (INUM_TO_IVEC(bslTimerToId (shmuartTimerId)),
                shmuartSioIntTx,
                (long) pChan);

    pChan->txEnabled = 0;                    
    bslTimerStop      (shmuartTimerId);
    bslTimerSetFreq   (shmuartTimerId, SHMUART_IDLE_FREQ);
    bslTimerIntEnable (shmuartTimerId);
 
    }




/******************************************************************************
*
* shmuartSioIntTx - handle a channels interrupt (timer expiration)
*
* If there is a character to transmit:
* Send the next character to the serial output port.  The next character is
* obtained by calling a callback function, which will return a status
* indicating whether another character was ready to send or not.
*
* If there is a character to receive:
* This function passes the received character on to vxWorks by calling
* the appropriate callback function.  For devices which can store multiple
* characters in an rx fifo, it is most efficient if this function empties
* the fifo.
* Therefore, this function has to determine if the serial driver is 
* in interrupt mode or not.  If it is in interrupt mode, then we can 
* call the proper callback function when a character is received.  If 
* in polled mode we just drop through the function.
*
* If the driver is still in interrupt mode after checking the buffers
* then a new timer is created.
*
* RETURNS: N/A
* NOMANUAL
*/ 

void shmuartSioIntTx
    (
    SHMUART_PORT *pChan	/* channel generating the interrupt */
    )
    {
    char rxChar, txChar;       
    int status = 0;
    int active = FALSE;

    if (pChan->txShmuart == 0)
        return;

    
    /* more room and more data to put... */

    if (pChan->txEnabled)
    {
        if((bslShmuartQuery (pChan->txShmuart)) != -1)
        {
            /*
             * Get char from vxWorks and put in shmuart transmit buffer
             */
            if ((*pChan->getTxChar) (pChan->getTxArg, &txChar) != ERROR)
            {
                active = TRUE;
                status = bslShmuartPut (pChan->txShmuart, txChar);
            }

            else
                pChan->txEnabled = 0;
        }
    }


    /* If interrupt mode and rx buffer not empty, get an input char */
   
    if(((pChan->mode) == SIO_MODE_INT) && (bslShmuartQuery (pChan->rcvShmuart)))
        {
        if ((bslShmuartGet (pChan->rcvShmuart, &rxChar)) == 0)
            {
            active = TRUE;
            (*pChan->putRcvChar) (pChan->putRcvArg, rxChar);    
            }  
        }

    if(active)
	bslTimerSetFreq   (shmuartTimerId, SHMUART_ACTIVE_FREQ);
    else
	bslTimerSetFreq   (shmuartTimerId, SHMUART_IDLE_FREQ);

    }



/******************************************************************************
*
* shmuartSioTxStartup - start the interrupt driven transmitter
*
* Not needed in this shared memory serial driver.
* NOMANUAL
*/

LOCAL int shmuartSioTxStartup
    (
    SIO_CHAN * pSioChan                 /* channel to start */
    )
    {
    char txChar;
    SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;
    
    if (pChan->txShmuart == 0)
        while ((*pChan->getTxChar) (pChan->getTxArg, &txChar) != ERROR);
        
    else
    {
        pChan->txEnabled = 1;
        bslTimerSetFreq (shmuartTimerId, SHMUART_ACTIVE_FREQ);    
    }
        
    return (OK);
    }



/***************************************************************************
*
* shmuartSioGenCallbackInstall - install ISR callbacks to get/put chars for a 
*                         generic SIO device
*
* This driver allows interrupt callbacks for transmitting characters
* and receiving characters. In general, drivers may support other
* types of callbacks too.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
* NOMANUAL
*/ 

LOCAL int shmuartSioGenCallbackInstall
    (
    SIO_CHAN *	pSioChan,               /* channel */
    int        callbackType,           /* type of callback */
    STATUS     (*callback)(void *, ...),          /* callback */
    void     * callbackArg             /* parameter to callback */
    )
    {
    SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;

    switch (callbackType)
        {
        case SIO_CALLBACK_GET_TX_CHAR:
	        pChan->getTxChar	= (void *)callback;
	        pChan->getTxArg	= callbackArg;
	        return (OK);

        case SIO_CALLBACK_PUT_RCV_CHAR:
           pChan->putRcvChar	= (void *)callback;
	        pChan->putRcvArg	= callbackArg;
	        return (OK);

        default:
	        return (ENOSYS);
        }
    }



/*******************************************************************************
*
* shmuartSioPollOutput - output a character in polled mode
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer if full. ENOSYS if the device is
* interrupt-only.
* NOMANUAL
*/

LOCAL int shmuartSioPollOutput
    (
    SIO_CHAN *	pSioChan,
    char	outChar
    )

    {
    int status;
    SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;


    /* If no tx shmuart, return OK, discarding character. */
     
    if (pChan->txShmuart == 0)
        status = OK;
        
        
    /* If transmit shmuart buffer not full then add char  */
     
    else if ((bslShmuartQuery (pChan->txShmuart)) != -1)
        status = bslShmuartPut (pChan->txShmuart,outChar);


    /*  else no room;  caller must retry later  */
    
    else
        status = EAGAIN;

        
    return (status);
    }



/******************************************************************************
*
* shmuartSioPollInput - poll the device for input
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer if empty, ENOSYS if the device is
* interrupt-only.
* NOMANUAL
*/

LOCAL int shmuartSioPollInput
    (
    SIO_CHAN *	pSioChan,
    char *	thisChar
    )

    {
    int status;
    SHMUART_PORT * pChan = (SHMUART_PORT *)pSioChan;


    if (pChan->rcvShmuart == 0)
        status = EAGAIN;

        
    else if ((bslShmuartQuery (pChan->rcvShmuart)) != 0)
        status = bslShmuartGet (pChan->rcvShmuart, thisChar);

        
    else
        status = EAGAIN;

        
    return (status);
    }




/******************************************************************************
*
* sioModeSet - toggle between interrupt and polled mode
*
* If switching from polled mode to interrupt mode and timer
* has expired, create a new one.
*
* RETURNS: OK on success, EIO on unsupported mode.
* NOMANUAL
*/

LOCAL int shmuartSioModeSet
    (
    SHMUART_PORT * pChan,        /* channel */
    uint_t    newMode          	/* new mode */
    )
    {
    if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
        return (EIO);


    /* Don't enter interrupt mode unless it is allowed. */

    if ((newMode == SIO_MODE_INT) && (!shmuartSioIntrMode))
        return (EIO);
            
    pChan->mode = newMode;


    /* If we have just switched to interrupt mode, start the timer */
    
    if (pChan->mode == SIO_MODE_INT)
    {
        pChan->txEnabled = 1;
        bslTimerSetFreq (shmuartTimerId, SHMUART_ACTIVE_FREQ);
        bslTimerStart   (shmuartTimerId);
    }
    
    else
        bslTimerStop (shmuartTimerId);

    return (OK);
    }





/*******************************************************************************
*
* shmuartSioIoctl - special device control
*
* This routine handles the IOCTL messages from the user. It supports commands 
* to get/set baud rate, mode(INT,POLL), hardware options(parity, number of 
* data bits) and modem control(RTS/CTS and DTR/DSR handshakes).
*
* RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed
* request.
* NOMANUAL
*/

LOCAL int shmuartSioIoctl
    (
    SIO_CHAN *	pSioChan,		/* device to control */
    int        request,		/* request code */
    void     * someArg			/* some argument */
    )
    {
    SHMUART_PORT *pChan = (SHMUART_PORT *) pSioChan;
    int     arg = (int)someArg;

    switch (request)
        {
        case SIO_BAUD_SET:                      /* fixed baud rate */
            return (ENOSYS);                   


        case SIO_BAUD_GET:                      /* fixed baud rate */
	         *(int *)arg = SIO_BAUD_RATE;                 
	         return (OK);


        case SIO_MODE_SET:                      /* int or polled mode  */
	         return (shmuartSioModeSet (pChan, arg));   


        case SIO_MODE_GET:                      /* int or polled mode  */
	         *(int *)arg = pChan->mode;
	         return (OK);


        case SIO_AVAIL_MODES_GET:               /* get mode options */
	         *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
	         return (OK);


        case SIO_HUP:
            return (OK);


        case SIO_OPEN:
	         return (OK); 


        default:
	         return (ENOSYS);
        }
    }






/*******************************************************************************
*
* shmuartDummyCallback - dummy callback routine
*
* RETURNS: ERROR
* NOMANUAL
*/

LOCAL STATUS shmuartDummyCallback (void)
    {
    return (ERROR);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -