1616from platform import system
1717from os import makedirs
1818from os .path import isdir , join
19+ import re
1920
2021from platformio .util import get_serial_ports
2122
@@ -67,6 +68,9 @@ def generate_uf2(target, source, env):
6768
6869 ARFLAGS = ["rc" ],
6970
71+ MKFSTOOL = "mklittlefs" ,
72+ PICO_FS_IMAGE_NAME = env .get ("PICO_FS_IMAGE_NAME" , "littlefs" ),
73+
7074 SIZEPROGREGEXP = r"^(?:\.text|\.data|\.rodata|\.text.align|\.ARM.exidx)\s+(\d+).*" ,
7175 SIZEDATAREGEXP = r"^(?:\.data|\.bss|\.noinit)\s+(\d+).*" ,
7276 SIZECHECKCMD = "$SIZETOOL -A -d $SOURCES" ,
@@ -109,6 +113,100 @@ def generate_uf2(target, source, env):
109113if not env .get ("PIOFRAMEWORK" ):
110114 env .SConscript ("frameworks/_bare.py" )
111115
116+
117+ def convert_size_expression_to_int (expression ):
118+ conversion_factors = {
119+ "M" : 1024 * 1024 ,
120+ "MB" : 1024 * 1024 ,
121+ "K" : 1024 ,
122+ "KB" : 1024 ,
123+ "B" : 1 ,
124+ "" : 1 # giving no conversion factor is factor 1.
125+ }
126+ # match <floating pointer number><conversion factor>.
127+ extract_regex = r'^((?:[0-9]*[.])?[0-9]+)([mkbMKB]*)$'
128+ res = re .findall (extract_regex , expression )
129+ # unparsable expression? Warning.
130+ if len (res ) == 0 :
131+ sys .stderr .write (
132+ "Error: Could not parse filesystem size expression '%s'."
133+ " Will treat as size = 0.\n " % str (expression ))
134+ return 0
135+ # access first result
136+ number , factor = res [0 ]
137+ number = float (number )
138+ number *= conversion_factors [factor .upper ()]
139+ return int (number )
140+
141+ def fetch_fs_size (env ):
142+ # follow generation formulas from makeboards.py for Earle Philhower core
143+ # given the total flash size, a user can specify
144+ # the amount for the filesystem (0MB, 2MB, 4MB, 8MB, 16MB)
145+ # via board_build.filesystem_size,
146+ # and we will calculate the flash size and eeprom size from that.
147+ flash_size = board .get ("upload.maximum_size" )
148+ filesystem_size = board .get ("build.filesystem_size" , "0MB" )
149+ filesystem_size_int = convert_size_expression_to_int (filesystem_size )
150+
151+ maximum_size = flash_size - 4096 - filesystem_size_int
152+
153+ print ("Flash size: %.2fMB" % (flash_size / 1024.0 / 1024.0 ))
154+ print ("Sketch size: %.2fMB" % (maximum_size / 1024.0 / 1024.0 ))
155+ print ("Filesystem size: %.2fMB" % (filesystem_size_int / 1024.0 / 1024.0 ))
156+
157+ flash_length = maximum_size
158+ eeprom_start = 0x10000000 + flash_size - 4096
159+ fs_start = 0x10000000 + flash_size - 4096 - filesystem_size_int
160+ fs_end = 0x10000000 + flash_size - 4096
161+
162+ if maximum_size <= 0 :
163+ sys .stderr .write (
164+ "Error: Filesystem too large for given flash. "
165+ "Can at max be flash size - 4096 bytes. "
166+ "Available sketch size with current "
167+ "config would be %d bytes.\n " % maximum_size )
168+ sys .stderr .flush ()
169+ env .Exit (- 1 )
170+
171+ env ["PICO_FLASH_LENGTH" ] = flash_length
172+ env ["PICO_EEPROM_START" ] = eeprom_start
173+ env ["FS_START" ] = fs_start
174+ env ["FS_END" ] = fs_end
175+ # LittleFS configuration paramters taken from
176+ # https://github.com/earlephilhower/arduino-pico-littlefs-plugin/blob/master/src/PicoLittleFS.java
177+ env ["FS_PAGE" ] = 256
178+ env ["FS_BLOCK" ] = 4096
179+
180+ print ("Maximium size: %d Flash Length: %d "
181+ "EEPROM Start: %d Filesystem start %d "
182+ "Filesystem end %s" %
183+ (maximum_size ,flash_length , eeprom_start , fs_start , fs_end ))
184+
185+
186+ def __fetch_fs_size (target , source , env ):
187+ fetch_fs_size (env )
188+ return (target , source )
189+
190+ env .Append (
191+ BUILDERS = dict (
192+ DataToBin = Builder (
193+ action = env .VerboseAction (" " .join ([
194+ '"$MKFSTOOL"' ,
195+ "-c" , "$SOURCES" ,
196+ "-p" , "$FS_PAGE" ,
197+ "-b" , "$FS_BLOCK" ,
198+ "-s" , "${FS_END - FS_START}" ,
199+ "$TARGET"
200+ ]), "Building file system image from '$SOURCES' directory to $TARGET" ),
201+ emitter = __fetch_fs_size ,
202+ source_factory = env .Dir ,
203+ suffix = ".bin"
204+ )
205+ )
206+ )
207+
208+ env ["fetch_fs_size" ] = fetch_fs_size
209+
112210#
113211# Target: Build executable and linkable firmware
114212#
@@ -119,16 +217,37 @@ def generate_uf2(target, source, env):
119217 target_firm = join ("$BUILD_DIR" , "${PROGNAME}.bin" )
120218else :
121219 target_elf = env .BuildProgram ()
122- target_firm = env .ElfToBin (join ("$BUILD_DIR" , "${PROGNAME}" ), target_elf )
123- env .Depends (target_firm , "checkprogsize" )
124-
220+ if set (["buildfs" , "uploadfs" ]) & set (COMMAND_LINE_TARGETS ):
221+ target_firm = env .DataToBin (
222+ join ("$BUILD_DIR" , "${PICO_FS_IMAGE_NAME}" ), "$PROJECTDATA_DIR" )
223+ AlwaysBuild (target_firm )
224+ else :
225+ target_firm = env .ElfToBin (join ("$BUILD_DIR" , "${PROGNAME}" ), target_elf )
226+ env .Depends (target_firm , "checkprogsize" )
227+
228+ env .AddPlatformTarget ("buildfs" , target_firm , target_firm , "Build Filesystem Image" )
125229AlwaysBuild (env .Alias ("nobuild" , target_firm ))
126230target_buildprog = env .Alias ("buildprog" , target_firm , target_firm )
127231
128232env .AddPostAction (
129233 target_elf , env .VerboseAction (generate_uf2 , "Generating UF2 image" )
130234)
131235
236+ def _update_max_upload_size (env ):
237+ fetch_fs_size (env )
238+ env .BoardConfig ().update ("upload.maximum_size" , env ["PICO_FLASH_LENGTH" ])
239+
240+ # update max upload size based on CSV file
241+ if env .get ("PIOMAINPROG" ):
242+ env .AddPreAction (
243+ "checkprogsize" ,
244+ env .VerboseAction (
245+ lambda source , target , env : _update_max_upload_size (env ),
246+ "Retrieving maximum program size $SOURCE" ))
247+ # remove after PIO Core 3.6 release
248+ elif set (["checkprogsize" , "upload" ]) & set (COMMAND_LINE_TARGETS ):
249+ _update_max_upload_size (env )
250+
132251#
133252# Target: Print binary size
134253#
@@ -232,7 +351,7 @@ def _jlink_cmd_script(env, source):
232351 sys .stderr .write ("Warning! Unknown upload protocol %s\n " % upload_protocol )
233352
234353AlwaysBuild (env .Alias ("upload" , upload_source , upload_actions ))
235-
354+ env . AddPlatformTarget ( "uploadfs" , target_firm , upload_actions , "Upload Filesystem Image" )
236355#
237356# Default targets
238357#
0 commit comments