vxworks中sd卡文件系统

       在调试好sd卡的底层驱动后,需要加载文件系统,这样才能方便的进行文件读写。而sd卡驱动要调试到什么程度呢,首先sd卡的初始化要没问题,裸读和裸写没有问题,例如读写一个2048字节的数据读到的数据和写入的数据是一样的,此时就算成功了。

      在vxworks中,每个设备都有一个节点,通过open,close,read,write这几个函数来操作设备节点。如何建立节点,这就是本日志的内容。文件系统和底层的sd卡驱动是独立的,它们有一些量作为中间纽带,也就是说,在sd卡驱动调试好之后需要向文件系统传递一些东西,有sd卡的读写接口函数。sd卡总的块的数量,以及每块的大小值(一般为512字节)

	pDrvCtrl->card.card = (struct mmc *)mmcdev;
	nblock = mmcdev->block_dev.lba;


	pDrvCtrl->card.blockNumber = nblock;
	pDrvCtrl->card.blockSize = mmcdev->block_dev.blksz;
	pDrvCtrl->cardIns = TRUE;

	pDrvCtrl->card.cardinsert = TRUE;

	pDrvCtrl->card.blkRd = (FUNCPTR)mmcdev->block_dev.block_read;
	pDrvCtrl->card.blkWt = (FUNCPTR)mmcdev->block_dev.block_write;

向这个pDrvCtrl结构体放入读写函数的地址,上层就通过这两个函数来对底层进行读写,同时告诉系统这个sd卡的大小为nblock块。在vxworks中,系统一般提供vxbus这种设备驱动模块,sd卡也就是注册到这当中作为一个模块。

xbd->bioMutex = semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
    if (xbd->bioMutex == NULL)
        goto error;

    xbd->bioReady = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
    if (xbd->bioReady == NULL)
        goto error;

    xbd->xbdSemId = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
    if (xbd->xbdSemId == NULL)
        goto error;

    if (!xbd->directModeFlag)
        {
        /* spawn service task */

        xbd->svcTaskId = taskSpawn (SDMMC_XBD_SVC_TASK_NAME, SDMMC_XBD_SVC_TASK_PRI,
                                    0, SDMMC_XBD_SVC_TASK_STACK,
                                    (FUNCPTR)sdMmcXbdBioSvcTask, (int)xbd,
                                    0, 0, 0, 0, 0, 0, 0, 0, 0);
        if (xbd->svcTaskId == ERROR)
            goto error;
        }
    /* register new event handler for base device synchronization */


    rc = erfHandlerRegister (xbdEventCategory, xbdEventInstantiated,
                             sdMmcXbdCreateSyncHandler, xbd, 0);
    if (rc != OK)
        goto error;


    /* attach XBD */

    if (devName == NULL)
        {
			logMsg("please point the name for sd\n",0,0,0,0,0,0);
			goto error;
        }
    else
        {
        strcpy ((char *)xbd->devName, devName);
        }

 rc = xbdAttach (&xbd->xbd, &sdMmcXbdFuncs, xbd->devName,xbd->blockSize,
                    xbd->blockNumber, &dev);
    if (rc != OK)
        goto error;

    /* raise an insert event */
   rc = erfEventRaise (xbdEventCategory, xbdEventPrimaryInsert, ERF_ASYNC_PROC,
                        (void *)dev, NULL);

    if (rc != OK)
        goto error;

    xbd->xbdInserted = 1;

    /* wait for FSM to send xbdEventInstantiated event */
    rc = semTake (xbd->xbdSemId, WAIT_FOREVER);
 该代码首先创建了3个系统信号量,然后开始注册sd卡设备。其中最重要的是xbdAttach函数,该函数以一个xbd结构体作为支点,放入几个参数,
xbd->devName,xbd->blockSize,  xbd->blockNumber
分别为xbd的名字(该名字就是会出现到节点中的名字),xbd块大小,xbd块的数量。还有一个就是
sdMmcXbdFuncs
这是一个结构体地址
LOCAL struct xbd_funcs sdMmcXbdFuncs =
    {
    sdMmcXbdIoctl,
    sdMmcXbdStrategy,
    sdMmcXbdDump,
    };
该结构注册了3个本地函数,其中最重要的是
sdMmcXbdIoctl
系统在节点操作时,会调用该函数,而在该函数中又会调用一个真正操作的子函数

LOCAL void sdMmcXbdExecBio
    (
    SDMMC_XBD_DEV * xbd,
    struct bio *    bio
    )
    {
    unsigned blkSize;
    sector_t blkNum;
    unsigned nblocks;
    unsigned size;
    STATUS rc = ERROR;

    blkSize = xbd->xbd.xbd_blocksize;
    blkNum = xbd->xbd.xbd_nblocks;

    /* check that all of this transaction fits in the disk */

    size = bio->bio_bcount;
    nblocks = size / blkSize;

    /* if our starting block number is bad, done with error */

    if (bio->bio_blkno >= blkNum)
        {
        bio->bio_bcount = 0;
        bio_done (bio, ENOSPC);
        return;
        }

    /* if we overrun the end of the disk, truncate the block number */

    if (bio->bio_blkno + nblocks > blkNum)
        nblocks = blkNum - bio->bio_blkno;

    /* calculate the real size */

    size = nblocks * blkSize;
    bio->bio_bcount = size;

    /* if we have less than 1 block, done it */

    if (nblocks == 0)
        {
        bio->bio_bcount = 0;
        bio_done (bio, 0);
        return;
        }

    if (bio->bio_flags & BIO_READ)
        {
        rc = xbd->blkRd (xbd->card, bio->bio_blkno, nblocks, bio->bio_data);
        }
    else if (bio->bio_flags & BIO_WRITE)
        {
        rc = xbd->blkWt (xbd->card, bio->bio_blkno, nblocks, bio->bio_data);
        }

    if (rc == OK)
        {
        bio_done (bio, 0);
        }
    else
        {
        bio->bio_bcount = 0;
        if (errno == S_ioLib_DISK_NOT_PRESENT)
            bio_done (bio, ENXIO);
        else
            bio_done (bio, errno);
        }
	SDMMC_XBD_DBG (SDMMC_XBD_DBG_RW, "END  blkNo (%d) numBlks (%d) buf (0x%08x)\n",
                   (int)bio->bio_blkno, (int)nblocks, (int)bio->bio_data,
                   0, 0, 0);
    }
在代码中
        rc = xbd->blkRd (xbd->card, bio->bio_blkno, nblocks, bio->bio_data);
        rc = xbd->blkWt (xbd->card, bio->bio_blkno, nblocks, bio->bio_data);
这两句其实就是调用之前注册的读写接口函数。

        还要注意的是xbdAttach函数一般是有操作顺序的,要erfHandlerRegister,xbdAttach,erfEventRaise这三个函数一起连用来完成。该代码执行时,系统会读写sd卡的相应块区域,读写的数据这是由文件系统决定的。

      执行完以上函数后,在系统shell中就创建了一个节点,比如代码中给的/sd名字,在shell中输入devs命令,就会出现/sd:0的节点,这时用cd命令进入该节点,同时输入ls命令可以查看该目录的结构。在第一次使用时可以使用dosfsDiskFormat函数对该块设备进行格式化;同时应用程序中就可以使用open和read,write函数对该节点进行读写。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔波的IT人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值