From 8cb78e0e5356134e9313e745667297d6b9dc46ed Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Mon, 15 Feb 2016 00:08:37 +0200 Subject: extmod/vfs_fat_diskio: Reusable FatFs module, move from stmhal/diskio. --- extmod/vfs_fat_diskio.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++++ py/py.mk | 1 + stmhal/Makefile | 1 - stmhal/diskio.c | 250 ----------------------------------------------- unix/Makefile | 1 - 5 files changed, 256 insertions(+), 252 deletions(-) create mode 100644 extmod/vfs_fat_diskio.c delete mode 100644 stmhal/diskio.c diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c new file mode 100644 index 000000000..7acdc8297 --- /dev/null +++ b/extmod/vfs_fat_diskio.c @@ -0,0 +1,255 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * Original template for this file comes from: + * Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013 + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpconfig.h" +#if MICROPY_FSUSERMOUNT + +#include +#include + +#include "py/mphal.h" + +#include "py/runtime.h" +#include "lib/fatfs/ff.h" /* FatFs lower layer API */ +#include "lib/fatfs/diskio.h" /* FatFs lower layer API */ +#include "extmod/fsusermount.h" + +STATIC fs_user_mount_t *disk_get_device(uint id) { + if (id < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) { + return MP_STATE_PORT(fs_user_mount)[id]; + } else { + return NULL; + } +} + +/*-----------------------------------------------------------------------*/ +/* Initialize a Drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE pdrv /* Physical drive nmuber (0..) */ +) +{ + fs_user_mount_t *vfs = disk_get_device(pdrv); + if (vfs == NULL) { + return STA_NOINIT; + } + + if (vfs->flags & FSUSER_HAVE_IOCTL) { + // new protocol with ioctl; call ioctl(INIT, 0) + vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_INIT); + vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused + mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); + if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { + // error initialising + return STA_NOINIT; + } + } + + if (vfs->writeblocks[0] == MP_OBJ_NULL) { + return STA_PROTECT; + } else { + return 0; + } +} + +/*-----------------------------------------------------------------------*/ +/* Get Disk Status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE pdrv /* Physical drive nmuber (0..) */ +) +{ + fs_user_mount_t *vfs = disk_get_device(pdrv); + if (vfs == NULL) { + return STA_NOINIT; + } + + if (vfs->writeblocks[0] == MP_OBJ_NULL) { + return STA_PROTECT; + } else { + return 0; + } +} + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address (LBA) */ + UINT count /* Number of sectors to read (1..128) */ +) +{ + fs_user_mount_t *vfs = disk_get_device(pdrv); + if (vfs == NULL) { + return RES_PARERR; + } + + if (vfs->flags & FSUSER_NATIVE) { + mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2]; + if (f(buff, sector, count) != 0) { + return RES_ERROR; + } + } else { + vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); + vfs->readblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, buff); + mp_call_method_n_kw(2, 0, vfs->readblocks); + // TODO handle error return + } + + return RES_OK; +} + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ + +#if _USE_WRITE +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address (LBA) */ + UINT count /* Number of sectors to write (1..128) */ +) +{ + fs_user_mount_t *vfs = disk_get_device(pdrv); + if (vfs == NULL) { + return RES_PARERR; + } + + if (vfs->writeblocks[0] == MP_OBJ_NULL) { + // read-only block device + return RES_WRPRT; + } + + if (vfs->flags & FSUSER_NATIVE) { + mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2]; + if (f(buff, sector, count) != 0) { + return RES_ERROR; + } + } else { + vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); + vfs->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, (void*)buff); + mp_call_method_n_kw(2, 0, vfs->writeblocks); + // TODO handle error return + } + + return RES_OK; +} +#endif + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +#if _USE_IOCTL +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + fs_user_mount_t *vfs = disk_get_device(pdrv); + if (vfs == NULL) { + return RES_PARERR; + } + + if (vfs->flags & FSUSER_HAVE_IOCTL) { + // new protocol with ioctl + switch (cmd) { + case CTRL_SYNC: + vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SYNC); + vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused + mp_call_method_n_kw(2, 0, vfs->u.ioctl); + return RES_OK; + + case GET_SECTOR_COUNT: { + vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_COUNT); + vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused + mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); + *((DWORD*)buff) = mp_obj_get_int(ret); + return RES_OK; + } + + case GET_SECTOR_SIZE: { + vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_SIZE); + vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused + mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); + if (ret == mp_const_none) { + // Default sector size + *((WORD*)buff) = 512; + } else { + *((WORD*)buff) = mp_obj_get_int(ret); + } + return RES_OK; + } + + case GET_BLOCK_SIZE: + *((DWORD*)buff) = 1; // erase block size in units of sector size + return RES_OK; + + default: + return RES_PARERR; + } + } else { + // old protocol with sync and count + switch (cmd) { + case CTRL_SYNC: + if (vfs->u.old.sync[0] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, vfs->u.old.sync); + } + return RES_OK; + + case GET_SECTOR_COUNT: { + mp_obj_t ret = mp_call_method_n_kw(0, 0, vfs->u.old.count); + *((DWORD*)buff) = mp_obj_get_int(ret); + return RES_OK; + } + + case GET_SECTOR_SIZE: + *((WORD*)buff) = 512; // old protocol had fixed sector size + return RES_OK; + + case GET_BLOCK_SIZE: + *((DWORD*)buff) = 1; // erase block size in units of sector size + return RES_OK; + + default: + return RES_PARERR; + } + } +} +#endif + +#endif // MICROPY_FSUSERMOUNT diff --git a/py/py.mk b/py/py.mk index 61faf0892..9391bbdfb 100644 --- a/py/py.mk +++ b/py/py.mk @@ -171,6 +171,7 @@ PY_O_BASENAME = \ ../extmod/modurandom.o \ ../extmod/fsusermount.o \ ../extmod/vfs_fat.o \ + ../extmod/vfs_fat_diskio.o \ ../extmod/moduos_dupterm.o \ # prepend the build destination prefix to the py object files diff --git a/stmhal/Makefile b/stmhal/Makefile index 3cad7d1da..cd565a6f4 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -156,7 +156,6 @@ SRC_C = \ file.c \ builtin_open.c \ sdcard.c \ - diskio.c \ fatfs_port.c \ ffconf.c \ lcd.c \ diff --git a/stmhal/diskio.c b/stmhal/diskio.c deleted file mode 100644 index 03be24188..000000000 --- a/stmhal/diskio.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * Original template for this file comes from: - * Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013 - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "py/mphal.h" - -#include "py/runtime.h" -#include "lib/fatfs/ff.h" /* FatFs lower layer API */ -#include "lib/fatfs/diskio.h" /* FatFs lower layer API */ -#include "extmod/fsusermount.h" - -STATIC fs_user_mount_t *disk_get_device(uint id) { - if (id < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) { - return MP_STATE_PORT(fs_user_mount)[id]; - } else { - return NULL; - } -} - -/*-----------------------------------------------------------------------*/ -/* Initialize a Drive */ -/*-----------------------------------------------------------------------*/ - -DSTATUS disk_initialize ( - BYTE pdrv /* Physical drive nmuber (0..) */ -) -{ - fs_user_mount_t *vfs = disk_get_device(pdrv); - if (vfs == NULL) { - return STA_NOINIT; - } - - if (vfs->flags & FSUSER_HAVE_IOCTL) { - // new protocol with ioctl; call ioctl(INIT, 0) - vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_INIT); - vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); - if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { - // error initialising - return STA_NOINIT; - } - } - - if (vfs->writeblocks[0] == MP_OBJ_NULL) { - return STA_PROTECT; - } else { - return 0; - } -} - -/*-----------------------------------------------------------------------*/ -/* Get Disk Status */ -/*-----------------------------------------------------------------------*/ - -DSTATUS disk_status ( - BYTE pdrv /* Physical drive nmuber (0..) */ -) -{ - fs_user_mount_t *vfs = disk_get_device(pdrv); - if (vfs == NULL) { - return STA_NOINIT; - } - - if (vfs->writeblocks[0] == MP_OBJ_NULL) { - return STA_PROTECT; - } else { - return 0; - } -} - -/*-----------------------------------------------------------------------*/ -/* Read Sector(s) */ -/*-----------------------------------------------------------------------*/ - -DRESULT disk_read ( - BYTE pdrv, /* Physical drive nmuber (0..) */ - BYTE *buff, /* Data buffer to store read data */ - DWORD sector, /* Sector address (LBA) */ - UINT count /* Number of sectors to read (1..128) */ -) -{ - fs_user_mount_t *vfs = disk_get_device(pdrv); - if (vfs == NULL) { - return RES_PARERR; - } - - if (vfs->flags & FSUSER_NATIVE) { - mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2]; - if (f(buff, sector, count) != 0) { - return RES_ERROR; - } - } else { - vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->readblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, buff); - mp_call_method_n_kw(2, 0, vfs->readblocks); - // TODO handle error return - } - - return RES_OK; -} - -/*-----------------------------------------------------------------------*/ -/* Write Sector(s) */ -/*-----------------------------------------------------------------------*/ - -#if _USE_WRITE -DRESULT disk_write ( - BYTE pdrv, /* Physical drive nmuber (0..) */ - const BYTE *buff, /* Data to be written */ - DWORD sector, /* Sector address (LBA) */ - UINT count /* Number of sectors to write (1..128) */ -) -{ - fs_user_mount_t *vfs = disk_get_device(pdrv); - if (vfs == NULL) { - return RES_PARERR; - } - - if (vfs->writeblocks[0] == MP_OBJ_NULL) { - // read-only block device - return RES_WRPRT; - } - - if (vfs->flags & FSUSER_NATIVE) { - mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2]; - if (f(buff, sector, count) != 0) { - return RES_ERROR; - } - } else { - vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, (void*)buff); - mp_call_method_n_kw(2, 0, vfs->writeblocks); - // TODO handle error return - } - - return RES_OK; -} -#endif - - -/*-----------------------------------------------------------------------*/ -/* Miscellaneous Functions */ -/*-----------------------------------------------------------------------*/ - -#if _USE_IOCTL -DRESULT disk_ioctl ( - BYTE pdrv, /* Physical drive nmuber (0..) */ - BYTE cmd, /* Control code */ - void *buff /* Buffer to send/receive control data */ -) -{ - fs_user_mount_t *vfs = disk_get_device(pdrv); - if (vfs == NULL) { - return RES_PARERR; - } - - if (vfs->flags & FSUSER_HAVE_IOCTL) { - // new protocol with ioctl - switch (cmd) { - case CTRL_SYNC: - vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SYNC); - vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - mp_call_method_n_kw(2, 0, vfs->u.ioctl); - return RES_OK; - - case GET_SECTOR_COUNT: { - vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_COUNT); - vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); - *((DWORD*)buff) = mp_obj_get_int(ret); - return RES_OK; - } - - case GET_SECTOR_SIZE: { - vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_SIZE); - vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - mp_obj_t ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); - if (ret == mp_const_none) { - // Default sector size - *((WORD*)buff) = 512; - } else { - *((WORD*)buff) = mp_obj_get_int(ret); - } - return RES_OK; - } - - case GET_BLOCK_SIZE: - *((DWORD*)buff) = 1; // erase block size in units of sector size - return RES_OK; - - default: - return RES_PARERR; - } - } else { - // old protocol with sync and count - switch (cmd) { - case CTRL_SYNC: - if (vfs->u.old.sync[0] != MP_OBJ_NULL) { - mp_call_method_n_kw(0, 0, vfs->u.old.sync); - } - return RES_OK; - - case GET_SECTOR_COUNT: { - mp_obj_t ret = mp_call_method_n_kw(0, 0, vfs->u.old.count); - *((DWORD*)buff) = mp_obj_get_int(ret); - return RES_OK; - } - - case GET_SECTOR_SIZE: - *((WORD*)buff) = 512; // old protocol had fixed sector size - return RES_OK; - - case GET_BLOCK_SIZE: - *((DWORD*)buff) = 1; // erase block size in units of sector size - return RES_OK; - - default: - return RES_PARERR; - } - } -} -#endif diff --git a/unix/Makefile b/unix/Makefile index 42f0edf81..342786deb 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -148,7 +148,6 @@ SRC_C = \ $(SRC_MOD) STMHAL_SRC_C = \ - stmhal/diskio.c \ stmhal/ffconf.c \ stmhal/file.c -- cgit v1.2.3