📄 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 <swi.h>
#include <dev.h>
#include <que.h>
#include "dss_isr.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 IDRAM;
static void DSS_txPrime(int chan, int calledByIsr);
static void DSS_rxPrime(int chan, int calledByIsr);
extern far SWI_Obj DSS_swi;
Int
DSS_close(DEV_Handle device)
{
/* 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(IDRAM, device->object, sizeof(DSS_Obj)) != TRUE) {
return SYS_EALLOC;
}
/* If no other devices are open, then shut down the ISR. */
if (DSS_adcObj[0] == NULL &&
DSS_adcObj[1] == NULL &&
DSS_dacObj[0] == NULL &&
DSS_dacObj[1] == NULL) {
dss_isr_stop();
}
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;
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++;
}
/* wait until the last word of the pending buffer has been sent */
if (dss_isr_get_txCnt_n(chan) != 0) {
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*/
dss_isr_stop();
DSS_txFrame[chan]->size = 0;
QUE_put(device->fromdevice, DSS_txFrame);
DSS_txFrame[chan] = NULL;
dss_isr_set_txBuf_n(NULL, 0, chan);
dss_isr_start();
} else {
dss_isr_stop();
DSS_rxFrame[chan]->size = 0;
QUE_put(device->fromdevice, DSS_rxFrame);
DSS_rxFrame[chan] = NULL;
dss_isr_set_rxBuf_n(NULL, 0, chan);
dss_isr_start();
}
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.
* */
static Bool inited = FALSE;
Void
DSS_init(Void)
{
inited = FALSE;
}
Int
DSS_issue(DEV_Handle 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;
int chan;
if (inited == FALSE) {
dss_isr_init();
inited = TRUE;
}
/* decode chan from arg */
/* error check, first char must be non-null and second must be null */
if (arg[0] == '\0' || arg[1] != '\0') {
return SYS_ENODEV;
}
switch (*arg) {
case '0' :
chan = 0;
break;
case '1':
chan = 1;
break;
default:
return SYS_ENODEV;
}
/* Only one input and one ouptput device can be opened */
if (device->mode == DEV_INPUT) {
if (DSS_adcObj[chan] != NULL) {
return SYS_EBUSY;
} else {
DSS_adcObj[chan] = device;
}
} else if (device->mode == DEV_OUTPUT) {
if (DSS_dacObj[chan] != NULL) {
return SYS_EBUSY;
} else {
DSS_dacObj[chan] = device;
}
} else {
/* something isn't right if we get here */
return SYS_EMODE;
}
objptr = MEM_alloc(IDRAM, sizeof(DSS_Obj), 0);
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); /* used to be set to device->nbufs */
}
objptr->ready = NULL;
objptr->chan = chan;
device->object = (Ptr)objptr;
dss_isr_set_swi_n(&DSS_swi, chan);
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)
{
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
};
/*
* Auxillary functions.
*/
void
DSS_swi_fxn(int arg0, int arg1)
{
Uns mbox = SWI_getmbox();
if (mbox & DSS_ISR_TX_0_FLAG) {
DSS_txPrime(0, 1);
}
if (mbox & DSS_ISR_TX_1_FLAG) {
DSS_txPrime(1, 1);
}
if (mbox & DSS_ISR_RX_0_FLAG) {
DSS_rxPrime(0, 1);
}
if (mbox & DSS_ISR_RX_1_FLAG) {
DSS_rxPrime(1, 1);
}
}
/*
* ======= DSS_txPrime ========
* DSS_dacObj must not be NULL!!
*/
static void
DSS_txPrime(int chan, int calledByIsr)
{
DEV_Frame *tmpFrame;
QUE_Handle txQueue = DSS_dacObj[chan]->todevice;
if (!calledByIsr)
dss_isr_stop();
if (dss_isr_get_txCnt_n(chan) == 0) {
/* return empty frame back to client */
if (DSS_txFrame[chan] != NULL && calledByIsr) {
QUE_put(DSS_dacObj[chan]->fromdevice, DSS_txFrame[chan]);
SEM_post(((DSS_Handle)DSS_dacObj[chan]->object)->sync);
DSS_txFrame[chan] = NULL;
}
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) {
QUE_put(DSS_dacObj[chan]->fromdevice, tmpFrame);
SEM_post(((DSS_Handle)DSS_dacObj[chan]->object)->sync);
/* go 'round again */
} else {
/* give full frame to isr */
DSS_txFrame[chan] = tmpFrame;
dss_isr_set_txBuf_n(DSS_txFrame[chan]->addr,
DSS_txFrame[chan]->size/sizeof(short),
chan);
break;
}
}
else {
break;
}
}
}
if (!calledByIsr)
dss_isr_start();
}
/*
* ======= DSS_rxPrime ========
* DSS_adcObj must not be NULL!!
*/
static void
DSS_rxPrime(int chan, int calledByIsr)
{
DEV_Frame *tmpFrame;
QUE_Handle rxQueue = DSS_adcObj[chan]->todevice;
if (!calledByIsr)
dss_isr_stop();
if (dss_isr_get_rxCnt_n(chan) == 0 ) {
/* return full frame back to client */
if (DSS_rxFrame[chan] != NULL && calledByIsr) {
QUE_put(DSS_adcObj[chan]->fromdevice, DSS_rxFrame[chan]);
SEM_post(((DSS_Handle)DSS_adcObj[chan]->object)->sync);
DSS_rxFrame[chan] = NULL;
}
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) {
QUE_put(DSS_adcObj[chan]->fromdevice, tmpFrame);
SEM_post(((DSS_Handle)DSS_adcObj[chan]->object)->sync);
}
else {
/* give empty frame to isr */
DSS_rxFrame[chan] = tmpFrame;
dss_isr_set_rxBuf_n(DSS_rxFrame[chan]->addr,
DSS_rxFrame[chan]->size/sizeof(short),
chan);
break;
}
}
else {
break;
}
}
}
if (!calledByIsr)
dss_isr_start();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -