summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott@chickadee.tech>2016-10-13 14:53:31 -0700
committerScott Shawcroft <scott@chickadee.tech>2016-10-21 15:36:59 -0700
commit306c921ed1437fc79423958a5e4bd8b0e96bc863 (patch)
tree634189a017a0fb428b21755c528548415f4ffbcf
parent6fe8c7b32c04e8c0b1ad8618920e241430634ad2 (diff)
atmel-samd: Rework mass storage interaction with underlying block
storage to use micropython's VFS interface. This makes mass storage work with any VFS implementation rather than a single one.
-rw-r--r--atmel-samd/Makefile4
-rw-r--r--atmel-samd/access_vfs.c (renamed from atmel-samd/rom_fs.c)58
-rw-r--r--atmel-samd/access_vfs.h (renamed from atmel-samd/rom_fs.h)17
-rw-r--r--atmel-samd/boards/arduino_zero/conf_access.h18
-rw-r--r--atmel-samd/boards/arduino_zero/mpconfigboard.mk2
-rw-r--r--atmel-samd/boards/feather_m0_basic/mpconfigboard.mk2
-rw-r--r--atmel-samd/internal_flash.c (renamed from atmel-samd/storage.c)118
-rw-r--r--atmel-samd/internal_flash.h53
-rw-r--r--atmel-samd/main.c3
-rw-r--r--atmel-samd/modmachine.c2
-rw-r--r--atmel-samd/mpconfigport.h2
-rw-r--r--atmel-samd/spi_flash.c299
-rw-r--r--atmel-samd/spi_flash.h (renamed from atmel-samd/storage.h)32
-rw-r--r--extmod/fsusermount.h3
-rw-r--r--extmod/vfs_fat_diskio.c4
15 files changed, 506 insertions, 111 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile
index 5d3af6e39..fbdfa3f93 100644
--- a/atmel-samd/Makefile
+++ b/atmel-samd/Makefile
@@ -143,6 +143,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
)
SRC_C = \
+ access_vfs.c \
builtin_open.c \
fatfs_port.c \
main.c \
@@ -156,9 +157,8 @@ SRC_C = \
modutime.c \
mphalport.c \
pin_named_pins.c \
- rom_fs.c \
samdneopixel.c \
- storage.c \
+ $(FLASH_IMPL) \
asf/common/services/sleepmgr/samd/sleepmgr.c \
asf/common/services/storage/ctrl_access/ctrl_access.c \
asf/common/services/usb/class/cdc/device/udi_cdc.c \
diff --git a/atmel-samd/rom_fs.c b/atmel-samd/access_vfs.c
index f0b01fa6b..a3e8aaebc 100644
--- a/atmel-samd/rom_fs.c
+++ b/atmel-samd/access_vfs.c
@@ -24,10 +24,16 @@
* THE SOFTWARE.
*/
-#include "rom_fs.h"
+#include "access_vfs.h"
#include "asf/common/services/usb/class/msc/device/udi_msc.h"
-#include "storage.h"
+#include "extmod/fsusermount.h"
+#include "lib/fatfs/diskio.h"
+#include "py/mpconfig.h"
+#include "py/mpstate.h"
+#include "py/misc.h"
+
+#define VFS_INDEX 0
//! This function tests memory state, and starts memory initialization
//! @return Ctrl_status
@@ -35,9 +41,17 @@
//! Memory unplug -> CTRL_NO_PRESENT
//! Not initialized or changed -> CTRL_BUSY
//! An error occurred -> CTRL_FAIL
-Ctrl_status rom_fs_test_unit_ready(void)
+Ctrl_status vfs_test_unit_ready(void)
{
- return CTRL_GOOD;
+ if (VFS_INDEX >= MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
+ return CTRL_FAIL;
+ }
+ DSTATUS status = disk_status(VFS_INDEX);
+ if (status == STA_NOINIT) {
+ return CTRL_NO_PRESENT;
+ }
+
+ return CTRL_GOOD;
}
//! This function returns the address of the last valid sector
@@ -47,9 +61,11 @@ Ctrl_status rom_fs_test_unit_ready(void)
//! Memory unplug -> CTRL_NO_PRESENT
//! Not initialized or changed -> CTRL_BUSY
//! An error occurred -> CTRL_FAIL
-Ctrl_status rom_fs_read_capacity(uint32_t *uint32_t_nb_sector)
+Ctrl_status vfs_read_capacity(uint32_t *uint32_t_nb_sector)
{
- *uint32_t_nb_sector = storage_get_block_count();
+ if (disk_ioctl(VFS_INDEX, GET_SECTOR_COUNT, uint32_t_nb_sector) != RES_OK) {
+ return CTRL_FAIL;
+ }
return CTRL_GOOD;
}
@@ -57,20 +73,26 @@ Ctrl_status rom_fs_read_capacity(uint32_t *uint32_t_nb_sector)
//!
//! @return true if the memory is protected
//!
-bool rom_fs_wr_protect(void)
+bool vfs_wr_protect(void)
{
- return false;
+ DSTATUS status = disk_status(VFS_INDEX);
+ return status == STA_NOINIT || status == STA_PROTECT;
}
//! This function informs about the memory type
//!
//! @return true if the memory is removable
//!
-bool rom_fs_removal(void)
+bool vfs_removal(void)
{
return true;
}
+bool vfs_unload(bool unload)
+{
+ return unload;
+}
+
// TODO(tannewt): Transfer more than a single sector at a time if we need more
// speed.
//! This function transfers the memory data to the USB MSC interface
@@ -84,11 +106,17 @@ bool rom_fs_removal(void)
//! Not initialized or changed -> CTRL_BUSY
//! An error occurred -> CTRL_FAIL
//!
-Ctrl_status rom_fs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
+Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
{
uint8_t sector_buffer[FLASH_BLOCK_SIZE];
for (uint16_t sector = 0; sector < nb_sector; sector++) {
- storage_read_block(sector_buffer, addr + sector);
+ DRESULT result = disk_read(VFS_INDEX, sector_buffer, addr + sector, 1);
+ if (result == RES_PARERR) {
+ return CTRL_NO_PRESENT;
+ }
+ if (result == RES_ERROR) {
+ return CTRL_FAIL;
+ }
if (!udi_msc_trans_block(true, sector_buffer, FLASH_BLOCK_SIZE, NULL)) {
return CTRL_FAIL; // transfer aborted
}
@@ -108,14 +136,18 @@ Ctrl_status rom_fs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
//! Not initialized or changed -> CTRL_BUSY
//! An error occurred -> CTRL_FAIL
//!
-Ctrl_status rom_fs_usb_write_10(uint32_t addr, uint16_t nb_sector)
+Ctrl_status vfs_usb_write_10(uint32_t addr, uint16_t nb_sector)
{
uint8_t sector_buffer[FLASH_BLOCK_SIZE];
for (uint16_t sector = 0; sector < nb_sector; sector++) {
if (!udi_msc_trans_block(false, sector_buffer, FLASH_BLOCK_SIZE, NULL)) {
return CTRL_FAIL; // transfer aborted
}
- if (!storage_write_block(sector_buffer, addr + sector)) {
+ DRESULT result = disk_write(VFS_INDEX, sector_buffer, addr + sector, 1);
+ if (result == RES_PARERR) {
+ return CTRL_NO_PRESENT;
+ }
+ if (result == RES_ERROR) {
return CTRL_FAIL;
}
}
diff --git a/atmel-samd/rom_fs.h b/atmel-samd/access_vfs.h
index 8b1fe2de9..07af89e22 100644
--- a/atmel-samd/rom_fs.h
+++ b/atmel-samd/access_vfs.h
@@ -24,17 +24,20 @@
* THE SOFTWARE.
*/
+// This adapts the ASF access API to MicroPython's VFS API so we can expose all
+// VFS block devices as Lun's over USB mass storage control.
+
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_ROM_FS_H__
#define __MICROPY_INCLUDED_ATMEL_SAMD_ROM_FS_H__
#include "asf/common/services/storage/ctrl_access/ctrl_access.h"
-
-Ctrl_status rom_fs_test_unit_ready(void);
-Ctrl_status rom_fs_read_capacity(uint32_t *u32_nb_sector);
-bool rom_fs_wr_protect(void);
-bool rom_fs_removal(void);
-Ctrl_status rom_fs_usb_read_10(uint32_t addr, uint16_t nb_sector);
-Ctrl_status rom_fs_usb_write_10(uint32_t addr, uint16_t nb_sector);
+Ctrl_status vfs_test_unit_ready(void);
+Ctrl_status vfs_read_capacity(uint32_t *u32_nb_sector);
+bool vfs_wr_protect(void);
+bool vfs_removal(void);
+bool vfs_unload(bool);
+Ctrl_status vfs_usb_read_10(uint32_t addr, uint16_t nb_sector);
+Ctrl_status vfs_usb_write_10(uint32_t addr, uint16_t nb_sector);
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_ROM_FS_H__
diff --git a/atmel-samd/boards/arduino_zero/conf_access.h b/atmel-samd/boards/arduino_zero/conf_access.h
index 8cf104e69..25109b75c 100644
--- a/atmel-samd/boards/arduino_zero/conf_access.h
+++ b/atmel-samd/boards/arduino_zero/conf_access.h
@@ -68,15 +68,15 @@
/*! \name LUN 0 Definitions
*/
//! @{
-#define LUN_0_INCLUDE "rom_fs.h"
-#define Lun_0_test_unit_ready rom_fs_test_unit_ready
-#define Lun_0_read_capacity rom_fs_read_capacity
-#define Lun_0_unload NULL /* Can not be unloaded */
-#define Lun_0_wr_protect rom_fs_wr_protect
-#define Lun_0_removal rom_fs_removal
-#define Lun_0_usb_read_10 rom_fs_usb_read_10
-#define Lun_0_usb_write_10 rom_fs_usb_write_10
-#define LUN_0_NAME "\"On-Chip ROM\""
+#define LUN_0_INCLUDE "access_vfs.h"
+#define Lun_0_test_unit_ready vfs_test_unit_ready
+#define Lun_0_read_capacity vfs_read_capacity
+#define Lun_0_unload NULL
+#define Lun_0_wr_protect vfs_wr_protect
+#define Lun_0_removal vfs_removal
+#define Lun_0_usb_read_10 vfs_usb_read_10
+#define Lun_0_usb_write_10 vfs_usb_write_10
+#define LUN_0_NAME "\"MicroPython VFS[0]\""
//! @}
#define MEM_USB LUN_USB
diff --git a/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/atmel-samd/boards/arduino_zero/mpconfigboard.mk
index 1b9956932..848b9fca3 100644
--- a/atmel-samd/boards/arduino_zero/mpconfigboard.mk
+++ b/atmel-samd/boards/arduino_zero/mpconfigboard.mk
@@ -1,3 +1,5 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x2341
USB_PID = 0x824D
+
+FLASH_IMPL = internal_flash.c
diff --git a/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
index d7f5c739b..2b5c263ac 100644
--- a/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
+++ b/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
@@ -1,3 +1,5 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x8015
+
+FLASH_IMPL = internal_flash.c
diff --git a/atmel-samd/storage.c b/atmel-samd/internal_flash.c
index a4037da4f..f7d0aea6c 100644
--- a/atmel-samd/storage.c
+++ b/atmel-samd/internal_flash.c
@@ -34,35 +34,35 @@
#include "asf/sam0/drivers/nvm/nvm.h"
-#include "storage.h"
+#include "internal_flash.h"
-#define TOTAL_FLASH_SIZE 0x010000
+#define TOTAL_INTERNAL_FLASH_SIZE 0x010000
-#define FLASH_MEM_SEG1_START_ADDR (0x00040000 - TOTAL_FLASH_SIZE)
-#define FLASH_PART1_START_BLOCK (0x100)
-#define FLASH_PART1_NUM_BLOCKS (TOTAL_FLASH_SIZE / FLASH_BLOCK_SIZE)
+#define INTERNAL_FLASH_MEM_SEG1_START_ADDR (0x00040000 - TOTAL_INTERNAL_FLASH_SIZE)
+#define INTERNAL_FLASH_PART1_START_BLOCK (0x100)
+#define INTERNAL_FLASH_PART1_NUM_BLOCKS (TOTAL_INTERNAL_FLASH_SIZE / INTERNAL_FLASH_BLOCK_SIZE)
-static bool flash_is_initialised = false;
+static bool internal_flash_is_initialised = false;
-void storage_init(void) {
- if (!flash_is_initialised) {
+void internal_flash_init(void) {
+ if (!internal_flash_is_initialised) {
struct nvm_config config_nvm;
nvm_get_config_defaults(&config_nvm);
config_nvm.manual_page_write = false;
nvm_set_config(&config_nvm);
- flash_is_initialised = true;
+ internal_flash_is_initialised = true;
}
}
-uint32_t storage_get_block_size(void) {
- return FLASH_BLOCK_SIZE;
+uint32_t internal_flash_get_block_size(void) {
+ return INTERNAL_FLASH_BLOCK_SIZE;
}
-uint32_t storage_get_block_count(void) {
- return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS;
+uint32_t internal_flash_get_block_count(void) {
+ return INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS;
}
-void storage_flush(void) {
+void internal_flash_flush(void) {
}
static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) {
@@ -102,16 +102,16 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo
}
static uint32_t convert_block_to_flash_addr(uint32_t block) {
- if (FLASH_PART1_START_BLOCK <= block && block < FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) {
+ if (INTERNAL_FLASH_PART1_START_BLOCK <= block && block < INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS) {
// a block in partition 1
- block -= FLASH_PART1_START_BLOCK;
- return FLASH_MEM_SEG1_START_ADDR + block * FLASH_BLOCK_SIZE;
+ block -= INTERNAL_FLASH_PART1_START_BLOCK;
+ return INTERNAL_FLASH_MEM_SEG1_START_ADDR + block * INTERNAL_FLASH_BLOCK_SIZE;
}
// bad block
return -1;
}
-bool storage_read_block(uint8_t *dest, uint32_t block) {
+bool internal_flash_read_block(uint8_t *dest, uint32_t block) {
//printf("RD %u\n", block);
if (block == 0) {
// fake the MBR so we can decide on our own partition table
@@ -120,7 +120,7 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
dest[i] = 0;
}
- build_partition(dest + 446, 0, 0x01 /* FAT12 */, FLASH_PART1_START_BLOCK, FLASH_PART1_NUM_BLOCKS);
+ build_partition(dest + 446, 0, 0x01 /* FAT12 */, INTERNAL_FLASH_PART1_START_BLOCK, INTERNAL_FLASH_PART1_NUM_BLOCKS);
build_partition(dest + 462, 0, 0, 0, 0);
build_partition(dest + 478, 0, 0, 0, 0);
build_partition(dest + 494, 0, 0, 0, 0);
@@ -140,7 +140,7 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
enum status_code error_code;
// A block is made up of multiple pages. Read each page
// sequentially.
- for (int i = 0; i < FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) {
+ for (int i = 0; i < INTERNAL_FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) {
do
{
error_code = nvm_read_buffer(src + i * NVMCTRL_PAGE_SIZE,
@@ -152,7 +152,7 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
}
}
-bool storage_write_block(const uint8_t *src, uint32_t block) {
+bool internal_flash_write_block(const uint8_t *src, uint32_t block) {
if (block == 0) {
// can't write MBR, but pretend we did
return true;
@@ -184,7 +184,7 @@ bool storage_write_block(const uint8_t *src, uint32_t block) {
// A block is made up of multiple pages. Write each page
// sequentially.
- for (int i = 0; i < FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) {
+ for (int i = 0; i < INTERNAL_FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) {
do
{
error_code = nvm_write_buffer(dest + i * NVMCTRL_PAGE_SIZE,
@@ -199,18 +199,18 @@ bool storage_write_block(const uint8_t *src, uint32_t block) {
}
}
-mp_uint_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
+mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
for (size_t i = 0; i < num_blocks; i++) {
- if (!storage_read_block(dest + i * FLASH_BLOCK_SIZE, block_num + i)) {
+ if (!internal_flash_read_block(dest + i * INTERNAL_FLASH_BLOCK_SIZE, block_num + i)) {
return 1; // error
}
}
return 0; // success
}
-mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
+mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
for (size_t i = 0; i < num_blocks; i++) {
- if (!storage_write_block(src + i * FLASH_BLOCK_SIZE, block_num + i)) {
+ if (!internal_flash_write_block(src + i * INTERNAL_FLASH_BLOCK_SIZE, block_num + i)) {
return 1; // error
}
}
@@ -223,68 +223,68 @@ mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t
// Expose the flash as an object with the block protocol.
// there is a singleton Flash object
-STATIC const mp_obj_base_t flash_obj = {&flash_type};
+STATIC const mp_obj_base_t internal_flash_obj = {&internal_flash_type};
-STATIC mp_obj_t flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return singleton object
- return (mp_obj_t)&flash_obj;
+ return (mp_obj_t)&internal_flash_obj;
}
-STATIC mp_obj_t flash_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
+STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
- mp_uint_t ret = storage_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE);
+ mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_readblocks_obj, flash_readblocks);
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks);
-STATIC mp_obj_t flash_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
+STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
- mp_uint_t ret = storage_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE);
+ mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_writeblocks_obj, flash_writeblocks);
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks);
-STATIC mp_obj_t flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
+STATIC mp_obj_t internal_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in);
switch (cmd) {
- case BP_IOCTL_INIT: storage_init(); return MP_OBJ_NEW_SMALL_INT(0);
- case BP_IOCTL_DEINIT: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly
- case BP_IOCTL_SYNC: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0);
- case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(storage_get_block_count());
- case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(storage_get_block_size());
+ case BP_IOCTL_INIT: internal_flash_init(); return MP_OBJ_NEW_SMALL_INT(0);
+ case BP_IOCTL_DEINIT: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly
+ case BP_IOCTL_SYNC: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0);
+ case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_count());
+ case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_size());
default: return mp_const_none;
}
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_ioctl_obj, flash_ioctl);
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_ioctl_obj, internal_flash_obj_ioctl);
-STATIC const mp_map_elem_t flash_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_readblocks), (mp_obj_t)&flash_readblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_writeblocks), (mp_obj_t)&flash_writeblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&flash_ioctl_obj },
+STATIC const mp_map_elem_t internal_flash_obj_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readblocks), (mp_obj_t)&internal_flash_obj_readblocks_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_writeblocks), (mp_obj_t)&internal_flash_obj_writeblocks_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&internal_flash_obj_ioctl_obj },
};
-STATIC MP_DEFINE_CONST_DICT(flash_locals_dict, flash_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(internal_flash_obj_locals_dict, internal_flash_obj_locals_dict_table);
-const mp_obj_type_t flash_type = {
+const mp_obj_type_t internal_flash_type = {
{ &mp_type_type },
- .name = MP_QSTR_Flash,
- .make_new = flash_make_new,
- .locals_dict = (mp_obj_t)&flash_locals_dict,
+ .name = MP_QSTR_InternalFlash,
+ .make_new = internal_flash_obj_make_new,
+ .locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict,
};
void flash_init_vfs(fs_user_mount_t *vfs) {
vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
- vfs->readblocks[0] = (mp_obj_t)&flash_readblocks_obj;
- vfs->readblocks[1] = (mp_obj_t)&flash_obj;
- vfs->readblocks[2] = (mp_obj_t)storage_read_blocks; // native version
- vfs->writeblocks[0] = (mp_obj_t)&flash_writeblocks_obj;
- vfs->writeblocks[1] = (mp_obj_t)&flash_obj;
- vfs->writeblocks[2] = (mp_obj_t)storage_write_blocks; // native version
- vfs->u.ioctl[0] = (mp_obj_t)&flash_ioctl_obj;
- vfs->u.ioctl[1] = (mp_obj_t)&flash_obj;
+ vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj;
+ vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj;
+ vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version
+ vfs->writeblocks[0] = (mp_obj_t)&internal_flash_obj_writeblocks_obj;
+ vfs->writeblocks[1] = (mp_obj_t)&internal_flash_obj;
+ vfs->writeblocks[2] = (mp_obj_t)internal_flash_write_blocks; // native version
+ vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj;
+ vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj;
}
diff --git a/atmel-samd/internal_flash.h b/atmel-samd/internal_flash.h
new file mode 100644
index 000000000..38886c930
--- /dev/null
+++ b/atmel-samd/internal_flash.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * 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.
+ */
+#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_H__
+#define __MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_H__
+
+#include "mpconfigport.h"
+
+#define INTERNAL_FLASH_BLOCK_SIZE (512)
+
+#define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms
+#define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2)
+
+void internal_flash_init(void);
+uint32_t internal_flash_get_block_size(void);
+uint32_t internal_flash_get_block_count(void);
+void internal_flash_irq_handler(void);
+void internal_flash_flush(void);
+bool internal_flash_read_block(uint8_t *dest, uint32_t block);
+bool internal_flash_write_block(const uint8_t *src, uint32_t block);
+
+// these return 0 on success, non-zero on error
+mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks);
+mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks);
+
+extern const struct _mp_obj_type_t internal_flash_type;
+
+struct _fs_user_mount_t;
+void flash_init_vfs(struct _fs_user_mount_t *vfs);
+
+#endif // __MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_H__
diff --git a/atmel-samd/main.c b/atmel-samd/main.c
index 77a0f53fd..6d781e796 100644
--- a/atmel-samd/main.c
+++ b/atmel-samd/main.c
@@ -23,7 +23,6 @@
#include "mpconfigboard.h"
#include "modmachine_pin.h"
-#include "storage.h"
fs_user_mount_t fs_user_mount_flash;
@@ -72,6 +71,8 @@ static const char fresh_readme_txt[] =
"Please visit http://micropython.org/help/ for further help.\r\n"
;
+extern void flash_init_vfs(fs_user_mount_t *vfs);
+
// we don't make this function static because it needs a lot of stack and we
// want it to be executed without using stack within main() function
void init_flash_fs() {
diff --git a/atmel-samd/modmachine.c b/atmel-samd/modmachine.c
index 67bccc5fd..791e09ada 100644
--- a/atmel-samd/modmachine.c
+++ b/atmel-samd/modmachine.c
@@ -37,7 +37,6 @@
#include "modmachine_dac.h"
#include "modmachine_pin.h"
#include "modmachine_pwm.h"
-#include "storage.h"
#if MICROPY_PY_MACHINE
// TODO(tannewt): Add the machine_ prefix to all types so that we don't risk
@@ -49,7 +48,6 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) },
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pwm_type) },
- { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&flash_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
};
diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h
index 0ebce1958..e38f3fb57 100644
--- a/atmel-samd/mpconfigport.h
+++ b/atmel-samd/mpconfigport.h
@@ -72,6 +72,8 @@
#define MICROPY_FSUSERMOUNT (1)
#define MICROPY_FATFS_MAX_SS (4096)
+#define FLASH_BLOCK_SIZE (512)
+
#define MICROPY_VFS_FAT (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
diff --git a/atmel-samd/spi_flash.c b/atmel-samd/spi_flash.c
new file mode 100644
index 000000000..73717ffca
--- /dev/null
+++ b/atmel-samd/spi_flash.c
@@ -0,0 +1,299 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include "asf/sam0/drivers/sercom/spi/spi.h"
+
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "lib/fatfs/ff.h"
+#include "extmod/fsusermount.h"
+
+#include "asf/sam0/drivers/nvm/nvm.h"
+
+#include "spi_flash.h"
+
+#define TOTAL_SPI_FLASH_SIZE 0x010000
+
+#define SPI_FLASH_MEM_SEG1_START_ADDR (0x00040000 - TOTAL_SPI_FLASH_SIZE)
+#define SPI_FLASH_PART1_START_BLOCK (0x100)
+#define SPI_FLASH_PART1_NUM_BLOCKS (TOTAL_SPI_FLASH_SIZE / SPI_FLASH_BLOCK_SIZE)
+
+static bool spi_flash_is_initialised = false;
+
+struct spi_module spi_flash_instance;
+
+void spi_flash_init(void) {
+ if (!spi_flash_is_initialised) {
+ struct spi_config config_spi_master;
+ spi_get_config_defaults(&config_spi_master);
+ config_spi_master.mux_setting = SPI_FLASH_MUX_SETTING;
+ config_spi_master.pinmux_pad0 = SPI_FLASH_PAD0_PINMUX;
+ config_spi_master.pinmux_pad1 = SPI_FLASH_PAD1_PINMUX;
+ config_spi_master.pinmux_pad2 = SPI_FLASH_PAD2_PINMUX;
+ config_spi_master.pinmux_pad3 = SPI_FLASH_PAD3_PINMUX;
+ config_spi_master.mode_specific.master.baudrate = SPI_FLASH_BAUDRATE;
+ spi_init(&spi_flash_instance, SPI_FLASH_SERCOM, &config_spi_master);
+ spi_enable(&spi_flash_instance);
+ }
+}
+
+uint32_t spi_flash_get_block_size(void) {
+ return SPI_FLASH_BLOCK_SIZE;
+}
+
+uint32_t spi_flash_get_block_count(void) {
+ return SPI_FLASH_PART1_START_BLOCK + SPI_FLASH_PART1_NUM_BLOCKS;
+}
+
+void spi_flash_flush(void) {
+}
+
+static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) {
+ buf[0] = boot;
+
+ if (num_blocks == 0) {
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ } else {
+ buf[1] = 0xff;
+ buf[2] = 0xff;
+ buf[3] = 0xff;
+ }
+
+ buf[4] = type;
+
+ if (num_blocks == 0) {
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+ } else {
+ buf[5] = 0xff;
+ buf[6] = 0xff;
+ buf[7] = 0xff;
+ }
+
+ buf[8] = start_block;
+ buf[9] = start_block >> 8;
+ buf[10] = start_block >> 16;
+ buf[11] = start_block >> 24;
+
+ buf[12] = num_blocks;
+ buf[13] = num_blocks >> 8;
+ buf[14] = num_blocks >> 16;
+ buf[15] = num_blocks >> 24;
+}
+
+static uint32_t convert_block_to_flash_addr(uint32_t block) {
+ if (SPI_FLASH_PART1_START_BLOCK <= block && block < SPI_FLASH_PART1_START_BLOCK + SPI_FLASH_PART1_NUM_BLOCKS) {
+ // a block in partition 1
+ block -= SPI_FLASH_PART1_START_BLOCK;
+ return SPI_FLASH_MEM_SEG1_START_ADDR + block * SPI_FLASH_BLOCK_SIZE;
+ }
+ // bad block
+ return -1;
+}
+
+bool spi_flash_read_block(uint8_t *dest, uint32_t block) {
+ //printf("RD %u\n", block);
+ if (block == 0) {
+ // fake the MBR so we can decide on our own partition table
+
+ for (int i = 0; i < 446; i++) {
+ dest[i] = 0;
+ }
+
+ build_partition(dest + 446, 0, 0x01 /* FAT12 */, SPI_FLASH_PART1_START_BLOCK, SPI_FLASH_PART1_NUM_BLOCKS);
+ build_partition(dest + 462, 0, 0, 0, 0);
+ build_partition(dest + 478, 0, 0, 0, 0);
+ build_partition(dest + 494, 0, 0, 0, 0);
+
+ dest[510] = 0x55;
+ dest[511] = 0xaa;
+
+ return true;
+
+ } else {
+ // non-MBR block, get data from flash memory
+ uint32_t src = convert_block_to_flash_addr(block);
+ if (src == -1) {
+ // bad block number
+ return false;
+ }
+ enum status_code error_code;
+ // A block is made up of multiple pages. Read each page
+ // sequentially.
+ for (int i = 0; i < SPI_FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) {
+ do
+ {
+ error_code = nvm_read_buffer(src + i * NVMCTRL_PAGE_SIZE,
+ dest + i * NVMCTRL_PAGE_SIZE,
+ NVMCTRL_PAGE_SIZE);
+ } while (error_code == STATUS_BUSY);
+ }
+ return true;
+ }
+}
+
+bool spi_flash_write_block(const uint8_t *src, uint32_t block) {
+ if (block == 0) {
+ // can't write MBR, but pretend we did
+ return true;
+
+ } else {
+ // non-MBR block, copy to cache
+ volatile uint32_t dest = convert_block_to_flash_addr(block);
+ if (dest == -1) {
+ // bad block number
+ return false;
+ }
+ enum status_code error_code;
+ // A block is formed by two rows of flash. We must erase each row
+ // before we write back to it.
+ do
+ {
+ error_code = nvm_erase_row(dest);
+ } while (error_code == STATUS_BUSY);
+ if (error_code != STATUS_OK) {
+ return false;
+ }
+ do
+ {
+ error_code = nvm_erase_row(dest + NVMCTRL_ROW_SIZE);
+ } while (error_code == STATUS_BUSY);
+ if (error_code != STATUS_OK) {
+ return false;
+ }
+
+ // A block is made up of multiple pages. Write each page
+ // sequentially.
+ for (int i = 0; i < SPI_FLASH_BLOCK_SIZE / NVMCTRL_PAGE_SIZE; i++) {
+ do
+ {
+ error_code = nvm_write_buffer(dest + i * NVMCTRL_PAGE_SIZE,
+ src + i * NVMCTRL_PAGE_SIZE,
+ NVMCTRL_PAGE_SIZE);
+ } while (error_code == STATUS_BUSY);
+ if (error_code != STATUS_OK) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
+ for (size_t i = 0; i < num_blocks; i++) {
+ if (!spi_flash_read_block(dest + i * SPI_FLASH_BLOCK_SIZE, block_num + i)) {
+ return 1; // error
+ }
+ }
+ return 0; // success
+}
+
+mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
+ for (size_t i = 0; i < num_blocks; i++) {
+ if (!spi_flash_write_block(src + i * SPI_FLASH_BLOCK_SIZE, block_num + i)) {
+ return 1; // error
+ }
+ }
+ return 0; // success
+}
+
+/******************************************************************************/
+// MicroPython bindings
+//
+// Expose the flash as an object with the block protocol.
+
+// there is a singleton Flash object
+STATIC const mp_obj_base_t spi_flash_obj = {&spi_flash_type};
+
+STATIC mp_obj_t spi_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ // check arguments
+ mp_arg_check_num(n_args, n_kw, 0, 0, false);
+
+ // return singleton object
+ return (mp_obj_t)&spi_flash_obj;
+}
+
+STATIC mp_obj_t spi_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
+ mp_uint_t ret = spi_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE);
+ return MP_OBJ_NEW_SMALL_INT(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_readblocks_obj, spi_flash_obj_readblocks);
+
+STATIC mp_obj_t spi_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
+ mp_uint_t ret = spi_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE);
+ return MP_OBJ_NEW_SMALL_INT(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_writeblocks_obj, spi_flash_obj_writeblocks);
+
+STATIC mp_obj_t spi_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
+ mp_int_t cmd = mp_obj_get_int(cmd_in);
+ switch (cmd) {
+ case BP_IOCTL_INIT: spi_flash_init(); return MP_OBJ_NEW_SMALL_INT(0);
+ case BP_IOCTL_DEINIT: spi_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly
+ case BP_IOCTL_SYNC: spi_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0);
+ case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(spi_flash_get_block_count());
+ case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(spi_flash_get_block_size());
+ default: return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(spi_flash_obj_ioctl_obj, spi_flash_obj_ioctl);
+
+STATIC const mp_map_elem_t spi_flash_obj_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readblocks), (mp_obj_t)&spi_flash_obj_readblocks_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_writeblocks), (mp_obj_t)&spi_flash_obj_writeblocks_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&spi_flash_obj_ioctl_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(spi_flash_obj_locals_dict, spi_flash_obj_locals_dict_table);
+
+const mp_obj_type_t spi_flash_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_SPIFlash,
+ .make_new = spi_flash_obj_make_new,
+ .locals_dict = (mp_obj_t)&spi_flash_obj_locals_dict,
+};
+
+void flash_init_vfs(fs_user_mount_t *vfs) {
+ vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
+ vfs->readblocks[0] = (mp_obj_t)&spi_flash_obj_readblocks_obj;
+ vfs->readblocks[1] = (mp_obj_t)&spi_flash_obj;
+ vfs->readblocks[2] = (mp_obj_t)spi_flash_read_blocks; // native version
+ vfs->writeblocks[0] = (mp_obj_t)&spi_flash_obj_writeblocks_obj;
+ vfs->writeblocks[1] = (mp_obj_t)&spi_flash_obj;
+ vfs->writeblocks[2] = (mp_obj_t)spi_flash_write_blocks; // native version
+ vfs->u.ioctl[0] = (mp_obj_t)&spi_flash_obj_ioctl_obj;
+ vfs->u.ioctl[1] = (mp_obj_t)&spi_flash_obj;
+}
diff --git a/atmel-samd/storage.h b/atmel-samd/spi_flash.h
index 8b814c34e..1a8ac0c8e 100644
--- a/atmel-samd/storage.h
+++ b/atmel-samd/spi_flash.h
@@ -23,31 +23,31 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_STORAGE_H__
-#define __MICROPY_INCLUDED_ATMEL_SAMD_STORAGE_H__
+#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H__
+#define __MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H__
#include "mpconfigport.h"
-#define FLASH_BLOCK_SIZE (512)
+#define SPI_FLASH_BLOCK_SIZE (512)
-#define STORAGE_SYSTICK_MASK (0x1ff) // 512ms
-#define STORAGE_IDLE_TICK(tick) (((tick) & STORAGE_SYSTICK_MASK) == 2)
+#define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms
+#define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2)
-void storage_init(void);
-uint32_t storage_get_block_size(void);
-uint32_t storage_get_block_count(void);
-void storage_irq_handler(void);
-void storage_flush(void);
-bool storage_read_block(uint8_t *dest, uint32_t block);
-bool storage_write_block(const uint8_t *src, uint32_t block);
+void spi_flash_init(void);
+uint32_t spi_flash_get_block_size(void);
+uint32_t spi_flash_get_block_count(void);
+void spi_flash_irq_handler(void);
+void spi_flash_flush(void);
+bool spi_flash_read_block(uint8_t *dest, uint32_t block);
+bool spi_flash_write_block(const uint8_t *src, uint32_t block);
// these return 0 on success, non-zero on error
-mp_uint_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks);
-mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks);
+mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks);
+mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks);
-extern const struct _mp_obj_type_t flash_type;
+extern const struct _mp_obj_type_t spi_flash_type;
struct _fs_user_mount_t;
void flash_init_vfs(struct _fs_user_mount_t *vfs);
-#endif // __MICROPY_INCLUDED_ATMEL_SAMD_STORAGE_H__
+#endif // __MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H__
diff --git a/extmod/fsusermount.h b/extmod/fsusermount.h
index e1f26f2ce..3eb54f8bd 100644
--- a/extmod/fsusermount.h
+++ b/extmod/fsusermount.h
@@ -24,6 +24,9 @@
* THE SOFTWARE.
*/
+#include "lib/fatfs/ff.h"
+#include "py/obj.h"
+
// these are the values for fs_user_mount_t.flags
#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func
#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount
diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c
index 3f1902b2e..5608e0645 100644
--- a/extmod/vfs_fat_diskio.c
+++ b/extmod/vfs_fat_diskio.c
@@ -90,7 +90,7 @@ DSTATUS disk_initialize (
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
- BYTE pdrv /* Physical drive nmuber (0..) */
+ BYTE pdrv /* Physical drive number (0..) */
)
{
fs_user_mount_t *vfs = disk_get_device(pdrv);
@@ -110,7 +110,7 @@ DSTATUS disk_status (
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
- BYTE pdrv, /* Physical drive nmuber (0..) */
+ BYTE pdrv, /* Physical drive number (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..128) */