Skip to content

Commit 30dc241

Browse files
authored
Merge pull request #31 from tannewt/external_flash
Add support for external flash chips and improve mass storage.
2 parents 6fe8c7b + b2834c3 commit 30dc241

24 files changed

+1052
-139
lines changed

atmel-samd/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
143143
)
144144

145145
SRC_C = \
146+
access_vfs.c \
146147
builtin_open.c \
147148
fatfs_port.c \
148149
main.c \
@@ -156,9 +157,8 @@ SRC_C = \
156157
modutime.c \
157158
mphalport.c \
158159
pin_named_pins.c \
159-
rom_fs.c \
160160
samdneopixel.c \
161-
storage.c \
161+
$(FLASH_IMPL) \
162162
asf/common/services/sleepmgr/samd/sleepmgr.c \
163163
asf/common/services/storage/ctrl_access/ctrl_access.c \
164164
asf/common/services/usb/class/cdc/device/udi_cdc.c \

atmel-samd/rom_fs.c renamed to atmel-samd/access_vfs.c

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,53 +24,91 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#include "rom_fs.h"
27+
#include <string.h>
28+
29+
#include "access_vfs.h"
2830

2931
#include "asf/common/services/usb/class/msc/device/udi_msc.h"
30-
#include "storage.h"
32+
#include "extmod/fsusermount.h"
33+
#include "lib/fatfs/diskio.h"
34+
#include "py/mpconfig.h"
35+
#include "py/mpstate.h"
36+
#include "py/misc.h"
37+
38+
#define VFS_INDEX 0
3139

3240
//! This function tests memory state, and starts memory initialization
3341
//! @return Ctrl_status
3442
//! It is ready -> CTRL_GOOD
3543
//! Memory unplug -> CTRL_NO_PRESENT
3644
//! Not initialized or changed -> CTRL_BUSY
3745
//! An error occurred -> CTRL_FAIL
38-
Ctrl_status rom_fs_test_unit_ready(void)
46+
Ctrl_status vfs_test_unit_ready(void)
3947
{
40-
return CTRL_GOOD;
48+
if (VFS_INDEX >= MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
49+
return CTRL_FAIL;
50+
}
51+
DSTATUS status = disk_status(VFS_INDEX);
52+
if (status == STA_NOINIT) {
53+
return CTRL_NO_PRESENT;
54+
}
55+
56+
return CTRL_GOOD;
4157
}
4258

4359
//! This function returns the address of the last valid sector
44-
//! @param uint32_t_nb_sector Pointer to number of sectors (sector=512 bytes)
60+
//! @param uint32_t_nb_sector Pointer to the last valid sector (sector=512 bytes)
4561
//! @return Ctrl_status
4662
//! It is ready -> CTRL_GOOD
4763
//! Memory unplug -> CTRL_NO_PRESENT
4864
//! Not initialized or changed -> CTRL_BUSY
4965
//! An error occurred -> CTRL_FAIL
50-
Ctrl_status rom_fs_read_capacity(uint32_t *uint32_t_nb_sector)
66+
Ctrl_status vfs_read_capacity(uint32_t *last_valid_sector)
5167
{
52-
*uint32_t_nb_sector = storage_get_block_count();
53-
return CTRL_GOOD;
68+
if (disk_ioctl(VFS_INDEX, GET_SECTOR_COUNT, last_valid_sector) != RES_OK) {
69+
return CTRL_FAIL;
70+
}
71+
// Subtract one from the sector count to get the last valid sector.
72+
(*last_valid_sector)--;
73+
return CTRL_GOOD;
5474
}
5575

5676
//! This function returns the write-protected mode
5777
//!
5878
//! @return true if the memory is protected
5979
//!
60-
bool rom_fs_wr_protect(void)
80+
bool vfs_wr_protect(void)
6181
{
62-
return false;
82+
if (VFS_INDEX >= MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
83+
return true;
84+
}
85+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[VFS_INDEX];
86+
if (vfs == NULL) {
87+
return true;
88+
}
89+
90+
// This is used to determine the writeability of the disk from USB.
91+
if (vfs->writeblocks[0] == MP_OBJ_NULL ||
92+
(vfs->flags & FSUSER_USB_WRITEABLE) == 0) {
93+
return true;
94+
}
95+
return false;
6396
}
6497

6598
//! This function informs about the memory type
6699
//!
67100
//! @return true if the memory is removable
68101
//!
69-
bool rom_fs_removal(void)
102+
bool vfs_removal(void)
70103
{
71104
return true;
72105
}
73106

107+
bool vfs_unload(bool unload)
108+
{
109+
return unload;
110+
}
111+
74112
// TODO(tannewt): Transfer more than a single sector at a time if we need more
75113
// speed.
76114
//! This function transfers the memory data to the USB MSC interface
@@ -84,11 +122,17 @@ bool rom_fs_removal(void)
84122
//! Not initialized or changed -> CTRL_BUSY
85123
//! An error occurred -> CTRL_FAIL
86124
//!
87-
Ctrl_status rom_fs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
125+
Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
88126
{
89127
uint8_t sector_buffer[FLASH_BLOCK_SIZE];
90128
for (uint16_t sector = 0; sector < nb_sector; sector++) {
91-
storage_read_block(sector_buffer, addr + sector);
129+
DRESULT result = disk_read(VFS_INDEX, sector_buffer, addr + sector, 1);
130+
if (result == RES_PARERR) {
131+
return CTRL_NO_PRESENT;
132+
}
133+
if (result == RES_ERROR) {
134+
return CTRL_FAIL;
135+
}
92136
if (!udi_msc_trans_block(true, sector_buffer, FLASH_BLOCK_SIZE, NULL)) {
93137
return CTRL_FAIL; // transfer aborted
94138
}
@@ -108,16 +152,36 @@ Ctrl_status rom_fs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
108152
//! Not initialized or changed -> CTRL_BUSY
109153
//! An error occurred -> CTRL_FAIL
110154
//!
111-
Ctrl_status rom_fs_usb_write_10(uint32_t addr, uint16_t nb_sector)
155+
Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector)
112156
{
113157
uint8_t sector_buffer[FLASH_BLOCK_SIZE];
114158
for (uint16_t sector = 0; sector < nb_sector; sector++) {
115159
if (!udi_msc_trans_block(false, sector_buffer, FLASH_BLOCK_SIZE, NULL)) {
116160
return CTRL_FAIL; // transfer aborted
117161
}
118-
if (!storage_write_block(sector_buffer, addr + sector)) {
162+
uint32_t sector_address = addr + sector;
163+
DRESULT result = disk_write(VFS_INDEX, sector_buffer, sector_address, 1);
164+
if (result == RES_PARERR) {
165+
return CTRL_NO_PRESENT;
166+
}
167+
if (result == RES_ERROR) {
119168
return CTRL_FAIL;
120169
}
170+
// Since by getting here we assume the mount is read-only to MicroPython
171+
// lets update the cached FatFs sector if its the one we just wrote.
172+
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[VFS_INDEX];
173+
volatile uint16_t x = addr;
174+
(void) x;
175+
#if _MAX_SS != _MIN_SS
176+
if (vfs->ssize == FLASH_BLOCK_SIZE) {
177+
#else
178+
// The compiler can optimize this away.
179+
if (_MAX_SS == FLASH_BLOCK_SIZE) {
180+
#endif
181+
if (sector_address == vfs->fatfs.winsect && sector_address > 0) {
182+
memcpy(vfs->fatfs.win, sector_buffer, FLASH_BLOCK_SIZE);
183+
}
184+
}
121185
}
122186
return CTRL_GOOD;
123187
}

atmel-samd/rom_fs.h renamed to atmel-samd/access_vfs.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,20 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
// This adapts the ASF access API to MicroPython's VFS API so we can expose all
28+
// VFS block devices as Lun's over USB mass storage control.
29+
2730
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_ROM_FS_H__
2831
#define __MICROPY_INCLUDED_ATMEL_SAMD_ROM_FS_H__
2932

3033
#include "asf/common/services/storage/ctrl_access/ctrl_access.h"
3134

32-
33-
Ctrl_status rom_fs_test_unit_ready(void);
34-
Ctrl_status rom_fs_read_capacity(uint32_t *u32_nb_sector);
35-
bool rom_fs_wr_protect(void);
36-
bool rom_fs_removal(void);
37-
Ctrl_status rom_fs_usb_read_10(uint32_t addr, uint16_t nb_sector);
38-
Ctrl_status rom_fs_usb_write_10(uint32_t addr, uint16_t nb_sector);
35+
Ctrl_status vfs_test_unit_ready(void);
36+
Ctrl_status vfs_read_capacity(uint32_t *u32_nb_sector);
37+
bool vfs_wr_protect(void);
38+
bool vfs_removal(void);
39+
bool vfs_unload(bool);
40+
Ctrl_status vfs_usb_read_10(uint32_t addr, uint16_t nb_sector);
41+
Ctrl_status vfs_usb_write_10(uint32_t addr, uint16_t nb_sector);
3942

4043
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_ROM_FS_H__

atmel-samd/boards/arduino_zero/conf_access.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@
6868
/*! \name LUN 0 Definitions
6969
*/
7070
//! @{
71-
#define LUN_0_INCLUDE "rom_fs.h"
72-
#define Lun_0_test_unit_ready rom_fs_test_unit_ready
73-
#define Lun_0_read_capacity rom_fs_read_capacity
74-
#define Lun_0_unload NULL /* Can not be unloaded */
75-
#define Lun_0_wr_protect rom_fs_wr_protect
76-
#define Lun_0_removal rom_fs_removal
77-
#define Lun_0_usb_read_10 rom_fs_usb_read_10
78-
#define Lun_0_usb_write_10 rom_fs_usb_write_10
79-
#define LUN_0_NAME "\"On-Chip ROM\""
71+
#define LUN_0_INCLUDE "access_vfs.h"
72+
#define Lun_0_test_unit_ready vfs_test_unit_ready
73+
#define Lun_0_read_capacity vfs_read_capacity
74+
#define Lun_0_unload NULL
75+
#define Lun_0_wr_protect vfs_wr_protect
76+
#define Lun_0_removal vfs_removal
77+
#define Lun_0_usb_read_10 vfs_usb_read_10
78+
#define Lun_0_usb_write_10 vfs_usb_write_10
79+
#define LUN_0_NAME "\"MicroPython VFS[0]\""
8080
//! @}
8181

8282
#define MEM_USB LUN_USB
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
LD_FILE = boards/samd21x18-bootloader.ld
22
USB_VID = 0x2341
33
USB_PID = 0x824D
4+
5+
FLASH_IMPL = internal_flash.c
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
LD_FILE = boards/samd21x18-bootloader.ld
22
USB_VID = 0x239A
33
USB_PID = 0x8015
4+
5+
FLASH_IMPL = internal_flash.c

atmel-samd/boards/metro_m0_flash/conf_access.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@
6868
/*! \name LUN 0 Definitions
6969
*/
7070
//! @{
71-
#define LUN_0_INCLUDE "rom_fs.h"
72-
#define Lun_0_test_unit_ready rom_fs_test_unit_ready
73-
#define Lun_0_read_capacity rom_fs_read_capacity
74-
#define Lun_0_unload NULL /* Can not be unloaded */
75-
#define Lun_0_wr_protect rom_fs_wr_protect
76-
#define Lun_0_removal rom_fs_removal
77-
#define Lun_0_usb_read_10 rom_fs_usb_read_10
78-
#define Lun_0_usb_write_10 rom_fs_usb_write_10
79-
#define LUN_0_NAME "\"On-Chip ROM\""
71+
#define LUN_0_INCLUDE "access_vfs.h"
72+
#define Lun_0_test_unit_ready vfs_test_unit_ready
73+
#define Lun_0_read_capacity vfs_read_capacity
74+
#define Lun_0_unload NULL
75+
#define Lun_0_wr_protect vfs_wr_protect
76+
#define Lun_0_removal vfs_removal
77+
#define Lun_0_usb_read_10 vfs_usb_read_10
78+
#define Lun_0_usb_write_10 vfs_usb_write_10
79+
#define LUN_0_NAME "\"MicroPython VFS[0]\""
8080
//! @}
8181

8282
#define MEM_USB LUN_USB
Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
1-
// LEDs
2-
#define MICROPY_HW_LED1 PIN_PA17 // red
31
// #define UART_REPL
42
#define USB_REPL
53

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

7+
#define MICROPY_HW_LED_MSC PIN_PA17
98
#define MICROPY_HW_LED_TX PIN_PA27
109
#define MICROPY_HW_LED_RX PIN_PB03
10+
11+
#define SPI_FLASH_BAUDRATE (1000000)
12+
13+
// Off-board flash
14+
// #define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E
15+
// #define SPI_FLASH_PAD0_PINMUX PINMUX_PA16C_SERCOM1_PAD0 // MISO D11
16+
// Use default pinmux for the chip select since we manage it ourselves.
17+
// #define SPI_FLASH_PAD1_PINMUX PINMUX_DEFAULT
18+
// #define SPI_FLASH_PAD2_PINMUX PINMUX_PA18C_SERCOM1_PAD2 // MOSI D10
19+
// #define SPI_FLASH_PAD3_PINMUX PINMUX_PA19C_SERCOM1_PAD3 // SCK D12
20+
// #define SPI_FLASH_CS PIN_PA17
21+
// #define SPI_FLASH_SERCOM SERCOM1
22+
23+
// On-board flash
24+
#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E
25+
#define SPI_FLASH_PAD0_PINMUX PINMUX_PA12D_SERCOM4_PAD0 // MISO
26+
// Use default pinmux for the chip select since we manage it ourselves.
27+
#define SPI_FLASH_PAD1_PINMUX PINMUX_DEFAULT // CS
28+
#define SPI_FLASH_PAD2_PINMUX PINMUX_PB10D_SERCOM4_PAD2 // MOSI
29+
#define SPI_FLASH_PAD3_PINMUX PINMUX_PB11D_SERCOM4_PAD3 // SCK
30+
#define SPI_FLASH_CS PIN_PA13
31+
#define SPI_FLASH_SERCOM SERCOM4
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
LD_FILE = boards/samd21x18-bootloader-external-flash.ld
22
USB_VID = 0x239A
33
USB_PID = 0x8015
4+
5+
FLASH_IMPL = spi_flash.c

atmel-samd/boards/metro_m0_flash/pins.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ PIN(PA19, false, NO_ADC_INPUT,
9292
TIMER(TC3, 0, 1, 1, PIN_PA19E_TC3_WO1, MUX_PA19E_TC3_WO1),
9393
TIMER(0, TCC0, 3, 3, PIN_PA19F_TCC0_WO3, MUX_PA19F_TCC0_WO3),
9494
SERCOM(SERCOM1, 3, PINMUX_PA19C_SERCOM1_PAD3),
95-
SERCOM(SERCOM3, 3, PINMUX_PA19C_SERCOM1_PAD3));
95+
SERCOM(SERCOM3, 3, PINMUX_PA19D_SERCOM3_PAD3));
9696
PIN(PA17, false, NO_ADC_INPUT,
9797
TIMER(0, TCC2, 1, 1, PIN_PA17E_TCC2_WO1, MUX_PA17E_TCC2_WO1),
9898
TIMER(0, TCC0, 3, 7, PIN_PA17F_TCC0_WO7, MUX_PA17F_TCC0_WO7),

0 commit comments

Comments
 (0)