2424 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525 * THE SOFTWARE.
2626 */
27+
2728#include "supervisor/internal_flash.h"
2829
2930#include <stdint.h>
3233
3334#include "extmod/vfs.h"
3435#include "extmod/vfs_fat.h"
36+
3537#include "py/mphal.h"
3638#include "py/obj.h"
3739#include "py/runtime.h"
38- #include "lib/oofatfs/ff.h"
3940
40- #include "components/spi_flash/include/esp_partition.h"
41+ #include "esp_ota_ops.h"
42+ #include "esp_partition.h"
4143
44+ #include "supervisor/filesystem.h"
4245#include "supervisor/flash.h"
4346#include "supervisor/usb.h"
4447
45- STATIC const esp_partition_t * _partition ;
48+ #define OP_READ 0
49+ #define OP_WRITE 1
4650
4751// TODO: Split the caching out of supervisor/shared/external_flash so we can use it.
4852#define SECTOR_SIZE 4096
4953STATIC uint8_t _cache [SECTOR_SIZE ];
5054STATIC uint32_t _cache_lba = 0xffffffff ;
5155
56+ #if CIRCUITPY_STORAGE_EXTEND
57+ #if FF_MAX_SS == FF_MIN_SS
58+ #define SECSIZE (fs ) (FF_MIN_SS)
59+ #else
60+ #define SECSIZE (fs ) ((fs)->ssize)
61+ #endif // FF_MAX_SS == FF_MIN_SS
62+ STATIC DWORD fatfs_bytes (void ) {
63+ FATFS * fatfs = filesystem_circuitpy ();
64+ return (fatfs -> csize * SECSIZE (fatfs )) * (fatfs -> n_fatent - 2 );
65+ }
66+ STATIC bool storage_extended = true;
67+ STATIC const esp_partition_t * _partition [2 ];
68+ #else
69+ STATIC const esp_partition_t * _partition [1 ];
70+ #endif // CIRCUITPY_STORAGE_EXTEND
71+
5272void supervisor_flash_init (void ) {
53- _partition = esp_partition_find_first (ESP_PARTITION_TYPE_DATA ,
73+ if (_partition [0 ] != NULL ) {
74+ return ;
75+ }
76+ _partition [0 ] = esp_partition_find_first (ESP_PARTITION_TYPE_DATA ,
5477 ESP_PARTITION_SUBTYPE_DATA_FAT ,
5578 NULL );
79+ #if CIRCUITPY_STORAGE_EXTEND
80+ _partition [1 ] = esp_ota_get_next_update_partition (NULL );
81+ #endif
5682}
5783
5884uint32_t supervisor_flash_get_block_size (void ) {
5985 return FILESYSTEM_BLOCK_SIZE ;
6086}
6187
6288uint32_t supervisor_flash_get_block_count (void ) {
63- return _partition -> size / FILESYSTEM_BLOCK_SIZE ;
89+ #if CIRCUITPY_STORAGE_EXTEND
90+ return ((storage_extended ) ? (_partition [0 ]-> size + _partition [1 ]-> size ) : _partition [0 ]-> size ) / FILESYSTEM_BLOCK_SIZE ;
91+ #else
92+ return _partition [0 ]-> size / FILESYSTEM_BLOCK_SIZE ;
93+ #endif
6494}
6595
6696void port_internal_flash_flush (void ) {
97+ }
6798
99+ STATIC void single_partition_rw (const esp_partition_t * partition , uint8_t * data ,
100+ const uint32_t offset , const uint32_t size_total , const bool op ) {
101+ if (op == OP_READ ) {
102+ esp_partition_read (partition , offset , data , size_total );
103+ } else {
104+ esp_partition_erase_range (partition , offset , size_total );
105+ esp_partition_write (partition , offset , _cache , size_total );
106+ }
107+ }
108+
109+ #if CIRCUITPY_STORAGE_EXTEND
110+ STATIC void multi_partition_rw (uint8_t * data ,
111+ const uint32_t offset , const uint32_t size_total , const bool op ) {
112+ if (offset > _partition [0 ]-> size ) {
113+ // only r/w partition 1
114+ single_partition_rw (_partition [1 ], data , (offset - _partition [0 ]-> size ), size_total , op );
115+ } else if ((offset + size_total ) > _partition [0 ]-> size ) {
116+ // first r/w partition 0, then partition 1
117+ uint32_t size_0 = _partition [0 ]-> size - offset ;
118+ uint32_t size_1 = size_total - size_0 ;
119+ if (op == OP_READ ) {
120+ esp_partition_read (_partition [0 ], offset , data , size_0 );
121+ esp_partition_read (_partition [1 ], 0 , (data + size_0 ), size_1 );
122+ } else {
123+ esp_partition_erase_range (_partition [0 ], offset , size_0 );
124+ esp_partition_write (_partition [0 ], offset , _cache , size_0 );
125+ esp_partition_erase_range (_partition [1 ], 0 , size_1 );
126+ esp_partition_write (_partition [1 ], 0 , (_cache + size_0 ), size_1 );
127+ }
128+ } else {
129+ // only r/w partition 0
130+ single_partition_rw (_partition [0 ], data , offset , size_total , op );
131+ }
68132}
133+ #endif
69134
70135mp_uint_t supervisor_flash_read_blocks (uint8_t * dest , uint32_t block , uint32_t num_blocks ) {
71- esp_partition_read (_partition ,
72- block * FILESYSTEM_BLOCK_SIZE ,
73- dest ,
74- num_blocks * FILESYSTEM_BLOCK_SIZE );
75- return 0 ;
136+ const uint32_t offset = block * FILESYSTEM_BLOCK_SIZE ;
137+ const uint32_t read_total = num_blocks * FILESYSTEM_BLOCK_SIZE ;
138+ #if CIRCUITPY_STORAGE_EXTEND
139+ multi_partition_rw (dest , offset , read_total , OP_READ );
140+ #else
141+ single_partition_rw (_partition [0 ], dest , offset , read_total , OP_READ );
142+ #endif
143+ return 0 ; // success
76144}
77145
78146mp_uint_t supervisor_flash_write_blocks (const uint8_t * src , uint32_t lba , uint32_t num_blocks ) {
@@ -82,12 +150,8 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
82150 uint32_t block_address = lba + block ;
83151 uint32_t sector_offset = block_address / blocks_per_sector * SECTOR_SIZE ;
84152 uint8_t block_offset = block_address % blocks_per_sector ;
85-
86153 if (_cache_lba != block_address ) {
87- esp_partition_read (_partition ,
88- sector_offset ,
89- _cache ,
90- SECTOR_SIZE );
154+ supervisor_flash_read_blocks (_cache , sector_offset / FILESYSTEM_BLOCK_SIZE , blocks_per_sector );
91155 _cache_lba = sector_offset ;
92156 }
93157 for (uint8_t b = block_offset ; b < blocks_per_sector ; b ++ ) {
@@ -100,15 +164,34 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
100164 FILESYSTEM_BLOCK_SIZE );
101165 block ++ ;
102166 }
103- esp_partition_erase_range ( _partition , sector_offset , SECTOR_SIZE );
104- esp_partition_write ( _partition ,
105- sector_offset ,
106- _cache ,
107- SECTOR_SIZE );
167+ #if CIRCUITPY_STORAGE_EXTEND
168+ multi_partition_rw ( _cache , sector_offset , SECTOR_SIZE , OP_WRITE );
169+ #else
170+ single_partition_rw ( _partition [ 0 ], _cache , sector_offset , SECTOR_SIZE , OP_READ );
171+ #endif
108172 }
109-
110173 return 0 ; // success
111174}
112175
113176void supervisor_flash_release_cache (void ) {
114177}
178+
179+ void supervisor_flash_set_extended (bool extended ) {
180+ #if CIRCUITPY_STORAGE_EXTEND
181+ storage_extended = extended ;
182+ #endif
183+ }
184+
185+ bool supervisor_flash_get_extended (void ) {
186+ #if CIRCUITPY_STORAGE_EXTEND
187+ return storage_extended ;
188+ #else
189+ return false;
190+ #endif
191+ }
192+
193+ void supervisor_flash_update_extended (void ) {
194+ #if CIRCUITPY_STORAGE_EXTEND
195+ storage_extended = (_partition [0 ]-> size < fatfs_bytes ());
196+ #endif
197+ }
0 commit comments