1717import re
1818from os .path import join
1919
20+
2021from SCons .Script import (ARGUMENTS , COMMAND_LINE_TARGETS , AlwaysBuild ,
2122 Builder , Default , DefaultEnvironment )
23+ from platformio import util
2224
23-
24- def _get_flash_size (env ):
25- # use board's flash size by default
26- board_max_size = int (env .BoardConfig ().get ("upload.maximum_size" , 0 ))
27-
28- # check if user overrides LD Script
29- match = re .search (r"\.flash\.(\d+)(m|k).*\.ld" , env .GetActualLDScript ())
30- if match :
31- if match .group (2 ) == "k" :
32- board_max_size = int (match .group (1 )) * 1024
33- elif match .group (2 ) == "m" :
34- board_max_size = int (match .group (1 )) * 1024 * 1024
35-
36- return ("%dK" % (board_max_size / 1024 ) if board_max_size < 1048576
37- else "%dM" % (board_max_size / 1048576 ))
25+ #
26+ # Helpers
27+ #
3828
3929
4030def _get_board_f_flash (env ):
@@ -43,6 +33,96 @@ def _get_board_f_flash(env):
4333 return int (int (frequency ) / 1000000 )
4434
4535
36+ def _parse_size (value ):
37+ if isinstance (value , int ):
38+ return value
39+ elif value .isdigit ():
40+ return int (value )
41+ elif value .startswith ("0x" ):
42+ return int (value , 16 )
43+ elif value [- 1 ].upper () in ("K" , "M" ):
44+ base = 1024 if value [- 1 ].upper () == "K" else 1024 * 1024
45+ return int (value [:- 1 ]) * base
46+ return value
47+
48+
49+ @util .memoized ()
50+ def _parse_ld_sizes (ldscript_path ):
51+ assert ldscript_path
52+ result = {}
53+ # get flash size from board's manifest
54+ result ['flash_size' ] = int (env .BoardConfig ().get ("upload.maximum_size" , 0 ))
55+ # get flash size from LD script path
56+ match = re .search (r"\.flash\.(\d+[mk]).*\.ld" , ldscript_path )
57+ if match :
58+ result ['flash_size' ] = _parse_size (match .group (1 ))
59+
60+ appsize_re = re .compile (
61+ r"irom0_0_seg\s*:.+len\s*=\s*(0x[\da-f]+)" , flags = re .I )
62+ spiffs_re = re .compile (
63+ r"PROVIDE\s*\(\s*_SPIFFS_(\w+)\s*=\s*(0x[\da-f]+)\s*\)" , flags = re .I )
64+ with open (ldscript_path ) as fp :
65+ for line in fp .readlines ():
66+ line = line .strip ()
67+ if not line or line .startswith ("/*" ):
68+ continue
69+ match = appsize_re .search (line )
70+ if match :
71+ result ['app_size' ] = _parse_size (match .group (1 ))
72+ continue
73+ match = spiffs_re .search (line )
74+ if match :
75+ result ['spiffs_%s' % match .group (1 )] = _parse_size (
76+ match .group (2 ))
77+ return result
78+
79+
80+ def _get_flash_size (env ):
81+ ldsizes = _parse_ld_sizes (env .GetActualLDScript ())
82+ if ldsizes ['flash_size' ] < 1048576 :
83+ return "%dK" % (ldsizes ['flash_size' ] / 1024 )
84+ return "%dM" % (ldsizes ['flash_size' ] / 1048576 )
85+
86+
87+ def fetch_spiffs_size (env ):
88+ ldsizes = _parse_ld_sizes (env .GetActualLDScript ())
89+ for key in ldsizes :
90+ if key .startswith ("spiffs_" ):
91+ env [key .upper ()] = ldsizes [key ]
92+
93+ assert all ([
94+ k in env
95+ for k in ["SPIFFS_START" , "SPIFFS_END" , "SPIFFS_PAGE" , "SPIFFS_BLOCK" ]
96+ ])
97+
98+ # esptool flash starts from 0
99+ for k in ("SPIFFS_START" , "SPIFFS_END" ):
100+ _value = 0
101+ if env [k ] < 0x40300000 :
102+ _value = env [k ] & 0xFFFFF
103+ elif env [k ] < 0x411FB000 :
104+ _value = env [k ] & 0xFFFFFF
105+ _value -= 0x200000 # correction
106+ else :
107+ _value = env [k ] & 0xFFFFFF
108+ _value += 0xE00000 # correction
109+
110+ env [k ] = _value
111+
112+
113+ def __fetch_spiffs_size (target , source , env ):
114+ fetch_spiffs_size (env )
115+ return (target , source )
116+
117+
118+ def _update_max_upload_size (env ):
119+ ldsizes = _parse_ld_sizes (env .GetActualLDScript ())
120+ if ldsizes and "app_size" in ldsizes :
121+ env .BoardConfig ().update ("upload.maximum_size" , ldsizes ['app_size' ])
122+
123+
124+ ########################################################
125+
46126env = DefaultEnvironment ()
47127platform = env .PioPlatform ()
48128
@@ -170,53 +250,15 @@ def _get_board_f_flash(env):
170250 for f in env .get ("BUILD_FLAGS" , [])
171251])
172252
173- #
174- # SPIFFS
175- #
176-
177-
178- def fetch_spiffs_size (env ):
179- spiffs_re = re .compile (
180- r"PROVIDE\s*\(\s*_SPIFFS_(\w+)\s*=\s*(0x[\dA-F]+)\s*\)" )
181- with open (env .GetActualLDScript ()) as f :
182- for line in f .readlines ():
183- match = spiffs_re .search (line )
184- if not match :
185- continue
186- env ["SPIFFS_%s" % match .group (1 ).upper ()] = match .group (2 )
187-
188- assert all ([k in env for k in ["SPIFFS_START" , "SPIFFS_END" , "SPIFFS_PAGE" ,
189- "SPIFFS_BLOCK" ]])
190-
191- # esptool flash starts from 0
192- for k in ("SPIFFS_START" , "SPIFFS_END" ):
193- _value = 0
194- if int (env [k ], 16 ) < 0x40300000 :
195- _value = int (env [k ], 16 ) & 0xFFFFF
196- elif int (env [k ], 16 ) < 0x411FB000 :
197- _value = int (env [k ], 16 ) & 0xFFFFFF
198- _value -= 0x200000 # correction
199- else :
200- _value = int (env [k ], 16 ) & 0xFFFFFF
201- _value += 0xE00000 # correction
202-
203- env [k ] = hex (_value )
204-
205-
206- def __fetch_spiffs_size (target , source , env ):
207- fetch_spiffs_size (env )
208- return (target , source )
209-
210-
211253env .Append (
212254 BUILDERS = dict (
213255 DataToBin = Builder (
214256 action = env .VerboseAction (" " .join ([
215257 '"$MKSPIFFSTOOL"' ,
216258 "-c" , "$SOURCES" ,
217- "-p" , "${int( SPIFFS_PAGE, 16)} " ,
218- "-b" , "${int( SPIFFS_BLOCK, 16)} " ,
219- "-s" , "${int( SPIFFS_END, 16) - int( SPIFFS_START, 16) }" ,
259+ "-p" , "$SPIFFS_PAGE" ,
260+ "-b" , "$SPIFFS_BLOCK" ,
261+ "-s" , "${SPIFFS_END - SPIFFS_START}" ,
220262 "$TARGET"
221263 ]), "Building SPIFFS image from '$SOURCES' directory to $TARGET" ),
222264 emitter = __fetch_spiffs_size ,
@@ -388,6 +430,17 @@ def __fetch_spiffs_size(target, source, env):
388430AlwaysBuild (env .Alias ("nobuild" , target_firm ))
389431target_buildprog = env .Alias ("buildprog" , target_firm , target_firm )
390432
433+ # update max upload size based on CSV file
434+ if env .get ("PIOMAINPROG" ):
435+ env .AddPreAction (
436+ "checkprogsize" ,
437+ env .VerboseAction (
438+ lambda source , target , env : _update_max_upload_size (env ),
439+ "Retrieving maximum program size $SOURCE" ))
440+ # remove after PIO Core 3.6 release
441+ elif set (["checkprogsize" , "upload" ]) & set (COMMAND_LINE_TARGETS ):
442+ _update_max_upload_size (env )
443+
391444#
392445# Target: Print binary size
393446#
0 commit comments