Skip to content

Add support for external flash chips and improve mass storage. #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions atmel-samd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
)

SRC_C = \
access_vfs.c \
builtin_open.c \
fatfs_port.c \
main.c \
Expand All @@ -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 \
Expand Down
94 changes: 79 additions & 15 deletions atmel-samd/rom_fs.c → atmel-samd/access_vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,53 +24,91 @@
* THE SOFTWARE.
*/

#include "rom_fs.h"
#include <string.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
//! It is ready -> CTRL_GOOD
//! 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
//! @param uint32_t_nb_sector Pointer to number of sectors (sector=512 bytes)
//! @param uint32_t_nb_sector Pointer to the last valid sector (sector=512 bytes)
//! @return Ctrl_status
//! It is ready -> CTRL_GOOD
//! 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 *last_valid_sector)
{
*uint32_t_nb_sector = storage_get_block_count();
return CTRL_GOOD;
if (disk_ioctl(VFS_INDEX, GET_SECTOR_COUNT, last_valid_sector) != RES_OK) {
return CTRL_FAIL;
}
// Subtract one from the sector count to get the last valid sector.
(*last_valid_sector)--;
return CTRL_GOOD;
}

//! This function returns the write-protected mode
//!
//! @return true if the memory is protected
//!
bool rom_fs_wr_protect(void)
bool vfs_wr_protect(void)
{
return false;
if (VFS_INDEX >= MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
return true;
}
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[VFS_INDEX];
if (vfs == NULL) {
return true;
}

// This is used to determine the writeability of the disk from USB.
if (vfs->writeblocks[0] == MP_OBJ_NULL ||
(vfs->flags & FSUSER_USB_WRITEABLE) == 0) {
return true;
}
return false;
}

//! 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
Expand All @@ -84,11 +122,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
}
Expand All @@ -108,16 +152,36 @@ 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, volatile 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)) {
uint32_t sector_address = addr + sector;
DRESULT result = disk_write(VFS_INDEX, sector_buffer, sector_address, 1);
if (result == RES_PARERR) {
return CTRL_NO_PRESENT;
}
if (result == RES_ERROR) {
return CTRL_FAIL;
}
// Since by getting here we assume the mount is read-only to MicroPython
// lets update the cached FatFs sector if its the one we just wrote.
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[VFS_INDEX];
volatile uint16_t x = addr;
(void) x;
#if _MAX_SS != _MIN_SS
if (vfs->ssize == FLASH_BLOCK_SIZE) {
#else
// The compiler can optimize this away.
if (_MAX_SS == FLASH_BLOCK_SIZE) {
#endif
if (sector_address == vfs->fatfs.winsect && sector_address > 0) {
memcpy(vfs->fatfs.win, sector_buffer, FLASH_BLOCK_SIZE);
}
}
}
return CTRL_GOOD;
}
17 changes: 10 additions & 7 deletions atmel-samd/rom_fs.h → atmel-samd/access_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__
18 changes: 9 additions & 9 deletions atmel-samd/boards/arduino_zero/conf_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions atmel-samd/boards/arduino_zero/mpconfigboard.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x2341
USB_PID = 0x824D

FLASH_IMPL = internal_flash.c
2 changes: 2 additions & 0 deletions atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x8015

FLASH_IMPL = internal_flash.c
18 changes: 9 additions & 9 deletions atmel-samd/boards/metro_m0_flash/conf_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 23 additions & 2 deletions atmel-samd/boards/metro_m0_flash/mpconfigboard.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
// LEDs
#define MICROPY_HW_LED1 PIN_PA17 // red
// #define UART_REPL
#define USB_REPL

#define MICROPY_HW_BOARD_NAME "Adafruit Metro M0 with Flash (Experimental)"
#define MICROPY_HW_MCU_NAME "samd21g18"

#define MICROPY_HW_LED_MSC PIN_PA17
#define MICROPY_HW_LED_TX PIN_PA27
#define MICROPY_HW_LED_RX PIN_PB03

#define SPI_FLASH_BAUDRATE (1000000)

// Off-board flash
// #define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E
// #define SPI_FLASH_PAD0_PINMUX PINMUX_PA16C_SERCOM1_PAD0 // MISO D11
// Use default pinmux for the chip select since we manage it ourselves.
// #define SPI_FLASH_PAD1_PINMUX PINMUX_DEFAULT
// #define SPI_FLASH_PAD2_PINMUX PINMUX_PA18C_SERCOM1_PAD2 // MOSI D10
// #define SPI_FLASH_PAD3_PINMUX PINMUX_PA19C_SERCOM1_PAD3 // SCK D12
// #define SPI_FLASH_CS PIN_PA17
// #define SPI_FLASH_SERCOM SERCOM1

// On-board flash
#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E
#define SPI_FLASH_PAD0_PINMUX PINMUX_PA12D_SERCOM4_PAD0 // MISO
// Use default pinmux for the chip select since we manage it ourselves.
#define SPI_FLASH_PAD1_PINMUX PINMUX_DEFAULT // CS
#define SPI_FLASH_PAD2_PINMUX PINMUX_PB10D_SERCOM4_PAD2 // MOSI
#define SPI_FLASH_PAD3_PINMUX PINMUX_PB11D_SERCOM4_PAD3 // SCK
#define SPI_FLASH_CS PIN_PA13
#define SPI_FLASH_SERCOM SERCOM4
2 changes: 2 additions & 0 deletions atmel-samd/boards/metro_m0_flash/mpconfigboard.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
LD_FILE = boards/samd21x18-bootloader-external-flash.ld
USB_VID = 0x239A
USB_PID = 0x8015

FLASH_IMPL = spi_flash.c
2 changes: 1 addition & 1 deletion atmel-samd/boards/metro_m0_flash/pins.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ PIN(PA19, false, NO_ADC_INPUT,
TIMER(TC3, 0, 1, 1, PIN_PA19E_TC3_WO1, MUX_PA19E_TC3_WO1),
TIMER(0, TCC0, 3, 3, PIN_PA19F_TCC0_WO3, MUX_PA19F_TCC0_WO3),
SERCOM(SERCOM1, 3, PINMUX_PA19C_SERCOM1_PAD3),
SERCOM(SERCOM3, 3, PINMUX_PA19C_SERCOM1_PAD3));
SERCOM(SERCOM3, 3, PINMUX_PA19D_SERCOM3_PAD3));
PIN(PA17, false, NO_ADC_INPUT,
TIMER(0, TCC2, 1, 1, PIN_PA17E_TCC2_WO1, MUX_PA17E_TCC2_WO1),
TIMER(0, TCC0, 3, 7, PIN_PA17F_TCC0_WO7, MUX_PA17F_TCC0_WO7),
Expand Down
8 changes: 8 additions & 0 deletions atmel-samd/boards/samd21x18-bootloader-external-flash.ld
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,13 @@ SECTIONS
_ebss = .;
} >RAM

/* this just checks there is enough RAM for a minimal stack */
.stack :
{
. = ALIGN(4);
. = . + 0x800; /* Reserve a minimum of 2K for the stack. */
. = ALIGN(4);
} >RAM

.ARM.attributes 0 : { *(.ARM.attributes) }
}
8 changes: 8 additions & 0 deletions atmel-samd/boards/samd21x18-bootloader.ld
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,13 @@ SECTIONS
_ebss = .;
} >RAM

/* this just checks there is enough RAM for a minimal stack */
.stack :
{
. = ALIGN(4);
. = . + 0x800; /* Reserve a minimum of 2K for the stack. */
. = ALIGN(4);
} >RAM

.ARM.attributes 0 : { *(.ARM.attributes) }
}
Loading