build-baremetal 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env python3
  2. import os
  3. import common
  4. class BaremetalComponent(self.Component):
  5. def do_build(self, args):
  6. self.assert_crosstool_ng_supports_arch(kwargs['arch'])
  7. build_dir = self.get_build_dir(args)
  8. bootloader_obj = os.path.join(kwargs['baremetal_build_lib_dir'], 'bootloader{}'.format(kwargs['obj_ext']))
  9. common_basename_noext = 'common'
  10. common_src = os.path.join(kwargs['root_dir'], common_basename_noext + kwargs['c_ext'])
  11. common_obj = os.path.join(kwargs['baremetal_build_lib_dir'], common_basename_noext + kwargs['obj_ext'])
  12. syscalls_basename_noext = 'syscalls'
  13. syscalls_src = os.path.join(kwargs['baremetal_src_lib_dir'], syscalls_basename_noext + kwargs['c_ext'])
  14. syscalls_obj = os.path.join(kwargs['baremetal_build_lib_dir'], syscalls_basename_noext + kwargs['obj_ext'])
  15. common_objs = [common_obj, syscalls_obj]
  16. cflags = [
  17. '-I', kwargs['baremetal_src_lib_dir'], LF,
  18. '-I', kwargs['root_dir'], LF,
  19. '-O0', LF,
  20. '-ggdb3', LF,
  21. '-mcpu={}'.format(kwargs['mcpu']), LF,
  22. '-nostartfiles', LF,
  23. ]
  24. if kwargs['prebuilt']:
  25. gcc = 'arm-none-eabi-gcc'
  26. else:
  27. os.environ['PATH'] = kwargs['crosstool_ng_bin_dir'] + os.environ['PATH']
  28. gcc = self.get_toolchain_tool('gcc', allowed_toolchains=['crosstool-ng'])
  29. if kwargs['emulator'] == 'gem5':
  30. if kwargs['machine'] == 'VExpress_GEM5_V1':
  31. entry_address = 0x80000000
  32. uart_address = 0x1c090000
  33. elif kwargs['machine'] == 'RealViewPBX':
  34. entry_address = 0x10000
  35. uart_address = 0x10009000
  36. else:
  37. raise Exception('unknown machine: ' + kwargs['machine'])
  38. cflags.extend(['-D', 'GEM5'.format(uart_address), LF])
  39. else:
  40. entry_address = 0x40000000
  41. uart_address = 0x09000000
  42. os.makedirs(build_dir, exist_ok=True)
  43. os.makedirs(kwargs['baremetal_build_lib_dir'], exist_ok=True)
  44. src = os.path.join(kwargs['baremetal_src_lib_dir'], '{}{}'.format(kwargs['arch'], kwargs['asm_ext']))
  45. if self.need_rebuild([src], bootloader_obj):
  46. self.sh.run_cmd(
  47. [gcc, LF] +
  48. cflags +
  49. [
  50. '-c', LF,
  51. '-o', bootloader_obj, LF,
  52. src, LF,
  53. ]
  54. )
  55. for src, obj in [
  56. (common_src, common_obj),
  57. (syscalls_src, syscalls_obj),
  58. ]:
  59. if self.need_rebuild([src], obj):
  60. self.sh.run_cmd(
  61. [gcc, LF] +
  62. cflags +
  63. [
  64. '-c', LF,
  65. '-D', 'UART0_ADDR={:#x}'.format(uart_address), LF,
  66. '-o', obj, LF,
  67. src, LF,
  68. ]
  69. )
  70. self._build_dir(
  71. '',
  72. gcc=gcc,
  73. cflags=cflags,
  74. entry_address=entry_address,
  75. bootloader_obj=bootloader_obj,
  76. common_objs=common_objs,
  77. )
  78. self._build_dir(
  79. 'interactive',
  80. gcc=gcc,
  81. cflags=cflags,
  82. entry_address=entry_address,
  83. bootloader_obj=bootloader_obj,
  84. common_objs=common_objs,
  85. )
  86. arch_dir = os.path.join('arch', kwargs['arch'])
  87. if os.path.isdir(os.path.join(kwargs['baremetal_src_dir'], arch_dir)):
  88. self._build_dir(
  89. arch_dir,
  90. gcc=gcc,
  91. cflags=cflags,
  92. entry_address=entry_address,
  93. bootloader_obj=bootloader_obj,
  94. common_objs=common_objs,
  95. )
  96. arch_dir = os.path.join('arch', kwargs['arch'], 'no_bootloader')
  97. if os.path.isdir(os.path.join(kwargs['baremetal_src_dir'], arch_dir)):
  98. self._build_dir(
  99. arch_dir,
  100. gcc=gcc,
  101. cflags=cflags,
  102. entry_address=entry_address,
  103. bootloader_obj=bootloader_obj,
  104. common_objs=common_objs,
  105. bootloader=False,
  106. )
  107. def get_argparse_args(self):
  108. return {
  109. 'description': '''\
  110. Build the baremetal examples with crosstool-NG.
  111. '''
  112. }
  113. def get_build_dir(self, args):
  114. return kwargs['baremetal_build_dir']
  115. def get_default_args(self):
  116. return {'baremetal': 'all'}
  117. def _build_dir(
  118. self,
  119. subpath,
  120. gcc,
  121. cflags,
  122. entry_address,
  123. bootloader_obj,
  124. common_objs,
  125. bootloader=True
  126. ):
  127. """
  128. Build all .c and .S files in a given subpath of the baremetal source
  129. directory non recursively.
  130. Place outputs on the same subpath or the output directory.
  131. """
  132. in_dir = os.path.join(kwargs['baremetal_src_dir'], subpath)
  133. out_dir = os.path.join(kwargs['baremetal_build_dir'], subpath)
  134. os.makedirs(out_dir, exist_ok=True)
  135. common_objs = common_objs.copy()
  136. if bootloader:
  137. common_objs.append(bootloader_obj)
  138. for in_basename in os.listdir(in_dir):
  139. in_path = os.path.join(in_dir, in_basename)
  140. if os.path.isfile(in_path) and os.path.splitext(in_basename)[1] in (kwargs['c_ext'], kwargs['asm_ext']):
  141. in_name = os.path.splitext(in_basename)[0]
  142. main_obj = os.path.join(kwargs['baremetal_build_dir'], subpath, '{}{}'.format(in_name, kwargs['obj_ext']))
  143. src = os.path.join(kwargs['baremetal_src_dir'], in_path)
  144. if self.need_rebuild([src], main_obj):
  145. self.sh.run_cmd(
  146. [gcc, LF] +
  147. cflags +
  148. [
  149. '-c', LF,
  150. '-o', main_obj, LF,
  151. src, LF,
  152. ]
  153. )
  154. objs = common_objs + [main_obj]
  155. out = os.path.join(kwargs['baremetal_build_dir'], subpath, in_name + kwargs['baremetal_build_ext'])
  156. link_script = os.path.join(kwargs['baremetal_src_dir'], 'link.ld')
  157. if self.need_rebuild(objs + [link_script], out):
  158. self.sh.run_cmd(
  159. [gcc, LF] +
  160. cflags +
  161. [
  162. '-Wl,--section-start=.text={:#x}'.format(entry_address), LF,
  163. '-o', out, LF,
  164. '-T', link_script, LF,
  165. ] +
  166. self.sh.add_newlines(objs)
  167. )
  168. if __name__ == '__main__':
  169. BaremetalComponent().build()