📄 dss.c
字号:
/* ***********************************************************
* THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
* REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
* COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
* TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
* POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
* INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
* YOUR USE OF THE PROGRAM.
*
* IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
* THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
* OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
* EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
* REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
* OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
* USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
* AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
* YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
* (U.S.$500).
*
* Unless otherwise stated, the Program written and copyrighted
* by Texas Instruments is distributed as "freeware". You may,
* only under TI's copyright in the Program, use and modify the
* Program without any charge or restriction. You may
* distribute to third parties, provided that you transfer a
* copy of this license to the third party and the third party
* agrees to these terms by its first use of the Program. You
* must reproduce the copyright notice and any other legend of
* ownership on each copy or partial copy, of the Program.
*
* You acknowledge and agree that the Program contains
* copyrighted material, trade secrets and other TI proprietary
* information and is protected by copyright laws,
* international copyright treaties, and trade secret laws, as
* well as other intellectual property laws. To protect TI's
* rights in the Program, you agree not to decompile, reverse
* engineer, disassemble or otherwise translate any object code
* versions of the Program to a human-readable form. You agree
* that in no event will you alter, remove or destroy any
* copyright notice included in the Program. TI reserves all
* rights not specifically granted under this license. Except
* as specifically provided herein, nothing in this agreement
* shall be construed as conferring by implication, estoppel,
* or otherwise, upon you, any license or other right under any
* TI patents, copyrights or trade secrets.
*
* You may not use the Program in non-TI devices.
* ********************************************************* */
#include <std.h>
#include <sem.h>
#include <mem.h>
#include <dev.h>
#include <que.h>
#include <log.h>
#include "lio.h"
#include "dss.h"
DEV_Obj *DSS_adcObj[2] = { NULL, NULL };
DEV_Obj *DSS_dacObj[2] = { NULL, NULL };
DEV_Frame *DSS_txFrame[2] = { NULL, NULL};
DEV_Frame *DSS_rxFrame[2] = { NULL, NULL};
extern Int SDRAM;
extern LIO_Fxns DSS_LIO_FXNS;
static void DSS_txPrime(int chan, int calledByIsr);
static void DSS_rxPrime(int chan, int calledByIsr);
void DSS_callback(int chan, Arg ignored);
Int
DSS_close(DEV_Handle device)
{
DSS_Handle objptr = (DSS_Handle)device->object;
objptr->drv->close(objptr->chan);
/* Null out the device object pointer used by the isr. */
if (device->mode == DEV_OUTPUT) {
DSS_adcObj[((DSS_Obj *)device->object)->chan] = NULL;
} else {
DSS_dacObj[((DSS_Obj *)device->object)->chan] = NULL;
}
/* Free the memory now that we aren't using it. */
if (MEM_free(SDRAM, device->object, sizeof(DSS_Obj)) != TRUE) {
return SYS_EALLOC;
}
return(0);
}
Int
DSS_ctrl(DEV_Handle handle, Uns val, Arg arg)
{
/* no control ops */
return SYS_EINVAL;
}
Int
DSS_idle(DEV_Handle device, Bool flush)
{
DSS_Handle objptr = (DSS_Handle)device->object;
int chan = objptr->chan;
int drvChan;
if (chan == 0)
drvChan = 1;
else
drvChan = 3;
if ((device->mode == DEV_OUTPUT) && !flush) {
Uns post_count = 0;
/* wait until all pending buffers have been sent */
while(!QUE_empty(device->todevice)) {
SEM_pend(objptr->sync, SYS_FOREVER);
post_count++;
}
/* PENDING: Not correct semantics for getBuf */
/* wait until the last word of the pending buffer has been sent */
if (objptr->drv->isEmpty(drvChan) != 1) {
SEM_pend(objptr->sync, SYS_FOREVER);
post_count++;
}
/* in theory the device has now stopped transmitting */
while(post_count > 0) {
SEM_post(objptr->sync);
post_count--;
}
} else {
if (device->mode == DEV_OUTPUT) {
/* flush pending output*/
objptr->drv->stop(drvChan);
DSS_txFrame[chan]->size = 0;
QUE_put(device->fromdevice, DSS_txFrame);
DSS_txFrame[chan] = NULL;
objptr->drv->setBuf(drvChan, NULL, 0);
objptr->drv->start(drvChan);
} else {
objptr->drv->stop(drvChan);
DSS_rxFrame[chan]->size = 0;
QUE_put(device->fromdevice, DSS_rxFrame);
DSS_rxFrame[chan] = NULL;
objptr->drv->setBuf(drvChan, NULL, 0);
objptr->drv->start(drvChan);
}
while (!QUE_empty(device->todevice)) {
QUE_put(device->fromdevice, QUE_get(device->todevice));
SEM_post(objptr->sync);
}
}
return SYS_OK;
}
/* PENDING
*
* This is a collection of hacks to get around recent changes in the
* startup sequence. It used to be that DEV_startup called the DEV init
* functions. This was good, because dss_isr_init_evm6x depends on the
* interrupt mux having been set and that is done by HWI_init. Well, for
* various reasons the DEV init functions are now called in *DEV_init
* *before* HWI_init has set the mux. Aargh. So now I'll just set a flag
* and call dss_isr_init in DSS_open if it hasn't been called yet.
* */
Void
DSS_init(Void)
{
/* PENDING: Hardcoded init references. */
LOG_message("DSS_init called", NULL);
DSS_LIO_FXNS.init(0, 0);
DSS_LIO_FXNS.init(1, 0);
DSS_LIO_FXNS.init(2, 0);
DSS_LIO_FXNS.init(3, 0);
}
Int
DSS_issue(DEV_Handle device)
{
LOG_message("DSS_issue: device == 0x%x", (Uns)device);
if (device->mode == DEV_OUTPUT) {
DSS_txPrime(((DSS_Obj *)device->object)->chan, 0);
} else {
DSS_rxPrime(((DSS_Obj *)device->object)->chan, 0);
}
return SYS_OK;
}
/* PENDING: Decode channel number from arg. */
Int
DSS_open(DEV_Handle device, String arg)
{
DSS_Handle objptr;
LOG_message("DSS_open called for chan %d", atoi(arg));
objptr = MEM_alloc(SDRAM, sizeof(DSS_Obj), 0);
/* PENDING: Very much should error check this */
if (objptr == NULL) {
return SYS_EALLOC;
}
objptr->chan = atoi(arg);
/* Only one input and one ouptput device can be opened */
if (device->mode == DEV_INPUT) {
if (DSS_adcObj[objptr->chan] != NULL) {
return SYS_EBUSY;
} else {
DSS_adcObj[objptr->chan] = device;
}
} else if (device->mode == DEV_OUTPUT) {
if (DSS_dacObj[objptr->chan] != NULL) {
return SYS_EBUSY;
} else {
DSS_dacObj[objptr->chan] = device;
}
} else {
/* something isn't right if we get here */
return SYS_EMODE;
}
if (device->mode == DEV_INPUT) {
/* there aren't any received buffers yet */
objptr->sync = SEM_create(0, NULL);
} else {
objptr->sync = SEM_create(0, NULL);
}
objptr->ready = NULL;
objptr->drv = &DSS_LIO_FXNS; /* SIO_LIO_DRIVER must be assigned in
* the linker command file to an LIO
* driver table.
*/
if (objptr->chan == 0) {
if (device->mode == DEV_INPUT) {
objptr->drv->init(0, 0);
objptr->drv->setCallback(0,
(LIO_TcallBack)DSS_callback,
0);
}
else {
objptr->drv->init(1, 0);
objptr->drv->setCallback(1,
(LIO_TcallBack)DSS_callback,
0);
}
}
else {
if (device->mode == DEV_INPUT) {
objptr->drv->init(2, 0);
objptr->drv->setCallback(2,
(LIO_TcallBack)DSS_callback,
0);
}
else {
objptr->drv->init(3, 0);
objptr->drv->setCallback(3,
(LIO_TcallBack)DSS_callback,
0);
}
}
device->object = (Ptr)objptr;
return SYS_OK;
}
Bool
DSS_ready(DEV_Handle device, SEM_Handle sem)
{
((DSS_Handle)device->object)->ready = sem;
DSS_rxPrime(((DSS_Obj *)device->object)->chan, 0);
return (TRUE);
}
Int
DSS_reclaim(DEV_Handle device)
{
LOG_message("DSS_reclaim enter: device == 0x%x", (Uns)device);
if (SEM_pend(((DSS_Handle)device->object)->sync, device->timeout)) {
return SYS_OK;
} else {
return SYS_ETIMEOUT;
}
}
/*
* SPOX Device Driver entry points
*/
DEV_Fxns DSS_FXNS = {
DSS_close,
DSS_ctrl,
DSS_idle,
DSS_issue,
DSS_open,
DSS_ready,
DSS_reclaim
};
/*
* ======= DSS_txPrime ========
* DSS_dacObj must not be NULL!!
*/
static int txPrimed[2] = {0,0};
static void
DSS_txPrime(int chan, int calledByIsr)
{
DEV_Frame *tmpFrame;
QUE_Handle txQueue = DSS_dacObj[chan]->todevice;
DSS_Handle objptr = (DSS_Handle)DSS_dacObj[chan]->object;
int wasPrimed = 0;
Ptr buf;
int drvChan;
if (chan == 0)
drvChan = 1;
else
drvChan = 3;
if (!calledByIsr) {
objptr->drv->stop(drvChan);
}
buf = objptr->drv->getBuf(drvChan, NULL, NULL);
/* Note the NULLs, this SIO driver only supports full frames */
#if 0
LOG_message("Tx isr:%d ", calledByIsr);
LOG_message("Tx frm:0x%x", (Arg)DSS_txFrame[chan]);
LOG_message("Tx primed:%d",txPrimed[chan]);
LOG_message("Tx buf:0x%x", (Arg)buf);
LOG_message("Tx chan:%d", chan);
#endif
wasPrimed = txPrimed[chan];
/* return empty frame back to client */
if (DSS_txFrame[chan] != NULL && calledByIsr) {
#if 0
LOG_message("Tx post frame", NULL);
#endif
QUE_enqueue(DSS_dacObj[chan]->fromdevice, DSS_txFrame[chan]);
SEM_post(objptr->sync);
DSS_txFrame[chan] = NULL;
txPrimed[chan] = 0;
}
/* if the DRV is waiting for another buffer */
if (buf != NULL || !wasPrimed) {
while(1) {
/* if there is a frame on the tx queue */
tmpFrame = (DEV_Frame *)QUE_get(txQueue);
if (tmpFrame != (DEV_Frame *)txQueue) {
if (tmpFrame->size == 0) {
#if 0
LOG_message("Tx zero frame", NULL);
#endif
QUE_enqueue(DSS_dacObj[chan]->fromdevice, tmpFrame);
SEM_post(objptr->sync);
/* go 'round again */
} else {
/* give full frame to isr */
DSS_txFrame[chan] = tmpFrame;
#if 0
LOG_message("Tx new frame 0x%x", (Arg)DSS_txFrame[chan]);
#endif
objptr->drv->setBuf(drvChan,
(Ptr)DSS_txFrame[chan]->addr,
(Uns)DSS_txFrame[chan]->size);
txPrimed[chan] = 1;
break;
}
}
else {
#if 0
LOG_message("Tx no frame avail", NULL);
LOG_message("Tx buffer 0x%x", (Arg)buf);
LOG_message("Tx wasPrimed %d", wasPrimed);
#endif
break;
}
}
}
else {
#if 0
LOG_message("Tx already primed", NULL);
#endif
}
if (!calledByIsr) {
objptr->drv->start(drvChan);
}
}
/*
* ======= DSS_rxPrime ========
* DSS_adcObj must not be NULL!!
*/
static int rxPrimed[2] = {0,0};
static void
DSS_rxPrime(int chan, int calledByIsr)
{
DEV_Frame *tmpFrame;
QUE_Handle rxQueue = DSS_adcObj[chan]->todevice;
DSS_Handle objptr = (DSS_Handle)DSS_adcObj[chan]->object;
int wasPrimed = 0;
Ptr buf;
int drvChan;
if (chan == 0)
drvChan = 0;
else
drvChan = 2;
if (!calledByIsr) {
objptr->drv->stop(drvChan);
}
buf = objptr->drv->getBuf(drvChan, NULL, NULL);
/* Note the NULLs, this SIO driver only supports full frames */
#if 0
LOG_message("Rx isr:%d ", calledByIsr);
LOG_message("Rx frm:0x%x", (Arg)DSS_rxFrame[chan]);
LOG_message("Rx primed:%d",rxPrimed[chan]);
LOG_message("Rx buf:0x%x", (Arg)buf);
LOG_message("Rx chan:%d", chan);
#endif
wasPrimed = rxPrimed[chan];
/* return full frame back to client */
if (DSS_rxFrame[chan] != NULL && calledByIsr) {
#if 0
LOG_message("Rx post frame", NULL);
#endif
QUE_enqueue(DSS_adcObj[chan]->fromdevice, DSS_rxFrame[chan]);
SEM_post(objptr->sync);
DSS_rxFrame[chan] = NULL;
rxPrimed[chan] = 0;
}
/* if the DRV is waiting for another buffer */
if (buf != NULL || !wasPrimed) {
while(1) {
/* if there is a frame on the rx queue */
tmpFrame = (DEV_Frame *)QUE_get(rxQueue);
if (tmpFrame != (DEV_Frame *)rxQueue) {
if (tmpFrame->size == 0) {
#if 0
LOG_message("Rx zero frame", NULL);
#endif
QUE_enqueue(DSS_adcObj[chan]->fromdevice, tmpFrame);
SEM_post(objptr->sync);
}
else {
/* give empty frame to isr */
DSS_rxFrame[chan] = tmpFrame;
#if 0
LOG_message("Rx new frame 0x%x", (Arg)DSS_rxFrame[chan]);
#endif
objptr->drv->setBuf(drvChan,
(Ptr)DSS_rxFrame[chan]->addr,
(Uns)DSS_rxFrame[chan]->size);
rxPrimed[chan] = 1;
break;
}
}
else {
#if 0
LOG_message ("Rx ERROR: no frame avail", NULL);
#endif
break;
}
}
}
else {
#if 0
LOG_message("Rx already primed", NULL);
#endif
}
if (!calledByIsr) {
objptr->drv->start(drvChan);
}
}
void DSS_callback(int chan, Arg ignored)
{
if ((chan == 0) || (chan == 2)) {
if (chan == 2)
chan = 1;
DSS_rxPrime(chan, 1);
} else {
if (chan == 1 )
chan = 0;
else
chan = 1;
DSS_txPrime(chan, 1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -