build-baremetal 6.6 KB

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