air302.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #!/usr/bin/python3
  2. # -*- coding: UTF-8 -*-
  3. import os.path
  4. import shutil
  5. import zipfile
  6. import time
  7. import subprocess
  8. import sys
  9. import json
  10. #------------------------------------------------------------------
  11. # 读取配置信息
  12. import configparser
  13. config = configparser.ConfigParser()
  14. config['air302'] = {
  15. "PLAT_ROOT" : "D:\\github\\air302\\sdk\\PLAT\\", # 仅开发者配置
  16. "FTC_PATH" : ".\\FlashToolCLI\\",
  17. "EC_PATH" : ".\\Air302_dev.ec",
  18. "USER_PATH": ".\\user\\",
  19. "LIB_PATH" : ".\\lib\\",
  20. "DEMO_PATH": ".\\demo\\",
  21. "MAIN_LUA_DEBUG" : "true",
  22. "LUA_DEBUG" : "false",
  23. "COM_PORT" : "COM56"
  24. }
  25. if os.path.exists("local.ini") :
  26. config.read("local.ini")
  27. if os.path.exists(config["air302"]["PLAT_ROOT"]):
  28. PLAT_ROOT = os.path.abspath(config["air302"]["PLAT_ROOT"]) + os.sep # 源码地址
  29. else:
  30. PLAT_ROOT = config["air302"]["PLAT_ROOT"]
  31. FTC_PATH = os.path.abspath(config["air302"]["FTC_PATH"]) + os.sep # FlashToolCLI刷机工具的目录
  32. EC_PATH = os.path.abspath(config["air302"]["EC_PATH"]) # EC后缀的固件路径
  33. USER_PATH = os.path.abspath(config["air302"]["USER_PATH"]) + os.sep # 用户脚本所在的目录
  34. LIB_PATH = os.path.abspath(config["air302"]["LIB_PATH"]) + os.sep # 用户脚本所在的目录
  35. DEMO_PATH = os.path.abspath(config["air302"]["DEMO_PATH"]) + os.sep # 用户脚本所在的目录
  36. MAIN_LUA_DEBUG = config["air302"]["MAIN_LUA_DEBUG"] == "true"
  37. LUA_DEBUG = config["air302"]["LUA_DEBUG"] == "true"
  38. COM_PORT = config["air302"]["COM_PORT"]
  39. # TODO 从环境变量获取上述参数
  40. '''
  41. 获取git库的当前版本号,为一个hash值
  42. '''
  43. def get_git_revision_short_hash():
  44. try :
  45. return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip()
  46. except:
  47. return ""
  48. '''
  49. 打印帮助信息
  50. '''
  51. def usage():
  52. print('''
  53. python air302.py [action]
  54. lfs - 编译文件系统
  55. dlrom - 下载底层固件
  56. dlfs - 下载lua脚本(即整个文件系统)
  57. dlfull- 下载底层和lua脚本
  58. pkg - 生成发布用的压缩包
  59. build - 构建源码(仅内部使用)
  60. 用例1, 生成文件系统并下载到开发板
  61. python air302.py lfs dlfs
  62. 用例2, 生成文件系统,并下载固件和文件系统到开发板
  63. python air302.py lfs dlfull
  64. 用例3, 仅下载底层固件
  65. python air302.py dlrom
  66. 用例四, 编译,打包,构建文件系统,全量下载
  67. python air302.py build lfs pkg dlfull
  68. ''')
  69. '''
  70. FlashToolCLI所需要的配置信息
  71. '''
  72. FTC_CNF_TMPL = '''
  73. [config]
  74. line_0_com = ${COM}
  75. agbaud = 921600
  76. ;bootloader.bin file infomation
  77. [bootloader]
  78. blpath = .\\image\\bootloader.bin
  79. blloadskip = 0
  80. ;system.bin file infomation
  81. [system]
  82. syspath = .\\system.bin
  83. sysloadskip = 0
  84. ;control such as reset before download
  85. [control]
  86. reset = 0
  87. [flexfile0]
  88. filepath = .\\rfCaliTb\\MergeRfTable.bin
  89. burnaddr = 0x3A4000
  90. [flexfile1]
  91. filepath = .\\rfCaliTb\\MergeRfTable.bin
  92. burnaddr = 0x16000
  93. [flexfile2]
  94. filepath = .\\disk.fs
  95. burnaddr = 0x350000
  96. '''.replace("${COM}", COM_PORT)
  97. '''
  98. 执行打包程序,内部使用
  99. '''
  100. def _pkg():
  101. # TODO 扩展为用户可用的打包ec固件的工具
  102. if os.path.exists("tmp"):
  103. shutil.rmtree("tmp")
  104. _tag = time.strftime("%Y%m%d%H%M%S", time.localtime())
  105. _tag = _tag + "-" + get_git_revision_short_hash().decode()
  106. os.mkdir("tmp")
  107. os.mkdir("tmp/ec")
  108. # 拷贝固件文件
  109. if os.path.exists(PLAT_ROOT) :
  110. shutil.copy(PLAT_ROOT + "out/ec616_0h00/air302/air302.bin", "tmp/ec/luatos.bin")
  111. shutil.copy(PLAT_ROOT + "out/ec616_0h00/air302/comdb.txt", "tmp/ec/comdb.txt")
  112. shutil.copy(FTC_PATH + "image/bootloader.bin", "tmp/ec/bootloader.bin")
  113. shutil.copy(FTC_PATH + "image/bootloader_head.bin", "tmp/ec/bootloader_head.bin")
  114. elif os.path.exists(EC_PATH) and EC_PATH.endswith(".ec") :
  115. with zipfile.ZipFile(EC_PATH) as zip :
  116. zip.extractall(path="tmp/ec/")
  117. # 拷贝库文件和demo
  118. shutil.copytree(LIB_PATH, "tmp/lib")
  119. shutil.copytree(DEMO_PATH, "tmp/demo")
  120. #拷贝自身
  121. shutil.copy(sys.argv[0], "tmp/air302.py")
  122. # 写入默认配置文件
  123. with open("tmp/local.ini", "w") as f:
  124. f.write('''
  125. [air302]
  126. ; PLAT_ROOT for factory only
  127. PLAT_ROOT = D:\\gitee\\air302
  128. FTC_PATH = FlashToolCLI\\
  129. EC_PATH = ${EC}
  130. USER_PATH = user\\
  131. LIB_PATH = lib\\
  132. DEMO_PATH = demo\\
  133. MAIN_LUA_DEBUG = true
  134. LUA_DEBUG = false
  135. COM_PORT = COM56
  136. '''.replace("${EC}", "Air302_V0001_"+_tag+".ec"))
  137. if os.path.exists("userdoc") :
  138. shutil.copytree("userdoc", "tmp/userdoc")
  139. if os.path.exists(USER_PATH):
  140. shutil.copytree(USER_PATH, "tmp/user")
  141. with open("tmp/文档在userdoc目录.txt", "w") as f:
  142. f.write("QQ群: 1061642968")
  143. with zipfile.ZipFile("tmp/Air302_V0001_"+_tag+".ec", mode="w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as zip :
  144. zip.write("tmp/ec/luatos.bin", "luatos.bin") # 底层固件
  145. zip.write("tmp/ec/comdb.txt", "comdb.txt") # uart0输出的unilog所需要的数据库文件,备用
  146. zip.write("tmp/ec/bootloader.bin", "bootloader.bin") # bootloader,备用
  147. zip.write("tmp/ec/bootloader_head.bin", "bootloader_head.bin") # bootloader_header,备用
  148. zip.write(FTC_PATH + "disk.fs", "disk.bin") # 默认磁盘镜像
  149. shutil.rmtree("tmp/ec/")
  150. if os.path.exists(FTC_PATH):
  151. shutil.copytree(FTC_PATH, "tmp/FlashToolCLI")
  152. pkg_name = "Air302_V0001_"+_tag + ".zip"
  153. shutil.make_archive("Air302_V0001_"+_tag, 'zip', "tmp")
  154. ## 拷贝一份固定路径的
  155. shutil.copy("tmp/Air302_V0001_"+_tag+".ec", "tmp/Air302_dev.ec")
  156. print("ALL DONE===================================================")
  157. print("Package Name", pkg_name)
  158. '''
  159. 下载底层或脚本
  160. '''
  161. def _dl(tp, _path=None):
  162. with open(FTC_PATH + "config.ini", "w") as f :
  163. f.write(FTC_CNF_TMPL)
  164. cmd = [FTC_PATH + "FlashToolCLI.exe", "-p", COM_PORT, "burnbatch", "--imglist"]
  165. if tp == "rom" or tp == "full":
  166. if EC_PATH.endswith(".ec") :
  167. import zipfile
  168. with zipfile.ZipFile(EC_PATH) as zip :
  169. with open(FTC_PATH + "system.bin", "wb") as f:
  170. f.write(zip.read("luatos.bin"))
  171. elif EC_PATH.endswith(".bin"):
  172. shutil.copy(EC_PATH, FTC_PATH + "system.bin")
  173. else:
  174. print("Bad EC_PATH")
  175. return
  176. cmd += ["system"]
  177. if tp == "fs" or tp == "full" :
  178. cmd += ["flexfile2"]
  179. print("CALL", " ".join(cmd))
  180. subprocess.check_call(cmd, cwd=FTC_PATH)
  181. '''
  182. 生成文件系统镜像
  183. '''
  184. def _lfs(_path=None):
  185. _disk = FTC_PATH + "disk"
  186. if os.path.exists(_disk) :
  187. shutil.rmtree(_disk)
  188. os.mkdir(_disk)
  189. if not _path:
  190. _path = USER_PATH
  191. # 收集需要处理的文件列表
  192. _paths = []
  193. # 首先,遍历lib目录
  194. if os.path.exists(LIB_PATH) :
  195. for name in os.listdir(LIB_PATH) :
  196. _paths.append(LIB_PATH + name)
  197. # 然后遍历user目录
  198. for name in os.listdir(_path) :
  199. _paths.append(_path + name)
  200. for name in _paths :
  201. # 如果是lua文件, 编译之
  202. if name.endswith(".lua") :
  203. cmd = [FTC_PATH + "luac.exe"]
  204. if name == "main.lua" :
  205. if not MAIN_LUA_DEBUG :
  206. cmd += ["-s"]
  207. elif not LUA_DEBUG :
  208. cmd += ["-s"]
  209. else:
  210. print("LUA_DEBUG", LUA_DEBUG, "False" == LUA_DEBUG)
  211. cmd += ["-o", FTC_PATH + "disk/" + os.path.basename(name) + "c", name]
  212. print("CALL", " ".join(cmd))
  213. subprocess.check_call(cmd)
  214. # 其他文件直接拷贝
  215. else:
  216. print("COPY", name, FTC_PATH + "disk/" + os.path.basename(name))
  217. shutil.copy(name, FTC_PATH + "disk/" + os.path.basename(name))
  218. print("CALL mklfs")
  219. subprocess.check_call([FTC_PATH + "mklfs.exe"], cwd=FTC_PATH)
  220. def main():
  221. argc = 1
  222. while len(sys.argv) > argc :
  223. if sys.argv[argc] == "build" :
  224. print("Action Build ----------------------------------")
  225. subprocess.check_call([PLAT_ROOT + "build.bat"])
  226. elif sys.argv[argc] == "lfs" :
  227. print("Action mklfs ----------------------------------")
  228. _lfs()
  229. elif sys.argv[argc] == "pkg" :
  230. print("Action pkg ------------------------------------")
  231. _pkg()
  232. elif sys.argv[argc] == "dlrom": #下载底层
  233. print("Action download ROM ---------------------------")
  234. if len(sys.argv) > argc + 1 and sys.argv[argc+1].startsWith("-path="):
  235. _dl("rom", sys.argv[argc+1][6:])
  236. argc += 1
  237. else:
  238. _dl("rom")
  239. elif sys.argv[argc] == "dlfs":
  240. print("Action download FS ---------------------------")
  241. if len(sys.argv) > argc + 1 and sys.argv[argc+1].startsWith("-path="):
  242. _dl("fs", sys.argv[argc+1][6:])
  243. argc += 1
  244. else:
  245. _dl("fs")
  246. elif sys.argv[argc] == "dlfull":
  247. if len(sys.argv) > argc + 1 and sys.argv[argc+1].startsWith("-path="):
  248. _dl("full", sys.argv[argc+1][6:])
  249. argc += 1
  250. else:
  251. _dl("full")
  252. elif sys.argv[argc] == "clean":
  253. if os.path.exists("tmp"):
  254. shutil.rmtree("tmp")
  255. else:
  256. usage()
  257. return
  258. argc += 1
  259. print("============================================================================")
  260. print("every done, bye")
  261. if len(sys.argv) == 1 :
  262. usage()
  263. else :
  264. main()