summaryrefslogtreecommitdiff
path: root/stmhal/diskio.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2016-02-10 16:32:57 +0000
committerDamien George <damien.p.george@gmail.com>2016-02-10 23:40:10 +0000
commitb33a7705966a743c5e4c0c3c3bb83e6d97b5e84d (patch)
tree2c62a5389a7f0189119b5fcbbb9b30f0ff5b9db5 /stmhal/diskio.c
parent34023eb673d5356bb4eb6fc635d6d48eefb35135 (diff)
extmod/fsusermount: Support mounting of multiple block devices.
This patch adds support to fsusermount for multiple block devices (instead of just one). The maximum allowed is fixed at compile time by the size of the fs_user_mount array accessed via MP_STATE_PORT, which in turn is set by MICROPY_FATFS_VOLUMES. With this patch, stmhal (which is still tightly coupled to fsusermount) is also modified to support mounting multiple devices And the flash and SD card are now just two block devices that are mounted at start up if they exist (and they have special native code to make them more efficient).
Diffstat (limited to 'stmhal/diskio.c')
-rw-r--r--stmhal/diskio.c322
1 files changed, 127 insertions, 195 deletions
diff --git a/stmhal/diskio.c b/stmhal/diskio.c
index 9a4efd1a4..998729a70 100644
--- a/stmhal/diskio.c
+++ b/stmhal/diskio.c
@@ -35,17 +35,23 @@
#include "py/runtime.h"
#include "lib/fatfs/ff.h" /* FatFs lower layer API */
#include "lib/fatfs/diskio.h" /* FatFs lower layer API */
-#include "storage.h"
-#include "sdcard.h"
#include "extmod/fsusermount.h"
// constants for block protocol ioctl
-//#define BP_IOCTL_INIT (1) // unused
+#define BP_IOCTL_INIT (1)
//#define BP_IOCTL_DEINIT (2) // unused
#define BP_IOCTL_SYNC (3)
#define BP_IOCTL_SEC_COUNT (4)
#define BP_IOCTL_SEC_SIZE (5)
+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 */
/*-----------------------------------------------------------------------*/
@@ -54,33 +60,27 @@ DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
- switch (pdrv) {
-#if MICROPY_HW_HAS_FLASH
- case PD_FLASH:
- storage_init();
- return 0;
-#endif
-
-#if MICROPY_HW_HAS_SDCARD
- case PD_SDCARD:
- if (!sdcard_power_on()) {
- return STA_NODISK;
- }
- // TODO return STA_PROTECT if SD card is read only
- return 0;
-#endif
+ fs_user_mount_t *vfs = disk_get_device(pdrv);
+ if (vfs == NULL) {
+ return STA_NOINIT;
+ }
- case PD_USER:
- if (MP_STATE_PORT(fs_user_mount) == NULL) {
- return STA_NODISK;
- }
- if (MP_STATE_PORT(fs_user_mount)->writeblocks[0] == MP_OBJ_NULL) {
- return STA_PROTECT;
- }
- return 0;
+ 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 (MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
+ // error initialising
+ return STA_NOINIT;
+ }
}
- return STA_NOINIT;
+ if (vfs->writeblocks[0] == MP_OBJ_NULL) {
+ return STA_PROTECT;
+ } else {
+ return 0;
+ }
}
/*-----------------------------------------------------------------------*/
@@ -91,28 +91,16 @@ DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
- switch (pdrv) {
- case PD_FLASH :
- // flash is ready
- return 0;
-
-#if MICROPY_HW_HAS_SDCARD
- case PD_SDCARD:
- // TODO return STA_PROTECT if SD card is read only
- return 0;
-#endif
-
- case PD_USER:
- if (MP_STATE_PORT(fs_user_mount) == NULL) {
- return STA_NODISK;
- }
- if (MP_STATE_PORT(fs_user_mount)->writeblocks[0] == MP_OBJ_NULL) {
- return STA_PROTECT;
- }
- return 0;
+ fs_user_mount_t *vfs = disk_get_device(pdrv);
+ if (vfs == NULL) {
+ return STA_NOINIT;
}
- return STA_NOINIT;
+ if (vfs->writeblocks[0] == MP_OBJ_NULL) {
+ return STA_PROTECT;
+ } else {
+ return 0;
+ }
}
/*-----------------------------------------------------------------------*/
@@ -126,37 +114,24 @@ DRESULT disk_read (
UINT count /* Number of sectors to read (1..128) */
)
{
- switch (pdrv) {
-#if MICROPY_HW_HAS_FLASH
- case PD_FLASH:
- for (int i = 0; i < count; i++) {
- if (!storage_read_block(buff + i * FLASH_BLOCK_SIZE, sector + i)) {
- return RES_ERROR;
- }
- }
- return RES_OK;
-#endif
-
-#if MICROPY_HW_HAS_SDCARD
- case PD_SDCARD:
- if (sdcard_read_blocks(buff, sector, count) != 0) {
- return RES_ERROR;
- }
- return RES_OK;
-#endif
+ fs_user_mount_t *vfs = disk_get_device(pdrv);
+ if (vfs == NULL) {
+ return RES_PARERR;
+ }
- case PD_USER:
- if (MP_STATE_PORT(fs_user_mount) == NULL) {
- // nothing mounted
- return RES_ERROR;
- }
- MP_STATE_PORT(fs_user_mount)->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
- MP_STATE_PORT(fs_user_mount)->readblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, buff);
- mp_call_method_n_kw(2, 0, MP_STATE_PORT(fs_user_mount)->readblocks);
- return RES_OK;
+ if (vfs->flags & FSUSER_NATIVE) {
+ mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)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_PARERR;
+ return RES_OK;
}
/*-----------------------------------------------------------------------*/
@@ -171,41 +146,29 @@ DRESULT disk_write (
UINT count /* Number of sectors to write (1..128) */
)
{
- switch (pdrv) {
-#if MICROPY_HW_HAS_FLASH
- case PD_FLASH:
- for (int i = 0; i < count; i++) {
- if (!storage_write_block(buff + i * FLASH_BLOCK_SIZE, sector + i)) {
- return RES_ERROR;
- }
- }
- return RES_OK;
-#endif
+ fs_user_mount_t *vfs = disk_get_device(pdrv);
+ if (vfs == NULL) {
+ return RES_PARERR;
+ }
-#if MICROPY_HW_HAS_SDCARD
- case PD_SDCARD:
- if (sdcard_write_blocks(buff, sector, count) != 0) {
- return RES_ERROR;
- }
- return RES_OK;
-#endif
+ if (vfs->writeblocks[0] == MP_OBJ_NULL) {
+ // read-only block device
+ return RES_WRPRT;
+ }
- case PD_USER:
- if (MP_STATE_PORT(fs_user_mount) == NULL) {
- // nothing mounted
- return RES_ERROR;
- }
- if (MP_STATE_PORT(fs_user_mount)->writeblocks[0] == MP_OBJ_NULL) {
- // read-only block device
- return RES_ERROR;
- }
- MP_STATE_PORT(fs_user_mount)->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
- MP_STATE_PORT(fs_user_mount)->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, (void*)buff);
- mp_call_method_n_kw(2, 0, MP_STATE_PORT(fs_user_mount)->writeblocks);
- return RES_OK;
+ if (vfs->flags & FSUSER_NATIVE) {
+ mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)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_PARERR;
+ return RES_OK;
}
#endif
@@ -221,100 +184,69 @@ DRESULT disk_ioctl (
void *buff /* Buffer to send/receive control data */
)
{
- switch (pdrv) {
-#if MICROPY_HW_HAS_FLASH
- case PD_FLASH:
- switch (cmd) {
- case CTRL_SYNC:
- storage_flush();
- return RES_OK;
-
- case GET_BLOCK_SIZE:
- *((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) block size
- return RES_OK;
- }
- break;
-#endif
+ fs_user_mount_t *vfs = disk_get_device(pdrv);
+ if (vfs == NULL) {
+ return RES_PARERR;
+ }
-#if MICROPY_HW_HAS_SDCARD
- case PD_SDCARD:
- switch (cmd) {
- case CTRL_SYNC:
- return RES_OK;
+ 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);
+ *((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_BLOCK_SIZE:
- *((DWORD*)buff) = 1; // high-level sector erase size in units of the small (512) block size
- 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;
}
- break;
-#endif
- case PD_USER: {
- fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount);
- if (vfs == NULL) {
- // nothing mounted
- return RES_ERROR;
- }
- if (vfs->u.old.count[1] == MP_OBJ_SENTINEL) {
- // 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);
- vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
- 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);
- vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
- 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);
- *((WORD*)buff) = mp_obj_get_int(ret);
- vfs->u.ioctl[3] = MP_OBJ_SENTINEL; // indicate new protocol
- return RES_OK;
- }
-
- case GET_BLOCK_SIZE:
- *((DWORD*)buff) = 1; // erase block size in units of sector size
- return RES_OK;
- }
- } 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;
- }
- }
- break;
+ 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;
}
}
-
- return RES_PARERR;
}
#endif