2 # This script includes arduino specific config
12 if not os.path.isfile(f):
16 strs = file.readlines()
19 if len(str) > 0 and str[0] == '#':
24 dict.setdefault(str[0:idx], str[idx + 1:])
28 def __get_boards(dict):
32 idx = key.find('.name')
34 if key.endswith('.name'):
35 boards.append(key[0:idx])
38 def __get_cpu(dict, board):
42 idx = key.find(board + '.menu.cpu.')
43 start = len(board + '.menu.cpu.')
45 end = key.find('.', start)
58 def __get_board_info(board, key):
60 v = boards_info.get(board + '.menu.cpu.' + cpu + key)
62 v = boards_info.get(board + key)
64 v = boards_info.get(board + key)
67 def __search_files(path, pattern, ondisk=True, source=True, strings=False, recursive=True):
69 return Glob(pattern, ondisk, source, strings)
72 for root, dirnames, filenames in os.walk(path):
73 #BLE library examples throw lot of errors. We dont need examples.
74 if 'examples' not in root:
75 matches.extend(Glob(root + '/' + pattern, ondisk, source, strings))
78 # To make sure the src is built in 'BUILD_DIR' (by default it will be built at
79 # the same directory as the .c .cpp .S)
80 def __src_to_obj(env, srcs):
82 prefix = env.get('BOARD') + '_'
84 prefix += env.get('CPU') + '_'
86 build_dir = env.get('BUILD_DIR') + '/arduino/'
88 obj = src.path.replace(arduino_home, build_dir)
91 if env.get('OBJSUFFIX'):
92 obj += env.get('OBJSUFFIX')
93 objs.extend(env.Object(obj, src, OBJPREFIX=prefix))
96 def __import_lib(env, lib):
97 lib_path = arduino_home + '/libraries/' + lib
98 if not os.path.exists(lib_path):
99 if target_arch == 'avr':
100 lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib
102 lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib
104 if os.path.exists(lib_path + '/src'):
105 lib_path = lib_path + '/src'
107 env.AppendUnique(CPPPATH = [lib_path])
109 if os.path.exists(lib_path + '/utility'):
110 env.AppendUnique(CPPPATH = [lib_path + '/utility'])
113 lib_src.extend(__search_files(lib_path, '*.S'))
114 lib_src.extend(__search_files(lib_path, '*.c'))
115 lib_src.extend(__search_files(lib_path, '*.cpp'))
117 lib_obj = __src_to_obj(env, lib_src)
118 build_dir = env.get('BUILD_DIR')
120 lib_a = env.StaticLibrary(build_dir + lib, lib_obj)
122 lib_a = env.StaticLibrary(lib, lib_obj)
124 # If we link libSPI.a, the final binary is not getting launched
125 # on the board. Which is not the case if we directly use SPI.o.
127 if env.get('TARGET_ARCH') == 'arm':
130 if obj.name.endswith('SPI.o'):
131 env.PrependUnique(LIBS = [File(obj)])
133 env.AppendUnique(LIBS = [File(lib_a[0])])
135 env.PrependUnique(LIBS = [File(lib_a[0])])
137 def __build_core(env):
138 core_src = __search_files(core_folder, '*.S')
139 core_src.extend(__search_files(core_folder, '*.c'))
140 core_src.extend(__search_files(core_folder, '*.cpp'))
142 core_src.extend(__search_files(variant_folder, '*.S'))
143 core_src.extend(__search_files(variant_folder, '*.c'))
144 core_src.extend(__search_files(variant_folder, '*.cpp'))
146 core_obj = __src_to_obj(env, core_src)
147 build_dir = env.get('BUILD_DIR')
149 s_core = env.StaticLibrary(build_dir + 'core', core_obj)
151 s_core = env.StaticLibrary('core', core_obj)
152 env.AppendUnique(LIBS = [File(s_core[0])])
154 # To avoid compiler issue. Otherewise there may be warnings:
155 # undefined reference to '_exit' '_close', '_getpid' ...
156 # Above functions are used in libc.a and implemented in syscalls_sam3.c
157 if env.get('TARGET_ARCH') == 'arm':
159 if obj.name.endswith('syscalls_sam3.o'):
160 env.AppendUnique(LIBS = [File(obj)])
162 def __create_bin(env, source):
164 if target_arch == 'avr':
165 eep = env.Command(name + '.eep', source, 'avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $SOURCE $TARGET')
166 hex = env.Command(name + '.hex', source, 'avr-objcopy -O ihex -R .eeprom $SOURCE $TARGET')
168 hex = env.Command(name + '.hex', source, 'arm-none-eabi-objcopy -O binary $SOURCE $TARGET')
170 #Currently Mega and Due build is supported.
171 def __upload(env, binary):
172 if target_arch == 'avr':
173 protocol = __get_board_info(board, '.upload.protocol')
174 speed = __get_board_info(board, '.upload.speed')
175 port = '/dev/ttyACM0'
176 upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \
177 + mcu + ' -c' + protocol + ' -P' + port + ' -b' + speed + ' -D -Uflash:w:' + binary + ':i'
179 print "Upload command: %s" %upload_cmd
180 install_cmd = env.Command('install_cmd', None, upload_cmd)
181 env.Default('install_cmd')
183 uu = __get_board_info(board, '.upload.native_usb')
185 upload_cmd = 'stty -F /dev/' + port + ' speed 1200 cs8 -cstopb -parenb \n' + arduino_home + '/hardware/tools/bossac -i -d --port=' + port + ' -U ' + uu + ' -e -w -v -b ' + binary + ' -R'
186 print "Upload command: %s" %upload_cmd
187 install_cmd = env.Command('install_cmd', None, upload_cmd)
188 env.Default('install_cmd')
190 # Print the command line that to upload binary to the board
191 def __upload_help(env):
192 if target_arch == 'avr':
193 protocol = __get_board_info(board, '.upload.protocol')
194 speed = __get_board_info(board, '.upload.speed')
196 upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \
197 + mcu + ' -c' + protocol + ' -P<serial_port>' + ' -b' + speed + ' -D -Uflash:w:<hex_file>:i'
199 uu = __get_board_info(board, '.upload.native_usb')
200 upload_cmd = arduino_home + '/hardware/tools/bossac -i -d --port=<serial_port> -U ' + uu + ' -e -w -v -b <bin file> -R'
203 ===============================================================================
204 You can upload the bin file with following command line:
206 Help('\n $ ' + upload_cmd)
208 \nPlease replace <xxx> according to the actual situation.
209 ===============================================================================
212 # ARDUINO_HOME build option
213 help_vars = Variables()
214 help_vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
215 help_vars.Update(env)
216 Help(help_vars.GenerateHelpText(env))
218 target_arch = env.get('TARGET_ARCH')
219 arduino_home = env.get('ARDUINO_HOME')
222 ************************************* Error ***********************************
223 * Arduino root directory isn't set, you can set enviornment variable *
224 * ARDUINO_HOME or add it in command line as: *
225 * # scons ARDUINO_HOME=<path to arduino root directory> ... *
226 *******************************************************************************
230 # Overwrite suffixes and prefixes
231 if env['HOST_OS'] == 'win32':
232 env['OBJSUFFIX'] = '.o'
233 env['SHOBJSUFFIX'] = '.os'
234 env['LIBPREFIX'] = 'lib'
235 env['LIBSUFFIX'] = '.a'
236 env['SHLIBPREFIX'] = 'lib'
237 env['SHLIBSUFFIX'] = '.so'
238 env['LIBPREFIXES'] = ['lib']
239 env['LIBSUFFIXES'] = ['.a', '.so']
240 env['PROGSUFFIX'] = ''
241 elif platform.system().lower() == 'darwin':
242 env['SHLIBSUFFIX'] = '.so'
243 env['LIBSUFFIXES'] = ['.a', '.so']
244 env['PROGSUFFIX'] = ''
246 # Debug/release relative flags
247 if env.get('RELEASE'):
248 env.AppendUnique(CCFLAGS = ['-Os'])
249 env.AppendUnique(CPPDEFINES = ['NDEBUG'])
251 env.AppendUnique(CCFLAGS = ['-g'])
256 if os.path.exists(arduino_home + '/lib/version.txt'):
257 vf = open(arduino_home + '/lib/version.txt', 'r')
258 version = vf.readline().replace('.', '')
261 ************************************* Error ***********************************
262 * Can't find version file (lib/version.txt), please check if (%s)
263 * is arduino root directory. *
264 *******************************************************************************
268 if version[0:2] == '10':
270 boards_info = __parse_config(arduino_home + '/hardware/arduino/boards.txt')
271 env.PrependENVPath('PATH', arduino_home + '/hardware/tools/avr/bin/')
272 env.Replace(CC = 'avr-gcc')
273 env.Replace(CXX = 'avr-gcc')
274 env.Replace(AR = 'avr-ar')
275 env.Replace(AS = 'avr-as')
276 env.Replace(LINK = 'avr-gcc')
277 env.Replace(RANLIB = 'avr-ranlib')
278 if target_arch != 'avr':
280 ************************************* Error ***********************************
281 * Arduino 1.0.x IDE only support 'avr', to support other arch at least 1.5.x *
283 *******************************************************************************
288 if target_arch == 'avr':
289 boards_info = __parse_config(arduino_home + '/hardware/arduino/avr/boards.txt')
290 platform_info = __parse_config(arduino_home + '/hardware/arduino/avr/platform.txt')
291 elif target_arch == 'arm':
292 boards_info = __parse_config(arduino_home + '/hardware/arduino/sam/boards.txt')
293 platform_info = __parse_config(arduino_home + '/hardware/arduino/sam/platform.txt')
296 ************************************* Error ***********************************
297 * CPU arch %s isn't supported currently.
298 *******************************************************************************
301 #Board option, let user to select the board
302 boards = __get_boards(boards_info)
303 help_vars = Variables()
304 help_vars.Add(EnumVariable('BOARD', 'arduino board', boards[0], boards))
305 help_vars.Update(env)
306 Help(help_vars.GenerateHelpText(env))
309 board = env.get('BOARD')
310 cpus = __get_cpu(boards_info, board)
312 help_vars = Variables()
313 help_vars.Add(EnumVariable('CPU', 'arduino board cpu', cpus[0], cpus))
314 help_vars.Update(env)
315 Help(help_vars.GenerateHelpText(env))
317 # Arduino commom flags
319 board = env.get('BOARD')
320 mcu = __get_board_info(board, '.build.mcu')
321 f_cpu = __get_board_info(board, '.build.f_cpu')
322 usb_vid = __get_board_info(board, '.build.vid')
323 usb_pid = __get_board_info(board, '.build.pid')
324 variant = __get_board_info(board, '.build.variant')
327 usb_vid = __get_board_info(board, '.vid.0')
329 usb_pid = __get_board_info(board, '.pid.0')
332 core_base = arduino_home + '/hardware/arduino/'
334 if target_arch == 'avr':
335 core_base = arduino_home + '/hardware/arduino/avr/'
337 core_base = arduino_home + '/hardware/arduino/sam/'
339 variant_folder = core_base + 'variants/' + variant
340 env.AppendUnique(CPPPATH = [variant_folder])
342 core = __get_board_info(board, '.build.core')
343 core_folder = core_base + 'cores/' + core + '/'
344 env.AppendUnique(CPPPATH = [core_folder])
347 comm_flags = ['-std=c99']
349 comm_flags.extend(['-mmcu=' + mcu])
351 comm_flags.extend(['-DF_CPU=' + f_cpu])
352 comm_flags.extend(['-DARDUINO=' + version])
354 comm_flags.extend(['-DUSB_VID=' + usb_vid])
356 comm_flags.extend(['-DUSB_PID=' + usb_pid])
358 env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
359 env.AppendUnique(ASFLAGS = comm_flags)
361 env.AppendUnique(CFLAGS = ['-Os', '-ffunction-sections', '-fdata-sections', '-MMD'])
362 env.AppendUnique(CFLAGS = comm_flags)
364 env.AppendUnique(CXXFLAGS = ['-Os', '-fno-exceptions', '-ffunction-sections', '-fdata-sections','-MMD'])
365 env.AppendUnique(CXXFLAGS = comm_flags)
367 env.AppendUnique(LINKFLAGS = ['-Os'])
368 if mcu == 'atmega2560':
369 env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections,--relax'])
371 env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections'])
372 env.AppendUnique(LINKFLAGS = ['-mmcu=' + mcu])
374 if target_arch == 'avr':
375 cpu_flag = '-mmcu=' + mcu
377 cpu_flag = '-mcpu=' + mcu
379 comm_flag = [cpu_flag, '-DF_CPU=' + f_cpu, '-DARDUINO=' + version, '-DARDUINO_' + __get_board_info(board, '.build.board')]
380 if target_arch == 'arm':
381 # As of 1.5.8 the arduino headers had asm bugs with ARM and
382 # require gnu99 to be used.
383 comm_flag.extend(['-std=gnu99', '-DARDUINO_ARCH_SAM'])
385 comm_flag.extend(['-std=c99', '-DARDUINO_ARCH_AVR'])
387 compiler_path = platform_info.get('compiler.path')
388 compiler_path = compiler_path.replace('{runtime.ide.path}', arduino_home)
389 env.PrependENVPath('PATH', compiler_path)
390 env.Replace(CC = platform_info.get('compiler.c.cmd'))
391 env.Replace(CXX = platform_info.get('compiler.cpp.cmd'))
392 env.Replace(AR = platform_info.get('compiler.ar.cmd'))
393 if target_arch == 'arm':
394 env.AppendUnique(CPPPATH = [arduino_home + '/hardware/arduino/sam/system/libsam',
395 arduino_home + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include/',
396 arduino_home + '/hardware/arduino/sam/system//CMSIS/Device/ATMEL'])
397 env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
398 env.AppendUnique(ASFLAGS = comm_flag)
399 env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags')))
400 env.AppendUnique(CXXFLAGS = Split(platform_info.get('compiler.cpp.flags')))
401 env.AppendUnique(ARFLAGS = Split(platform_info.get('compiler.ar.flags')))
402 env.AppendUnique(CCFLAGS = comm_flag)
404 extra_flags = __get_board_info(board, '.build.extra_flags')
406 extra_flags = extra_flags.replace('{build.usb_flags}', '')
407 env.AppendUnique(CCFLAGS = Split(extra_flags))
408 usb_flags = ['-DUSB_VID=' + usb_vid, '-DUSB_PID=' + usb_pid, '-DUSBCON', '-DUSB_MANUFACTURER="Unknown"']
409 env.AppendUnique(CCFLAGS = usb_flags)
411 if target_arch == 'arm':
412 env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag,
413 '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript'),
414 '-Wl,-Map,' + env.get('BUILD_DIR') + 'arduino_prj.map'])
415 env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group'))
417 variant_system_lib = __get_board_info(board, '.build.variant_system_lib')
418 if variant_system_lib:
419 if variant_folder.find(' ') >= 0:
420 variant_folder = '"' + variant_folder + '"'
421 env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS '
422 + variant_folder + '/' + variant_system_lib + ' -Wl,--end-group')
424 env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group')
426 env.AppendUnique(LINKFLAGS = Split(platform_info.get('compiler.c.elf.flags')))
427 env.AppendUnique(LINKFLAGS = [cpu_flag])
428 env.AppendUnique(LIBS = 'm')
429 env.Replace(ARCOM = '$AR ' + platform_info.get('compiler.ar.flags') + ' $TARGET $SOURCES')
433 env.AddMethod(__import_lib, "ImportLib") #import arduino library
434 #env.AddMethod(__build_core, "BuildCore") #build arduino core
435 env.AddMethod(__create_bin, "CreateBin") #create binary files(.eep and .hex)
436 env.AddMethod(__upload, "Upload") #Upload binary to board
437 env.AddMethod(__upload_help, "UploadHelp") #print the command line that to upload binary to the boardf