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

📄 dsk5402_mcbsp_ad50.c

📁 TMS320DM642使用的mini驱动程序的例子
💻 C
字号:
/*
 *  Copyright 2003 by Texas Instruments Incorporated.
 *  All rights reserved. Property of Texas Instruments Incorporated.
 *  Restricted rights to use, duplicate or disclose this code are
 *  granted through contract.
 *  
 */
/* "@(#) DDK 1.10.00.23 07-02-03 (ddk-b12)" */
/*
 *  ======== dsk5402_mcbsp_ad50.c ========
 *
 *  MCBSP sample-by-sample device driver for TI.
 *  5402 DSK. Uses the C54x Chip Support Library. 
 */

#include <std.h>

#include <atm.h>
#include <hwi.h>
#include <que.h>

#include <csl.h>
#include <csl_mcbsp.h>
#include <csl_irq.h>

#include <iom.h>

#include <dsk5402_mcbsp_ad50.h>
#include <ad50.h>

typedef struct ChanObj {
    Bool        inuse;          /* TRUE => channel has been opened */
    Int         mode;           /* IOM_INPUT or IOM_OUTPUT */
    IOM_Packet  *dataPacket;    /* current active I/O packet */
    QUE_Obj     pendList;       /* list of packets for I/O */
    Uns         *bufptr;        /* pointer *within* current buffer */
    Uns         bufcnt;         /* remaining samples to be handled */
    IOM_TiomCallback cbFxn;     /* used to notify client when I/O complete */
    Ptr         cbArg;
} ChanObj, *ChanHandle;

#define INPUT  0  /* Used as index since IOM mode is a bit mask, not index */
#define OUTPUT 1

#define NUMCHANS        2       /* INPUT and OUTPUT */

static ChanObj chans[NUMCHANS] = {
    { FALSE, INPUT, NULL, { NULL, NULL }, NULL, 0, NULL, NULL },
    { FALSE, OUTPUT, NULL, { NULL, NULL }, NULL, 0, NULL, NULL }
};

static MCBSP_Handle hMcbsp;

/*
 * Forward declaration of IOM interface functions.
 */
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
        Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
static Int mdDeleteChan(Ptr chanp);
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);

/*
 * Public IOM interface table.
 */
IOM_Fxns DSK5402_MCBSP_AD50_FXNS = {
    mdBindDev,
    IOM_UNBINDDEVNOTIMPL,
    mdControlChan,
    mdCreateChan,
    mdDeleteChan,
    mdSubmitChan
};

/*
 *  Public driver setup data object. Used if the user passes NULL as
 *  setup() argument, or by the user to modify the default parameters.
 */
DSK5402_MCBSP_AD50_DevParams DSK5402_MCBSP_AD50_DEVPARAMS = {
    AD50_DEFAULTPARAMS,              /* default codec parameters */
};

/*
 * local ISR functions.
 * rxIsr() and txIsr() are plugged using HWI_dispatchPlug() in mdBindDev().
 */
static Void rxIsr(void);
static Void txIsr(void);
static Void updateChan(ChanHandle chan);
static Void abortio(ChanHandle chan);

/*
 *  ======== mdBindDev ========
 *  This function is called by DSP/BIOS during device initialization.
 *  It is called after DSK5402_MCBSP_AD50_init().
 *  
 */
#pragma CODE_SECTION(mdBindDev, ".text:init")
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
{
    DSK5402_MCBSP_AD50_DevParams *params = 
        (DSK5402_MCBSP_AD50_DevParams *)devParams;
    static Bool curinit = FALSE;

    /* CSL handle to the McBSP. The McBSP is shared between the two channels */
    static MCBSP_Config mcbspCfg0 = {
        0x0021,        /*  Serial Port Control Register 1   */
        0x0201,        /*  Serial Port Control Register 2   */
        0x0040,        /*  Receive Control Register 1   */
        0x0000,        /*  Receive Control Register 2   */
        0x0040,        /*  Transmit Control Register 1   */
        0x0000,        /*  Transmit Control Register 2   */
        0x0000,        /*  Sample Rate Generator Register 1   */
        0x0000,        /*  Sample Rate Generator Register 2   */
        0x0000,        /*  Multichannel Control Register 1   */
        0x0000,        /*  Multichannel Control Register 2   */
        0x000c,        /*  Pin Control Register   */
        0x0000,        /*  Receive Channel Enable Register Partition A   */
        0x0000,        /*  Receive Channel Enable Register Partition B   */
        0x0000,        /*  Transmit Channel Enable Register Partition A   */
        0x0000         /*  Transmit Channel Enable Register Partition B   */
    };

    static volatile ioport unsigned port04;     /* for CPLD CTRL 2 */

    if (curinit) {
        return (IOM_EBADIO);
    }
    curinit = TRUE; 

    /* use default parameters if none are given */
    if (params == NULL) {
        params = &DSK5402_MCBSP_AD50_DEVPARAMS;
    }

    /* open the McBSP */
    hMcbsp = MCBSP_open(MCBSP_PORT1, MCBSP_OPEN_RESET);
    MCBSP_config(hMcbsp, &mcbspCfg0);

    /*
     * DSK5402 board setup ...
     * Select McBSP1 mapped to Audio Codec (CPLD Register)
     * and FC bit = 0 (secondary control off)
     */
    port04 &= 0xf5;

    /* start the McBSP */
    MCBSP_start(hMcbsp, MCBSP_XMIT_START | MCBSP_RCV_START, 0x0);

    /* set codec parameters (this will also initialize the codec) */
    AD50_setParams(hMcbsp, &(params->ad50) );

    /* bind Rx/Tx interrupts and use DSP/BIOS HWI dispatcher */
    HWI_dispatchPlug(IRQ_EVT_RINT1, (Fxn)rxIsr, NULL);
    HWI_dispatchPlug(IRQ_EVT_XINT1, (Fxn)txIsr, NULL);


    *devp = chans;

    return (IOM_COMPLETED);
}

/*
 *  ======== mdControlChan ========
 */
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
{
        /*
         * If a channel timeouts(in IOM class driver) a calldown is made to mdControlChan w/
         *   cmd = IOM_CHAN_TIMED out. Timeout processing is optionally implemented here.
         * If not performed return status of IOM_ENOTIMPL.
         */
        if (cmd == IOM_CHAN_TIMEDOUT) {
        /*
         *  Channel timed out. Perform needed channel cleanup.
         */ 
                abortio(chanp);
    }
    else {
        return (IOM_ENOTIMPL); /* return IOM_ENOTIMPL for codes not handled */    
    }
    
    return (IOM_COMPLETED);

}




/*
 *  ======== mdCreateChan ========
 */
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
                Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
{
    ChanHandle  chans = (ChanHandle)devp;
    ChanHandle  chan;
    
    if (mode == IOM_INPUT) {
        chan = &chans[INPUT];     /* input only channel */
    }
    else if (mode == IOM_OUTPUT) {
        chan = &chans[OUTPUT];    /* output only channel */
    }
    else {
        return (IOM_EBADMODE); /* bi-directional channels not supported */
    }
    
    /*
     * Check check if channel is already in use.
     * Use ATM_setu() for atomic test-and-set.
     */
    if (ATM_setu((Uns *)&chan->inuse, TRUE)) {
        return (IOM_EBADIO);            /* ERROR! channel is already open! */
    }

    QUE_new(&chan->pendList);

    chan->dataPacket = NULL;

    /* no need to initialize chan->bufptr */

    chan->cbFxn = cbFxn;
    chan->cbArg = cbArg;

    if (chan->mode == INPUT) {
        IRQ_enable(IRQ_EVT_RINT1);  /* Rx Intr enable */
    }
    else {
        IRQ_enable(IRQ_EVT_XINT1);  /* Tx intr enable */
    }

    *chanp = chan;                  /* return channel handle */

    return (IOM_COMPLETED);         /* success */
}

/*
 *  ======== mdDeleteChan ========
 *  Mark the channel available and disable the appropriate interrupt.
 */
static Int mdDeleteChan(Ptr chanp)
{
    ChanHandle chan = (ChanHandle)chanp;

    chan->inuse = FALSE;

    if (chan->mode == INPUT) {
        IRQ_disable(IRQ_EVT_RINT1);
    }
    else {
        IRQ_disable(IRQ_EVT_XINT1);
    }

    return (IOM_COMPLETED);
}

/*
 *  ======== mdSubmitChan ========
 *  Sets the buf variables in the channel object.  ISR will then
 *  emtpy or fill this buffer.
 */
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
{
    ChanHandle chan = (ChanHandle)chanp;
    Uns         imask;

    /*
     * First check if command is to abort or flush this channel.
     * Note: For this audio codec we are going to toss the output data even 
     *       when flushing.
     */
    if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {

        abortio(chan);  
        
        packet->status = IOM_COMPLETED; /* flush/abort pkt completed */

        return (IOM_COMPLETED);
    }

    imask = HWI_disable();

    if (chan->dataPacket == NULL) {

        chan->bufptr = (Uns *)packet->addr;
        chan->bufcnt = packet->size;

        /* 'dataPacket' must be set last to synchronize with ISR */
        chan->dataPacket = packet;
    }
    else {
        QUE_put(&chan->pendList, packet);
    }

    HWI_restore(imask);

    return (IOM_PENDING);
}

/*
 *  ======== DSK5402_MCBSP_AD50_init ========
 */
#pragma CODE_SECTION(DSK5402_MCBSP_AD50_init, ".text:init")
Void DSK5402_MCBSP_AD50_init(Void)
{
}

/*
 *  ======== rxIsr ========
 *  Handle receive (input) interrupt.
 *
 *  Copies a new sample from McBSP to buffer.  If buffer is full, then call
 *  the registered callback function with the registered argument and the
 *  size of the buffer.
 */
static Void rxIsr(Void)
{
    ChanHandle  chan = &chans[INPUT];

    if (chan->dataPacket == NULL) {
        MCBSP_read(hMcbsp);             /* toss data */
        return;
    }

    *chan->bufptr = MCBSP_read(hMcbsp);

    updateChan(chan);
}

/*
 *  ======== txIsr ========
 *  Handle transmit (output) interrupt.
 *
 *  Copies a new sample from the buffer to MCBSP.  If buffer is empty, then
 *  call the registered callback function with the registered argument and
 *  the size of the buffer.
 */
static Void txIsr(Void)
{
    ChanHandle  chan = &chans[OUTPUT];

    if (chan->dataPacket == NULL) {
        MCBSP_write(hMcbsp, 0);         /* output dummy sample */
        return;
    }

    MCBSP_write(hMcbsp, *chan->bufptr & 0xfffe);

    updateChan(chan);
}

/*
 *  ======== updateChan ========
 *  updateChan() is called at ISR context with appropriate ISR disabled.
 *  updateChan() is used by the rx and tx ISRs to update the channel
 *  structures after input or output sample has been handled.
 */
static Void updateChan(ChanHandle chan)
{
    IOM_Packet *tmpPacket;

    chan->bufptr++;
    chan->bufcnt--;

    /* Is this buffer finished? */
    if (chan->bufcnt == 0) {
        chan->dataPacket->status = IOM_COMPLETED;

        tmpPacket = chan->dataPacket;

        chan->dataPacket = QUE_get(&chan->pendList);
        if (chan->dataPacket == (IOM_Packet *)&chan->pendList) {
            chan->dataPacket = NULL;
        }
        else {
            chan->bufptr = chan->dataPacket->addr;
            chan->bufcnt = chan->dataPacket->size;
        }

        (*chan->cbFxn)(chan->cbArg, tmpPacket);
    }
}

/*
 *  ======== abortio ========
 *  Aborts uncompleted i/o packet requests.
 */
static Void abortio(ChanHandle chan)
{
    IOM_Packet *tmpPacket;

    HWI_disable();
    tmpPacket = chan->dataPacket;
    chan->dataPacket = NULL;
    HWI_enable();
        
    if (tmpPacket) {     
        tmpPacket->status = IOM_ABORTED;   /* abort current request */
        (*chan->cbFxn)(chan->cbArg, tmpPacket); 
                
        tmpPacket = QUE_get(&chan->pendList);
        while (tmpPacket != (IOM_Packet *)&chan->pendList) {

            tmpPacket->status = IOM_ABORTED;   /* abort queued requests */
            (*chan->cbFxn)(chan->cbArg, tmpPacket);

            tmpPacket = QUE_get(&chan->pendList);
        }
    }
}




⌨️ 快捷键说明

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