Teensy development platform for PlatformIO compatible with GCC10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
7.5KB

  1. # Copyright 2014-present PlatformIO <contact@platformio.org>
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import sys
  15. from platform import system
  16. from os import makedirs
  17. from os.path import isdir, isfile, join
  18. from SCons.Script import (COMMAND_LINE_TARGETS, AlwaysBuild, Builder, Default,
  19. DefaultEnvironment)
  20. env = DefaultEnvironment()
  21. platform = env.PioPlatform()
  22. board_config = env.BoardConfig()
  23. env.Replace(
  24. ARFLAGS=["rc"],
  25. SIZEPROGREGEXP=r"^(?:\.text|\.data|\.rodata|\.text.align|\.ARM.exidx)\s+(\d+).*",
  26. SIZEDATAREGEXP=r"^(?:\.data|\.bss|\.noinit)\s+(\d+).*",
  27. SIZECHECKCMD="$SIZETOOL -A -d $SOURCES",
  28. PROGSUFFIX=".elf"
  29. )
  30. # Allow user to override via pre:script
  31. if env.get("PROGNAME", "program") == "program":
  32. env.Replace(PROGNAME="firmware")
  33. if "BOARD" in env and board_config.get("build.core") == "teensy":
  34. env.Replace(
  35. AR="avr-ar",
  36. AS="avr-as",
  37. CC="avr-gcc",
  38. CXX="avr-g++",
  39. GDB="avr-gdb",
  40. OBJCOPY="avr-objcopy",
  41. RANLIB="avr-ranlib",
  42. SIZETOOL="avr-size",
  43. SIZEPRINTCMD='$SIZETOOL --mcu=$BOARD_MCU -C -d $SOURCES'
  44. )
  45. env.Append(
  46. BUILDERS=dict(
  47. ElfToEep=Builder(
  48. action=env.VerboseAction(" ".join([
  49. "$OBJCOPY",
  50. "-O",
  51. "ihex",
  52. "-j",
  53. ".eeprom",
  54. '--set-section-flags=.eeprom="alloc,load"',
  55. "--no-change-warnings",
  56. "--change-section-lma",
  57. ".eeprom=0",
  58. "$SOURCES",
  59. "$TARGET"
  60. ]), "Building $TARGET"),
  61. suffix=".eep"
  62. ),
  63. ElfToHex=Builder(
  64. action=env.VerboseAction(" ".join([
  65. "$OBJCOPY",
  66. "-O",
  67. "ihex",
  68. "-R",
  69. ".eeprom",
  70. "$SOURCES",
  71. "$TARGET"
  72. ]), "Building $TARGET"),
  73. suffix=".hex"
  74. )
  75. )
  76. )
  77. if not env.get("PIOFRAMEWORK"):
  78. env.SConscript("frameworks/_bare_avr.py")
  79. elif "BOARD" in env and board_config.get("build.core") in ("teensy3", "teensy4", "teensy41"):
  80. env.Replace(
  81. AR="arm-none-eabi-ar",
  82. AS="arm-none-eabi-as",
  83. CC="arm-none-eabi-gcc",
  84. CXX="arm-none-eabi-g++",
  85. GDB="arm-none-eabi-gdb",
  86. OBJCOPY="arm-none-eabi-objcopy",
  87. RANLIB="arm-none-eabi-gcc-ranlib",
  88. SIZETOOL="arm-none-eabi-size",
  89. SIZEPRINTCMD='$SIZETOOL -B -d $SOURCES'
  90. )
  91. env.Append(
  92. BUILDERS=dict(
  93. ElfToBin=Builder(
  94. action=env.VerboseAction(" ".join([
  95. "$OBJCOPY",
  96. "-O",
  97. "binary",
  98. "$SOURCES",
  99. "$TARGET"
  100. ]), "Building $TARGET"),
  101. suffix=".bin"
  102. ),
  103. ElfToHex=Builder(
  104. action=env.VerboseAction(" ".join([
  105. "$OBJCOPY",
  106. "-O",
  107. "ihex",
  108. "-R",
  109. ".eeprom",
  110. "$SOURCES",
  111. "$TARGET"
  112. ]), "Building $TARGET"),
  113. suffix=".hex"
  114. )
  115. )
  116. )
  117. if not env.get("PIOFRAMEWORK"):
  118. env.SConscript("frameworks/_bare_arm.py")
  119. #
  120. # Target: Build executable and linkable firmware
  121. #
  122. target_elf = None
  123. if "nobuild" in COMMAND_LINE_TARGETS:
  124. target_elf = join("$BUILD_DIR", "${PROGNAME}.elf")
  125. target_firm = join("$BUILD_DIR", "${PROGNAME}.hex")
  126. else:
  127. target_elf = env.BuildProgram()
  128. target_firm = env.ElfToHex(join("$BUILD_DIR", "${PROGNAME}"), target_elf)
  129. AlwaysBuild(env.Alias("nobuild", target_firm))
  130. target_buildprog = env.Alias("buildprog", target_firm, target_firm)
  131. #
  132. # Target: Print binary size
  133. #
  134. target_size = env.Alias(
  135. "size", target_elf,
  136. env.VerboseAction("$SIZEPRINTCMD", "Calculating size $SOURCE"))
  137. AlwaysBuild(target_size)
  138. #
  139. # Target: Upload by default firmware file
  140. #
  141. # Force Teensy CLI when Teensy App is not available (Linux ARM)
  142. if env.subst("$UPLOAD_PROTOCOL") == "teensy-gui" and not isfile(
  143. join(
  144. platform.get_package_dir("tool-teensy") or "",
  145. "teensy_post_compile.exe"
  146. if system() == "Windows" else "teensy_post_compile")):
  147. env.Replace(UPLOAD_PROTOCOL="teensy-cli")
  148. upload_protocol = env.subst("$UPLOAD_PROTOCOL")
  149. upload_actions = []
  150. if upload_protocol.startswith("jlink"):
  151. def _jlink_cmd_script(env, source):
  152. build_dir = env.subst("$BUILD_DIR")
  153. if not isdir(build_dir):
  154. makedirs(build_dir)
  155. script_path = join(build_dir, "upload.jlink")
  156. commands = ["h", "loadfile %s" % source, "r", "q"]
  157. with open(script_path, "w") as fp:
  158. fp.write("\n".join(commands))
  159. return script_path
  160. env.Replace(
  161. __jlink_cmd_script=_jlink_cmd_script,
  162. UPLOADER="JLink.exe" if system() == "Windows" else "JLinkExe",
  163. UPLOADERFLAGS=[
  164. "-device", board_config.get("debug", {}).get("jlink_device"),
  165. "-speed", "4000",
  166. "-if", ("jtag" if upload_protocol == "jlink-jtag" else "swd"),
  167. "-autoconnect", "1",
  168. "-NoGui", "1"
  169. ],
  170. UPLOADCMD='$UPLOADER $UPLOADERFLAGS -CommanderScript "${__jlink_cmd_script(__env__, SOURCE)}"'
  171. )
  172. upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
  173. elif upload_protocol == "teensy-cli":
  174. env.Replace(
  175. REBOOTER="teensy_reboot",
  176. UPLOADER="teensy_loader_cli",
  177. UPLOADERFLAGS=[
  178. "-mmcu=$BOARD_MCU",
  179. "-w", # wait for device to appear
  180. "-s", # soft reboot if device not online
  181. "-v" # verbose output
  182. ],
  183. UPLOADCMD="$UPLOADER $UPLOADERFLAGS $SOURCES"
  184. )
  185. upload_actions = [
  186. env.VerboseAction("$REBOOTER -s", "Rebooting..."),
  187. env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")
  188. ]
  189. elif upload_protocol == "teensy-gui":
  190. env.Replace(
  191. UPLOADER="teensy_post_compile",
  192. UPLOADERFLAGS=[
  193. "-file=${PROGNAME}", '-path="$BUILD_DIR"',
  194. "-tools=%s" % (platform.get_package_dir("tool-teensy") or ""),
  195. "-board=%s" % board_config.id.upper(),
  196. "-reboot"
  197. ],
  198. UPLOADCMD="$UPLOADER $UPLOADERFLAGS"
  199. )
  200. upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
  201. # custom upload tool
  202. elif upload_protocol == "custom":
  203. upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]
  204. else:
  205. sys.stderr.write("Warning! Unknown upload protocol %s\n" % upload_protocol)
  206. AlwaysBuild(env.Alias("upload", target_firm, upload_actions))
  207. #
  208. # Default targets
  209. #
  210. Default([target_buildprog, target_size])