全志D1开发(十)SD驱动之挂载根文件系统

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2022年5月3日18:07:49 1 881

1. 完善SD驱动

1.1 完善SD控制和传输函数

根据上一章节封装的几个硬件设置接口,在控制和传输函数中相应位置进行调用:

static int sdIoctl (PLW_SD_ADAPTER psdadapter, int cmd, long arg)
{
    switch (cmd) {
    case SDBUS_CTRL_POWEROFF:
        // TODO:关闭电源
        break;
    case SDBUS_CTRL_POWERUP:
    case SDBUS_CTRL_POWERON:
        // TODO:使能电源
        break;
    case SDBUS_CTRL_SETBUSWIDTH:
        // TODO:设置线宽
        sunxi_mmc0_buswidth_set((int)arg);
        break;
    case SDBUS_CTRL_SETCLK:
        // TODO:设置时钟频率
        sunxi_mmc0_clock_set((int)arg);
        break;
    case SDBUS_CTRL_DELAYCLK:
        break;
    case SDBUS_CTRL_GETOCR:
        // TODO:获取支持的电压情况
        *(UINT32 *)arg = SD_VDD_32_33 | SD_VDD_33_34;
        break;
    default:
        return -1;
    }

    return 0;
}
static int sdTransfer (PLW_SD_ADAPTER psdadapter,
                       PLW_SD_DEVICE  psddevice,
                       PLW_SD_MESSAGE psdmsg,
                       int            num)
{
    int ret;

    while (num--) {
        ret = sunxi_mmc0_xfer(psdmsg);
        if (ret) {
            return -1;
        }
        psdmsg++;
    }

    return 0;
}

sdTransfer 函数中根据SD消息的个数循环调用 sunxi_mmc0_xfer 传输命令和数据。同时在 sdDevCreate 中调用控制器硬件初始化设置接口:

int sdDevCreate (void)
{
    // TODO:硬件初始化
    sunxi_mmc0_init();

    // 创建SD适配器
    API_SdAdapterCreate("/bus/sd/0", &sdfuncs);

    // 注册SD存储设备类驱动
    API_SdmLibInit();
    API_SdMemDrvInstall();

    // 注册host信息到sdm框架
    sdmhost = API_SdmHostRegister(&sdhost);

    // 通知sdm框架立即初始化sd卡,创建块设备等
    API_SdmEventNotify(sdmhost, SDM_EVENT_BOOT_DEV_INSERT);

    return 0;
}

1.2 修改映射和内核启动参数

在bspMap.h中添加ccu和smhc模块寄存器地址映射:

全志D1开发(十)SD驱动之挂载根文件系统

接着修改内核启动参数,将原来的根文件系统从挂载在ram换成挂载在sd卡上:

/*
 *  这里使用 bsp 设置启动参数, 如果 bootloader 支持, 可使用 bootloader 设置.
 *  为了兼容以前的项目, 这里 kfpu=yes 允许内核中(包括中断)使用 FPU.
 *
 *  TODO: 可以修改内核启动参数
 */
API_KernelStartParam("ncpus=1 kdlog=no kderror=yes kfpu=no heapchk=yes hz=1000 hhz=1000 "
        /*"rfsmap=/:/dev/ram"*/ "rfsmap=/boot:/media/sdcard0,/:/media/sdcard1");
                                                                    /*  操作系统启动参数设置        */
  • /boot:/media/sdcard0:表示将根文件系统的/boot目录挂载在/media/sdcard0位置,这个位置一般都是sd卡fat分区挂载的位置,里面存放sylixos的bin镜像,从而让uboot能从fat分区加载SylixOS镜像并启动。
  • /:/media/sdcard1:表示将根文件系统挂载在/media/sdcard1位置,这个位置一般都是sd卡tps分区挂载的位置,里面存放系统程序、库、用户程序等。

最后在 halDevInit 中调用 sdDevCreate 创建和初始化sd卡设备:

static VOID  halDevInit (VOID)
{
    /*
     *  创建根文件系统时, 将自动创建 dev, mnt, var 目录.
     */
    rootFsDevCreate();                                                  /*  创建根文件系统              */
#if LW_CFG_PROCFS_EN > 0
    procFsDevCreate();                                                  /*  创建 proc 文件系统          */
#endif                                                                  /*  LW_CFG_PROCFS_EN > 0        */
#if LW_CFG_SHM_DEVICE_EN > 0
    shmDevCreate();                                                     /*  创建共享内存设备            */
#endif                                                                  /*  LW_CFG_SHM_DEVICE_EN > 0    */
    randDevCreate();                                                    /*  创建随机数文件              */

    /*
     * TODO: 加入你的处理代码, 参考代码如下:
     */
#if 1                                                                   /*  参考代码开始                */
    SIO_CHAN    *psio0 = uartSioChanCreate();                           /*  创建串口 0 通道             */
    ttyDevCreate("/dev/ttyS0", psio0, 512, 512);                        /*  add    tty   device         */
#endif                                                                   /*  参考代码结束                */

    sdDevCreate();

#if LW_CFG_YAFFS_EN > 0
    yaffsDevCreate("/yaffs2");                                          /*  create yaffs device(only fs)*/
#endif                                                                  /*  LW_CFG_YAFFS_EN > 0         */
}

2. 分区和格式化

重新编译BSP,重启开发板并分区和格式化SD卡,在SylixOS下如何分区和格式化参见http://www.databusworld.cn/9935.html。我们这里需要将SD卡分成三个区,第一个保留区域,因为里面有uboot,不能被新数据覆盖,第二个fat分区,第三个tps分区,如下所示:

全志D1开发(十)SD驱动之挂载根文件系统

这里我将保留分区和fat分区各分100MB,剩下空间全部给tps分区。再次重启开发板,启动系统后如果看到以下信息说明sd卡初始化和根文件系统挂载基本没问题了:

全志D1开发(十)SD驱动之挂载根文件系统

一般如果文件系统挂载有问题的话,在命令行前面的root会变成unknow,通过这个可以快速的判断文件系统是否正常挂载了。

3. SD验证

存储类驱动开发完成后,可以通过几个简单的测试来初步验证驱动是否正常,下面一一介绍。

3.1 查看挂载信息

通过showmount命令查看设备各个分区的挂载位置:

全志D1开发(十)SD驱动之挂载根文件系统

可以看出sd卡的第二个分区也就是fat分区挂载在/media/sdcard0位置,第三个分区也就是tps分区挂载在/media/sdcard1位置。

到根目录下通过ll命令也可以查看各个目录的挂载位置:

全志D1开发(十)SD驱动之挂载根文件系统

3.2 中断信息

如果驱动采用了DMA描述符方式来传输数据,一般都会配合中断来工作的,那么就可以通过ints命令查看驱动的中断次数来确定驱动是否在工作,但是由于本次驱动我们采用的cpu轮询读写fifo,并没有使用中断,所以这种方法失效。

3.3 读写文件

进入apps目录下,通过以下几个步骤快速验证读写文件是否正常:

  • 通过touch命令创建一个新的空文件。
  • 使用ll命令查看该文件信息。
  • 通过echo命令将一段字符串写入新文件中。
  • 再次使用ll命令查看该文件信息,主要是文件大小是否变化。
  • 使用cat命令查看改文件内容,确认是否是刚才写入到文件中的字符串。

全志D1开发(十)SD驱动之挂载根文件系统

如果一切正常的话,cat出来的内容和echo写进去的内容应该是一样的。

3.4 速度测试

简单快速的读写速度测试可以使用base编译出的dd工具,这个工具和linux下的dd作用类似,但是由于我们还没有做好网络驱动,所以我们需要将sd卡插到电脑上并dd程序复制到fat分区中:

全志D1开发(十)SD驱动之挂载根文件系统

如上图所示,将libsylixos下编译出来的dd和libvpmpdm.so这两个文件复制到sd卡fat分区,然后将sd卡插回开发板重启启动。启动后进入/boot目录,通过如下命令测试fat分区写速度:

/boot/dd if=/dev/zero of=testw.dbf2 bs=1M count=10

通过如下命令测试fat分区读速度:

/boot/dd if=testw.dbf2 of=/dev/null bs=1M count=10

测试结果如下所示:

全志D1开发(十)SD驱动之挂载根文件系统

测试tps分区速度之前首先通过cp命令将libvpmpdm.so复制到/lib目录下,然后进入到apps目录下,同样的操作测试tps分区的读写速度:

全志D1开发(十)SD驱动之挂载根文件系统

到底为止,一个简单的sd驱动我们就完成了,在实际的测试中,一般还配合iozone来更详细的测试驱动在不同条件下的读写速度。带sd驱动的最小系统源码可以在这里下载:https://pan.baidu.com/s/1DqcgPGlN4byx2PERATukaA?pwd=kfh9

gewenbin
  • 本文由 发表于 2022年5月3日18:07:49
  • 转载请务必保留本文链接:http://www.databusworld.cn/10702.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

评论:1   其中:访客  1   博主  0
    • vector vector 0

      板子全志d1,sd卡挂载后unknow,代码是链接最后的提供的那个,问题出在哪呢