diff --git a/cc3200/fatfs/src/drivers/sd_diskio.c b/cc3200/fatfs/src/drivers/sd_diskio.c index 733bc5201d..3b17aa6b89 100644 --- a/cc3200/fatfs/src/drivers/sd_diskio.c +++ b/cc3200/fatfs/src/drivers/sd_diskio.c @@ -279,8 +279,6 @@ DSTATUS sd_disk_init (void) { sd_disk_info.bStatus = 0; } } - // Set card rd/wr block len - MAP_SDHostBlockSizeSet(SDHOST_BASE, SD_SECTOR_SIZE); } return sd_disk_info.bStatus; @@ -315,15 +313,6 @@ DSTATUS sd_disk_status (void) { return sd_disk_info.bStatus; } -//***************************************************************************** -// -//! Returns wether the sd card is ready to be accessed or not -// -//***************************************************************************** -bool sd_disk_ready (void) { - return (!sd_disk_info.bStatus); -} - //***************************************************************************** // //! Reads sector(s) from the disk drive. diff --git a/cc3200/fatfs/src/drivers/sd_diskio.h b/cc3200/fatfs/src/drivers/sd_diskio.h index 7867b3acf2..f1cb2a0bfe 100644 --- a/cc3200/fatfs/src/drivers/sd_diskio.h +++ b/cc3200/fatfs/src/drivers/sd_diskio.h @@ -22,7 +22,6 @@ extern DiskInfo_t sd_disk_info; DSTATUS sd_disk_init (void); void sd_disk_deinit (void); DSTATUS sd_disk_status (void); -bool sd_disk_ready (void); DRESULT sd_disk_read (BYTE* pBuffer, DWORD ulSectorNumber, UINT bSectorCount); DRESULT sd_disk_write (const BYTE* pBuffer, DWORD ulSectorNumber, UINT bSectorCount); diff --git a/cc3200/ftp/ftp.c b/cc3200/ftp/ftp.c index 651cd1ef90..f61ee6d481 100644 --- a/cc3200/ftp/ftp.c +++ b/cc3200/ftp/ftp.c @@ -47,8 +47,7 @@ #include "ff.h" #include "fifo.h" #include "socketfifo.h" -#include "diskio.h" -#include "sd_diskio.h" +#include "pybsd.h" #include "updater.h" #include "timeutils.h" @@ -193,7 +192,7 @@ static const ftp_month_t ftp_month[] = { { "Jan" }, { "Feb" }, { "Mar" }, { "Apr { "May" }, { "Jun" }, { "Jul" }, { "Ago" }, { "Sep" }, { "Oct" }, { "Nov" }, { "Dec" } }; -static SocketFifoElement_t *ftp_fifoelements; +static SocketFifoElement_t ftp_fifoelements[FTP_SOCKETFIFO_ELEMENTS_MAX]; static FIFO_t ftp_socketfifo; /****************************************************************************** @@ -233,7 +232,6 @@ void ftp_init (void) { ASSERT ((ftp_path = mem_Malloc(FTP_MAX_PARAM_SIZE)) != NULL); ASSERT ((ftp_scratch_buffer = mem_Malloc(FTP_MAX_PARAM_SIZE)) != NULL); ASSERT ((ftp_cmd_buffer = mem_Malloc(FTP_MAX_PARAM_SIZE + FTP_CMD_SIZE_MAX)) != NULL); - ASSERT ((ftp_fifoelements = mem_Malloc(FTP_SOCKETFIFO_ELEMENTS_MAX * sizeof(SocketFifoElement_t))) != NULL); SOCKETFIFO_Init (&ftp_socketfifo, (void *)ftp_fifoelements, FTP_SOCKETFIFO_ELEMENTS_MAX); ftp_data.c_sd = -1; ftp_data.d_sd = -1; @@ -987,7 +985,7 @@ static ftp_result_t ftp_open_dir_for_listing (const char *path, char *list, uint if (path[0] == '/' && path[1] == '\0') { next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "flash"); #if MICROPY_HW_HAS_SDCARD - if (sd_disk_ready()) { + if (pybsd_is_mounted()) { next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "sd"); } #endif diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c index 68084b711b..0d62a96e85 100644 --- a/cc3200/mods/moduos.c +++ b/cc3200/mods/moduos.c @@ -39,7 +39,7 @@ #include "sflash_diskio.h" #include "file.h" #include "random.h" -#include "sd_diskio.h" +#include "pybsd.h" #include "mpexception.h" #include "version.h" #include "timeutils.h" @@ -60,13 +60,6 @@ /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ -STATIC bool sd_in_root(void) { -#if MICROPY_HW_HAS_SDCARD - return sd_disk_ready(); -#else - return false; -#endif -} /******************************************************************************/ // Micro Python bindings @@ -151,7 +144,7 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) { mp_obj_t dir_list = mp_obj_new_list(0, NULL); mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_flash)); #if MICROPY_HW_HAS_SDCARD - if (sd_in_root()) { + if (pybsd_is_mounted()) { mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_sd)); } #endif @@ -280,7 +273,11 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) { if (path_equal(path, "/") || path_equal(path, "/flash") || path_equal(path, "/sd")) { // stat built-in directory - if (path[1] == 's' && !sd_in_root()) { +#if MICROPY_HW_HAS_SDCARD + if (path[1] == 's' && !pybsd_is_mounted()) { +#else + if (path[1] == 's') { +#endif // no /sd directory res = FR_NO_PATH; goto error; @@ -353,11 +350,21 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #endif -/// \function mkfs('path') -/// Formats the selected drive, useful when the filesystem has been damaged beyond repair +/// \function mkfs('drive') +/// Formats the selected drive, useful when the filesystem has been damaged beyond repair. +/// Path must be either '/sd' or '/flash' STATIC mp_obj_t os_mkfs(mp_obj_t path_o) { const char *path = mp_obj_str_get_str(path_o); - if (FR_OK != f_mkfs(path, 1, 0)) { + uint8_t sfd; + + if (!strcmp(path, "/flash")) { + sfd = 1; + } else if (!strcmp(path, "/sd")) { + sfd = 0; + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + } + if (FR_OK != f_mkfs(path, sfd, 0)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); } return mp_const_none; diff --git a/cc3200/mods/pybsd.c b/cc3200/mods/pybsd.c index c5444b5911..110356adc2 100644 --- a/cc3200/mods/pybsd.c +++ b/cc3200/mods/pybsd.c @@ -58,19 +58,23 @@ typedef struct { pin_obj_t *pin_clk; bool pinsset; bool enabled; + bool mounted; } pybsd_obj_t; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ -STATIC pybsd_obj_t pybsd_obj; +STATIC pybsd_obj_t pybsd_obj = {.pinsset = false, .enabled = false, .mounted = false}; /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ +STATIC void pybsd_hw_init (pybsd_obj_t *self); STATIC mp_obj_t pybsd_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t pybsd_disable (mp_obj_t self_in); -STATIC mp_obj_t pybsd_enable (mp_obj_t self_in); +STATIC mp_obj_t pybsd_init (uint n_args, const mp_obj_t *args); +STATIC mp_obj_t pybsd_deinit (mp_obj_t self_in); +STATIC mp_obj_t pybsd_mount (mp_obj_t self_in); +STATIC mp_obj_t pybsd_unmount (mp_obj_t self_in); /****************************************************************************** DEFINE PUBLIC FUNCTIONS @@ -81,15 +85,19 @@ void pybsd_init0 (void) { ASSERT ((pybsd_obj.fatfs = mem_Malloc(sizeof(FATFS))) != NULL); } -void pybsd_deinit (void) { - pybsd_disable ((mp_obj_t)&pybsd_obj); +void pybsd_disable (void) { + pybsd_deinit ((mp_obj_t)&pybsd_obj); +} + +bool pybsd_is_mounted (void) { + return pybsd_obj.mounted; } /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ -/// Initalizes the sd card driver -STATIC void pybsd_init (pybsd_obj_t *self) { +/// Initalizes the sd card hardware driver +STATIC void pybsd_hw_init (pybsd_obj_t *self) { // Configure the clock pin as output only MAP_PinDirModeSet(self->pin_clk->pin_num, PIN_DIR_MODE_OUT); // Enable SD peripheral clock @@ -100,6 +108,41 @@ STATIC void pybsd_init (pybsd_obj_t *self) { MAP_SDHostInit(SDHOST_BASE); // Configure the card clock MAP_SDHostSetExpClk(SDHOST_BASE, MAP_PRCMPeripheralClockGet(PRCM_SDHOST), PYBSD_FREQUENCY_HZ); + // Set card rd/wr block len + MAP_SDHostBlockSizeSet(SDHOST_BASE, SD_SECTOR_SIZE); +} + +STATIC mp_obj_t pybsd_init_helper (pybsd_obj_t *self, uint n_args, const mp_obj_t *args) { + if (n_args > 0) { + if (mp_obj_get_type(args[0]) == &mp_type_tuple) { + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[0], 6, &items); + + // save the clock pin for later use + self->pin_clk = (pin_obj_t *)pin_find(items[2]); + + // configure the data pin with pull-up enabled + pin_config ((pin_obj_t *)pin_find(items[0]), mp_obj_get_int(items[1]), 0, PIN_TYPE_STD_PU, PIN_STRENGTH_4MA); + // configure the clock pin + pin_config (self->pin_clk, mp_obj_get_int(items[3]), 0, PIN_TYPE_STD, PIN_STRENGTH_4MA); + // configure the command pin with pull-up enabled + pin_config ((pin_obj_t *)pin_find(items[4]), mp_obj_get_int(items[5]), 0, PIN_TYPE_STD_PU, PIN_STRENGTH_4MA); + self->pinsset = true; + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments)); + } + } + + if (!self->enabled) { + if (!self->pinsset) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + } + pybsd_hw_init (self); + // mark as enabled and register it with the sleep module + self->enabled = true; + pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)pybsd_hw_init); + } + return mp_const_none; } /******************************************************************************/ @@ -107,95 +150,98 @@ STATIC void pybsd_init (pybsd_obj_t *self) { // /// \classmethod \constructor() -/// Configure the pins used for the sd card. -/// May receive 0, or 6 arguments. +/// Creates an SD card object. +/// Accepts a tuple of pins an alternate functions to configure the SD card interface. +/// When called with no arguments it returns the previoulsy created SD card object. /// /// Usage: /// sd = pyb.SD() -//// -/// sd = pyb.SD(d0_pin, d0_af, clk_pin, clk_af, cmd_pin, cmd_af) +/// Or: +/// sd = pyb.SD((d0_pin, d0_af, clk_pin, clk_af, cmd_pin, cmd_af)) /// STATIC mp_obj_t pybsd_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 6, false); + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_t self = &pybsd_obj; + pybsd_obj.base.type = &pyb_sd_type; - if (n_args == 6) { - // save the clock pin for later use - pybsd_obj.pin_clk = (pin_obj_t *)pin_find(args[2]); - - // configure the data pin with pull-up enabled - pin_config ((pin_obj_t *)pin_find(args[0]), mp_obj_get_int(args[1]), 0, PIN_TYPE_STD_PU, PIN_STRENGTH_4MA); - // configure the clock pin - pin_config (pybsd_obj.pin_clk, mp_obj_get_int(args[3]), 0, PIN_TYPE_STD, PIN_STRENGTH_4MA); - // configure the command pin with pull-up enabled - pin_config ((pin_obj_t *)pin_find(args[4]), mp_obj_get_int(args[5]), 0, PIN_TYPE_STD_PU, PIN_STRENGTH_4MA); - - pybsd_obj.pinsset = true; - pybsd_obj.base.type = &pyb_sd_type; + if (n_args > 0) { + pybsd_init_helper (self, n_args, args); } - else if (!pybsd_obj.pinsset) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments)); - } - - return &pybsd_obj; + return self; } -/// \method enable() -/// Enables the sd card and mounts the file system -STATIC mp_obj_t pybsd_enable (mp_obj_t self_in) { +/// \method init() +/// Enables the sd card +STATIC mp_obj_t pybsd_init (uint n_args, const mp_obj_t *args) { + return pybsd_init_helper(args[0], n_args - 1, args + 1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pybsd_init_obj, 1, 2, pybsd_init); + +/// \method deinit() +/// Disables the sd card +STATIC mp_obj_t pybsd_deinit (mp_obj_t self_in) { pybsd_obj_t *self = self_in; + if (self->enabled) { + // unmounted in case not done yet + pybsd_unmount (self); + self->enabled = false; + // disable the peripheral + MAP_PRCMPeripheralClkDisable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); + // de-initialze the sd card at diskio level + sd_disk_deinit(); + // unregister it with the sleep module + pybsleep_remove (self); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_deinit_obj, pybsd_deinit); - if (!self->enabled) { - // do the init first - pybsd_init (self); - +/// \method mount() +/// Mount the sd card on /sd +STATIC mp_obj_t pybsd_mount (mp_obj_t self_in) { + pybsd_obj_t *self = self_in; + if (!self->mounted) { + if (!self->enabled) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + } // try to mount the sd card on /sd if (FR_OK != f_mount(self->fatfs, "/sd", 1)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); } - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); - - // register it with the sleep module - pybsleep_add ((const mp_obj_t)&pybsd_obj, (WakeUpCB_t)pybsd_init); - self->enabled = true; + self->mounted = true; } - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_enable_obj, pybsd_enable); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_mount_obj, pybsd_mount); -/// \method disable() -/// Disables the sd card and unmounts the file system -STATIC mp_obj_t pybsd_disable (mp_obj_t self_in) { +/// \method unmount() +/// Unmount the sd card +STATIC mp_obj_t pybsd_unmount (mp_obj_t self_in) { pybsd_obj_t *self = self_in; - if (self->enabled) { - self->enabled = false; + if (self->mounted) { + if (!self->enabled) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + } // unmount the sd card f_mount (NULL, "/sd", 1); // remove sd paths from mp_sys_path mp_obj_list_remove(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); mp_obj_list_remove(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); - - // disable the peripheral - MAP_PRCMPeripheralClkDisable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); - - // de-initialze de sd card at diskio level - sd_disk_deinit(); - - // unregister it with the sleep module - pybsleep_remove (self); - + self->mounted = false; // change the drive in case it was /sd f_chdrive("/flash"); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_disable_obj, pybsd_disable); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_unmount_obj, pybsd_unmount); STATIC const mp_map_elem_t pybsd_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&pybsd_enable_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&pybsd_disable_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pybsd_init_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pybsd_deinit_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&pybsd_mount_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_unmount), (mp_obj_t)&pybsd_unmount_obj }, }; STATIC MP_DEFINE_CONST_DICT(pybsd_locals_dict, pybsd_locals_dict_table); diff --git a/cc3200/mods/pybsd.h b/cc3200/mods/pybsd.h index b1244f23f9..5004441f38 100644 --- a/cc3200/mods/pybsd.h +++ b/cc3200/mods/pybsd.h @@ -30,7 +30,8 @@ extern const mp_obj_type_t pyb_sd_type; void pybsd_init0 (void); -void pybsd_deinit (void); +void pybsd_disable (void); +bool pybsd_is_mounted (void); #endif #endif // PYBSD_H_ diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 3a62c46238..5c4a45ad11 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -251,7 +251,7 @@ soft_reset_exit: modusocket_close_all_user_sockets(); #if MICROPY_HW_HAS_SDCARD - pybsd_deinit(); + pybsd_disable(); #endif // wait for pending transactions to complete @@ -284,7 +284,7 @@ STATIC void mptask_pre_init (void) { // this one allocates memory for the updater semaphore updater_pre_init(); - // this one allocates memory for the Socket semaphore + // this one allocates memory for the socket semaphore modusocket_pre_init(); #if MICROPY_HW_HAS_SDCARD diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index b3d25fac7b..393d2b798c 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -188,8 +188,10 @@ Q(deinit) #if MICROPY_HW_HAS_SDCARD // for SD class Q(SD) -Q(enable) -Q(disable) +Q(init) +Q(deinit) +Q(mount) +Q(unmount) #endif // for RTC class diff --git a/cc3200/serverstask.h b/cc3200/serverstask.h index 06de1275b8..ceebf345c4 100644 --- a/cc3200/serverstask.h +++ b/cc3200/serverstask.h @@ -31,7 +31,7 @@ DEFINE CONSTANTS ******************************************************************************/ #define SERVERS_PRIORITY 2 -#define SERVERS_STACK_SIZE 1072 +#define SERVERS_STACK_SIZE 1024 #define SERVERS_SSID_LEN_MAX 16 #define SERVERS_KEY_LEN_MAX 16 diff --git a/docs/library/pyb.SD.rst b/docs/library/pyb.SD.rst index 0746b435bf..9b3d95dac4 100644 --- a/docs/library/pyb.SD.rst +++ b/docs/library/pyb.SD.rst @@ -15,25 +15,34 @@ Example usage:: # data, clk and cmd pins must be passed along with # their respective alternate functions - sd = pyb.SD('GP15', 8, 'GP10', 6, 'GP11', 6) - sd.enable() # enable and mount the SD card - sd.disable() # disable and unmount it + sd = pyb.SD(('GP15', 8, 'GP10', 6, 'GP11', 6)) + sd.mount() + # do normal file operations Constructors ------------ -.. class:: pyb.SD(dat_pin, dat_pin_af, clk_pin, clk_pin_af, cmd_pin, cmd_pin_af) +.. class:: pyb.SD([pins_tuple]) - Create a SD card object. Data, clock and cmd pins must be passed along with - their respective alternate functions. + Create a SD card object. In order to initalize the card, give it a 6-tuple + ``(dat_pin, dat_af, clk_pin, clk_af, cmd_pin, cmd_af)`` with the data, clock + and cmd pins together their respective alternate functions. Methods ------- -.. method:: sd.enable() +.. method:: sd.init([pins_tuple]) - Enable the SD card and mount it on the file system. Accesible as ``/sd``. + Enable the SD card. -.. method:: sd.disable() +.. method:: sd.deinit() - Disable the SD card and remove it from the file system. + Disable the SD card (also unmounts it to avoid file system crashes). + +.. method:: sd.mount() + + Mount the SD card on the file system. Accesible as ``/sd``. + +.. method:: sd.unmount() + + Unmount the SD card from the file system. diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst index 2acbaa5413..358020d94e 100644 --- a/docs/wipy/quickref.rst +++ b/docs/wipy/quickref.rst @@ -172,10 +172,10 @@ See :ref:`pyb.SD `. :: from pyb import SD - # SD card pins need special configuration so we pass 'em to the constructor + # SD card pins need special configuration so we pass them to the constructor # data pin, data af, clock pin, clock af, cmd pin, cmd af - sd = pyb.SD('GP15', 8, 'GP10', 6, 'GP11', 6) - sd.enable() + sd = pyb.SD(('GP15', 8, 'GP10', 6, 'GP11', 6)) + sd.mount() WLAN (WiFi) -----------