📄 async_mmc.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.11.00.00 11-04-03 (ddk-b13)" */
/*
* ======== async_mmc.c ========
*
* MMC Driver Async Test for the MMC on a C5509 DSP EVM.
* The test is to transfer data from DSP memory to the MMC card
* (MMC write) or from the MMC card to DSP memory (MMC read)
* Data values placed in the memory are based on channel number, such as
* 0x00010001 transfered for channel one, 0x00050005 for channel 5.
*
* User defines the following parameters:
*
* -- CHANNUM: Number of channels to be opened
* -- MMCREQNUM: Number of IOPs for each channel
* -- TRANSFERCOUNT: # of words to be transfered
*/
#include <stdio.h>
#include <std.h>
#include <log.h>
#include <sys.h>
#include <tsk.h>
#include <gio.h>
#include <iom.h>
#include <async.h>
#include <csl_mmc.h>
#include <c5509_mmc.h>
/* Test Configuration Parameters */
#define CHANNUM 4 /* Maximum number of channels */
/* A task is spawned for each channel */
#define MMCREQNUM 4 /* Depth of each request queue */
/* Constraint: MMCREQNUM must always be even */
/* interrupt mask definitions */
#define C5509_MMC_IER0_MASK_DEFAULT 1
#define C5509_MMC_IER1_MASK_DEFAULT 1
extern LOG_Obj trace;
/* Reserve space for channels */
static C5509_MMC_ChanObj chans[CHANNUM];
/* Globals */
C5509_MMC_DevObj C5509_MMC_devObj;
/* Bind Parameters */
C5509_MMC_DevParams C5509_MMC_devParams = {
/* devParams */
C5509_MMC_VERSION_1, /* Version number */
0, /* Enable/disable DMA for data read/write */
0, /* dat3EdgeDetection -- DUMMY */
0, /* Determines if MMC goes IDLE during IDLE instr */
0, /* enableClkPin -- DUMMY */
2, /* CPU CLK to MMC function clk divide down */
3, /* MMC function clk to memory clk divide down */
0, /*
* No. memory clks to wait before response timeout
* Zero indicates no timeout.
*/
0, /*
* No. memory clks to wait before data timeout
* Zero indicates no timeout.
*/
512, /* Length of DATA block to be read in BYTEs*/
/* drvrParams */
2, /* RCA - set by the application */
CHANNUM, /* maximum number of channels required */
MEDIA_BYTENORMAL, /* MEDIA_[BYTESWAP|BYTENORMAL] */
0, /* DMA channel number used for READ operations */
0, /* DMA channel number used for WRITE operations */
NULL, /* Buffer for DMA read */
NULL, /* Buffer for DMA write */
chans, /* Array of (noChan number of) Channel Objs */
C5509_MMC_IER0_MASK_DEFAULT,
C5509_MMC_IER1_MASK_DEFAULT
};
/* User defined constants */
#define TRANSFERCOUNT C5509_MMC_SECLEN
#define SLEEPTIME 10
typedef struct CallbackObj {
Int chanNum; /* trace the channel number */
Int reqNum; /* index for trace submitted request */
Int cmd; /* IOM_READ/IOM_WRITE */
MdUns value; /* value to write to memory, then read it back */
Bool packetFree; /* if the packet is free to use */
} CallbackObj;
static Void chanCallback(Ptr arg, Int status, Ptr reqp, Uns size);
static Void chanTsk(Arg chanNum);
static Void setMem(Int count, MdUns *memAddr, MdUns value);
static Bool verifyData(Int chanNum, Ptr reqp, MdUns value);
static GIO_Handle gio[CHANNUM];
/* Declare here so that the stack space is conserved */
static MdUns globalSectorBuffers[CHANNUM][MMCREQNUM][C5509_MMC_SECLEN];
/*
* ======== main ========
*/
Void main()
{
TSK_Attrs tskAttrs[CHANNUM];
GIO_Attrs gioAttrs[CHANNUM];
Int i;
for (i = 0; i < CHANNUM; i++) {
/* GIO_Attrs init */
gioAttrs[i].nPackets = MMCREQNUM;
gioAttrs[i].timeout = SYS_FOREVER;
}
/* create IOM objs */
for (i = 0; i < CHANNUM; i++) {
gio[i] = ASYNC_create("/udevMmc0", IOM_INOUT, NULL, NULL, &gioAttrs[i]);
if (gio[i] == NULL) {
LOG_printf (&trace, "ERROR: GIO_create NULL!");
}
}
/* create tasks */
for (i = 0; i < CHANNUM; i++) {
tskAttrs[i] = TSK_ATTRS;
if (TSK_create ((Fxn)chanTsk, &tskAttrs[i], (Arg)i) == NULL) {
LOG_printf (&trace, "ERROR: TSK_create NULL!");
}
}
LOG_printf (&trace, "Exitting main");
/* fall into DSP/BIOS idle loop */
return;
}
/*
* ======== chanCallback ========
* Handle callback
*/
static Void chanCallback(Ptr arg, Int status, Ptr reqp, Uns size)
{
CallbackObj *pCallback = (CallbackObj *)arg;
MEDIA_RdWrObj *req = (MEDIA_RdWrObj *)reqp;
Int chanNum = pCallback->chanNum;
/*
* if this callback is for ASYNC_read, then check
* if read value = written value
*/
if (pCallback->cmd == IOM_READ) {
if (verifyData(chanNum, req, pCallback->value)) {
LOG_printf (&trace, "[%d] verifyData OK!", chanNum);
}
else {
LOG_printf (&trace, "[%d] ERROR: verifyData Failed!", chanNum);
}
}
pCallback->packetFree = TRUE;
}
/*
* ======== chanTsk ========
*/
static Void chanTsk(Arg channelNumber)
{
Uns size;
Int status;
MEDIA_RdWrObj req[MMCREQNUM];
MEDIA_RdWrObj *curReq;
GIO_AppCallback gioCallback[MMCREQNUM];
CallbackObj callback[MMCREQNUM];
MdUns value;
Int submitReqIndex;
Int j;
Int chanNum;
Int yieldCount;
chanNum = ArgToInt(channelNumber);
value = (MdUns)(chanNum | 0xAA00);
/* First set write req, then set read request */
/* A paired write and read operate on the same sectorNumber */
for (j = 0; j < MMCREQNUM; j = j + 2) {
/* MMC write : DSP->MMC Card */
req[j].buf = globalSectorBuffers[chanNum][j];
req[j].address = chanNum * 100 + j;
req[j].subAddress = 0;
req[j].length = C5509_MMC_SECLEN;
callback[j].cmd = IOM_WRITE;
/* MMC read : MMC Card->DSP */
req[j + 1].buf = globalSectorBuffers[chanNum][j + 1];
req[j + 1].address = chanNum * 100 + j;
req[j + 1].subAddress = 0;
req[j + 1].length = C5509_MMC_SECLEN;
callback[j + 1].cmd = IOM_READ;
}
for (j = 0; j < MMCREQNUM; j++) {
callback[j].chanNum = chanNum;
callback[j].reqNum = j;
callback[j].value = value;
callback[j].packetFree = TRUE;
gioCallback[j].fxn = (GIO_TappCallback)chanCallback;
gioCallback[j].arg = (Ptr)(&callback[j]);
}
submitReqIndex = 0;
for (;;) {
yieldCount = 0;
LOG_printf (&trace, "[%d] IsPacketFreeAt [%d]",
chanNum, submitReqIndex);
while (!callback[submitReqIndex].packetFree) {
yieldCount++;
TSK_sleep (SLEEPTIME);
}
LOG_printf (&trace, "[%d] Slept [%d] times", chanNum, yieldCount);
callback[submitReqIndex].packetFree = FALSE;
curReq = (MEDIA_RdWrObj *)(&req[submitReqIndex]);
if (callback[submitReqIndex].cmd == IOM_WRITE) {
/*
* set dsp memory value as chanNum chanNum ...
* (for example: 0x0001 0x0001 ... for Chan1)
*/
setMem(TRANSFERCOUNT, curReq->buf, value);
/* MMC write: DSP->MMC. Write the value to MMC card */
size = sizeof (*curReq);
status = ASYNC_write(gio[chanNum], curReq, &size,
&gioCallback[submitReqIndex]);
if (status < 0) {
LOG_printf (&trace, "[%d] ERROR: ASYNC_write status [%d]",
chanNum, status);
}
} else { /* IOM_READ */
/* first set dsp mem value to default 0xDEAD */
setMem(TRANSFERCOUNT, curReq->buf, 0xDEAD);
/* MMC read: MMC->DSP. Readback MMC card contents to DSP memory */
size = sizeof (*curReq);
status = ASYNC_read(gio[chanNum], curReq, &size,
&gioCallback[submitReqIndex]);
if (status < 0) {
LOG_printf (&trace, "[%d] ERROR: ASYNC_read status [%d]",
chanNum, status);
}
}
submitReqIndex++;
if (submitReqIndex == MMCREQNUM) {
submitReqIndex = 0;
}
TSK_yield (); /* Yield control to another task */
}
}
/*
* ======== setMem ========
* Set memory value
*/
static Void setMem(Int count, MdUns *memAddr, MdUns value)
{
MdUns *tempMem = (MdUns *)memAddr;
Int i;
for (i = 0; i < count; i++) {
*tempMem = value;
tempMem++;
}
}
/*
* ======== verifyData ========
* Verify read back data
*/
static Bool verifyData(Int chanNum, Ptr reqp, MdUns value)
{
MEDIA_RdWrObj *req;
MdUns *addr;
Int i;
req = (MEDIA_RdWrObj *)reqp;
if (req != NULL) {
addr = (MdUns *)req->buf;
for (i = 0; i < req->length; i++) {
if (*addr != value) {
LOG_printf (&trace, "[%d] ERROR: in verifyData at addr [0x%x]",
chanNum, addr);
return FALSE;
}
addr++;
}
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -