efr32.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. # Copyright (c) 2021 Project CHIP Authors
  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 os
  15. import shlex
  16. import subprocess
  17. from enum import Enum, auto
  18. from .gn import GnBuilder
  19. class Efr32App(Enum):
  20. LIGHT = auto()
  21. LOCK = auto()
  22. SWITCH = auto()
  23. WINDOW_COVERING = auto()
  24. THERMOSTAT = auto()
  25. PUMP = auto()
  26. UNIT_TEST = auto()
  27. def ExampleName(self):
  28. if self == Efr32App.LIGHT:
  29. return 'lighting-app'
  30. elif self == Efr32App.LOCK:
  31. return 'lock-app'
  32. elif self == Efr32App.SWITCH:
  33. return 'light-switch-app'
  34. elif self == Efr32App.WINDOW_COVERING:
  35. return 'window-app'
  36. elif self == Efr32App.THERMOSTAT:
  37. return 'thermostat'
  38. elif self == Efr32App.PUMP:
  39. return 'pump-app'
  40. else:
  41. raise Exception('Unknown app type: %r' % self)
  42. def AppNamePrefix(self):
  43. if self == Efr32App.LIGHT:
  44. return 'matter-silabs-lighting-example'
  45. elif self == Efr32App.LOCK:
  46. return 'matter-silabs-lock-example'
  47. elif self == Efr32App.SWITCH:
  48. return 'matter-silabs-light-switch-example'
  49. elif self == Efr32App.WINDOW_COVERING:
  50. return 'matter-silabs-window-example'
  51. elif self == Efr32App.THERMOSTAT:
  52. return 'matter-silabs-thermostat-example'
  53. elif self == Efr32App.PUMP:
  54. return 'matter-silabs-pump-example'
  55. elif self == Efr32App.UNIT_TEST:
  56. return 'matter-silabs-device_tests'
  57. else:
  58. raise Exception('Unknown app type: %r' % self)
  59. def FlashBundleName(self):
  60. if self == Efr32App.LIGHT:
  61. return 'lighting_app.flashbundle.txt'
  62. elif self == Efr32App.LOCK:
  63. return 'lock_app.flashbundle.txt'
  64. elif self == Efr32App.SWITCH:
  65. return 'light_switch_app.flashbundle.txt'
  66. elif self == Efr32App.WINDOW_COVERING:
  67. return 'window_app.flashbundle.txt'
  68. elif self == Efr32App.THERMOSTAT:
  69. return 'thermostat_app.flashbundle.txt'
  70. elif self == Efr32App.PUMP:
  71. return 'pump_app.flashbundle.txt'
  72. elif self == Efr32App.UNIT_TEST:
  73. return 'efr32_device_tests.flashbundle.txt'
  74. else:
  75. raise Exception('Unknown app type: %r' % self)
  76. def BuildRoot(self, root):
  77. if self == Efr32App.UNIT_TEST:
  78. return os.path.join(root, 'src', 'test_driver', 'efr32')
  79. else:
  80. return os.path.join(root, 'examples', self.ExampleName(), 'silabs')
  81. class Efr32Board(Enum):
  82. BRD4161A = 1
  83. BRD4163A = 2
  84. BRD4164A = 3
  85. BRD4166A = 4
  86. BRD4170A = 5
  87. BRD4186A = 6
  88. BRD4187A = 7
  89. BRD4304A = 8
  90. BRD4187C = 9
  91. BRD4186C = 10
  92. def GnArgName(self):
  93. if self == Efr32Board.BRD4161A:
  94. return 'BRD4161A'
  95. elif self == Efr32Board.BRD4163A:
  96. return 'BRD4163A'
  97. elif self == Efr32Board.BRD4164A:
  98. return 'BRD4164A'
  99. elif self == Efr32Board.BRD4166A:
  100. return 'BRD4166A'
  101. elif self == Efr32Board.BRD4170A:
  102. return 'BRD4170A'
  103. elif self == Efr32Board.BRD4186A:
  104. return 'BRD4186A'
  105. elif self == Efr32Board.BRD4187A:
  106. return 'BRD4187A'
  107. elif self == Efr32Board.BRD4304A:
  108. return 'BRD4304A'
  109. elif self == Efr32Board.BRD4186C:
  110. return 'BRD4186C'
  111. elif self == Efr32Board.BRD4187C:
  112. return 'BRD4187C'
  113. else:
  114. raise Exception('Unknown board #: %r' % self)
  115. class Efr32Builder(GnBuilder):
  116. def __init__(self,
  117. root,
  118. runner,
  119. app: Efr32App = Efr32App.LIGHT,
  120. board: Efr32Board = Efr32Board.BRD4161A,
  121. chip_build_libshell: bool = False,
  122. chip_logging: bool = True,
  123. chip_openthread_ftd: bool = True,
  124. enable_heap_monitoring: bool = False,
  125. enable_openthread_cli: bool = True,
  126. show_qr_code: bool = False,
  127. enable_rpcs: bool = False,
  128. enable_ota_requestor: bool = False,
  129. enable_icd: bool = False,
  130. enable_low_power: bool = False,
  131. enable_wifi: bool = False,
  132. enable_rs911x: bool = False,
  133. enable_wf200: bool = False,
  134. enable_wifi_ipv4: bool = False,
  135. enable_additional_data_advertising: bool = False,
  136. enable_ot_lib: bool = False,
  137. enable_ot_coap_lib: bool = False,
  138. no_version: bool = False
  139. ):
  140. super(Efr32Builder, self).__init__(
  141. root=app.BuildRoot(root),
  142. runner=runner)
  143. self.app = app
  144. self.extra_gn_options = ['silabs_board="%s"' % board.GnArgName()]
  145. self.dotfile = ''
  146. if enable_rpcs:
  147. self.extra_gn_options.append('is_debug=false import("//with_pw_rpc.gni")')
  148. if enable_ota_requestor:
  149. self.extra_gn_options.append('chip_enable_ota_requestor=true')
  150. if enable_icd:
  151. self.extra_gn_options.append('chip_enable_icd_server=true chip_openthread_ftd=false')
  152. if enable_low_power:
  153. self.extra_gn_options.append(
  154. 'chip_build_libshell=false enable_openthread_cli=false show_qr_code=false disable_lcd=true')
  155. if chip_build_libshell:
  156. self.extra_gn_options.append('chip_build_libshell=true')
  157. if chip_logging is False:
  158. self.extra_gn_options.append('chip_logging=false')
  159. if chip_openthread_ftd is False:
  160. self.extra_gn_options.append('chip_openthread_ftd=false')
  161. if enable_heap_monitoring:
  162. self.extra_gn_options.append('enable_heap_monitoring=true')
  163. if enable_openthread_cli is False:
  164. self.extra_gn_options.append('enable_openthread_cli=false')
  165. if show_qr_code:
  166. self.extra_gn_options.append('show_qr_code=true')
  167. if enable_wifi:
  168. self.dotfile += self.root + '/build_for_wifi_gnfile.gn'
  169. if board == Efr32Board.BRD4161A:
  170. self.extra_gn_options.append('is_debug=false chip_logging=false')
  171. else:
  172. self.extra_gn_options.append('disable_lcd=true use_external_flash=false')
  173. if enable_rs911x:
  174. self.extra_gn_options.append('use_rs911x=true')
  175. elif enable_wf200:
  176. self.extra_gn_options.append('use_wf200=true')
  177. else:
  178. raise Exception('Wifi usage: ...-wifi-[rs911x|wf200]-...')
  179. if enable_wifi_ipv4:
  180. self.extra_gn_options.append('chip_enable_wifi_ipv4=true')
  181. if enable_additional_data_advertising:
  182. self.extra_gn_options.append('chip_enable_additional_data_advertising=true chip_enable_rotating_device_id=true')
  183. if enable_ot_lib:
  184. self.extra_gn_options.append(
  185. 'use_silabs_thread_lib=true chip_openthread_target="../silabs:ot-efr32-cert" openthread_external_platform=""')
  186. if enable_ot_coap_lib:
  187. self.extra_gn_options.append(
  188. 'use_silabs_thread_lib=true chip_openthread_target="../silabs:ot-efr32-cert" '
  189. 'use_thread_coap_lib=true openthread_external_platform=""')
  190. if not no_version:
  191. shortCommitSha = subprocess.check_output(
  192. ['git', 'describe', '--always', '--dirty', '--exclude', '*']).decode('ascii').strip()
  193. branchName = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode('ascii').strip()
  194. self.extra_gn_options.append(
  195. 'sl_matter_version_str="v1.1-%s-%s"' % (branchName, shortCommitSha))
  196. if "GSDK_ROOT" in os.environ:
  197. # EFR32 SDK is very large. If the SDK path is already known (the
  198. # case for pre-installed images), use it directly.
  199. sdk_path = shlex.quote(os.environ['GSDK_ROOT'])
  200. self.extra_gn_options.append(f"efr32_sdk_root=\"{sdk_path}\"")
  201. self.extra_gn_options.append(f"openthread_root=\"{sdk_path}/util/third_party/openthread\"")
  202. def GnBuildArgs(self):
  203. return self.extra_gn_options
  204. def build_outputs(self):
  205. items = {}
  206. for extension in ["out", "out.map", "hex"]:
  207. name = '%s.%s' % (self.app.AppNamePrefix(), extension)
  208. items[name] = os.path.join(self.output_dir, name)
  209. if self.app == Efr32App.UNIT_TEST:
  210. # Include test runner python wheels
  211. for root, dirs, files in os.walk(os.path.join(self.output_dir, 'chip_nl_test_runner_wheels')):
  212. for file in files:
  213. items["chip_nl_test_runner_wheels/" +
  214. file] = os.path.join(root, file)
  215. # Figure out flash bundle files and build accordingly
  216. with open(os.path.join(self.output_dir, self.app.FlashBundleName())) as f:
  217. for line in f.readlines():
  218. name = line.strip()
  219. items['flashbundle/%s' %
  220. name] = os.path.join(self.output_dir, name)
  221. return items
  222. def generate(self):
  223. cmd = [
  224. 'gn', 'gen', '--check', '--fail-on-unused-args',
  225. '--export-compile-commands',
  226. '--root=%s' % self.root
  227. ]
  228. if self.dotfile:
  229. cmd += ['--dotfile=%s' % self.dotfile]
  230. extra_args = self.GnBuildArgs()
  231. if self.options.pw_command_launcher:
  232. extra_args.append('pw_command_launcher="%s"' % self.options.pw_command_launcher)
  233. if self.options.pregen_dir:
  234. extra_args.append('chip_code_pre_generated_directory="%s"' % self.options.pregen_dir)
  235. if extra_args:
  236. cmd += ['--args=%s' % ' '.join(extra_args)]
  237. cmd += [self.output_dir]
  238. title = 'Generating ' + self.identifier
  239. extra_env = self.GnBuildEnv()
  240. if extra_env:
  241. # convert the command into a bash command that includes
  242. # setting environment variables
  243. cmd = [
  244. 'bash', '-c', '\n' + ' '.join(
  245. ['%s="%s" \\\n' % (key, value) for key, value in extra_env.items()] +
  246. [shlex.join(cmd)]
  247. )
  248. ]
  249. self._Execute(cmd, title=title)