build_interrupt_handlers.py 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. #! /usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  4. import sys, interrupt_names_teensy_3_6
  5. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  6. def ENDC () :
  7. return '\033[0m'
  8. #······················································································································*
  9. def RED () :
  10. return '\033[91m'
  11. #······················································································································*
  12. def BOLD () :
  13. return '\033[1m'
  14. #······················································································································*
  15. def BOLD_RED () :
  16. return BOLD () + RED ()
  17. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  18. def asSeparator () :
  19. return "@" + ("-" * 119) + "\n"
  20. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  21. def cppSeparator () :
  22. return "//" + ("-" * 118) + "\n"
  23. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  24. def generateSVChandler ():
  25. sFile = asSeparator ()
  26. sFile += "@ S V C H A N D L E R ( D O U B L E S T A C K M O D E )\n"
  27. sFile += asSeparator ()
  28. sFile += "@\n"
  29. sFile += "@ PSP+32 -> | |\n"
  30. sFile += "@ |----------------------------| \\\n"
  31. sFile += "@ PSP+28 -> | xPSR | |\n"
  32. sFile += "@ |----------------------------| |\n"
  33. sFile += "@ PSP+24 -> | PC (after SVC instruction) | |\n"
  34. sFile += "@ |----------------------------| |\n"
  35. sFile += "@ PSP+20 -> | LR | |\n"
  36. sFile += "@ |----------------------------| |\n"
  37. sFile += "@ PSP+16 -> | R12 | | Saved by interrupt response\n"
  38. sFile += "@ |----------------------------| |\n"
  39. sFile += "@ PSP+12 -> | R3 | |\n"
  40. sFile += "@ |----------------------------| |\n"
  41. sFile += "@ PSP+8 -> | R2 | |\n"
  42. sFile += "@ |----------------------------| |\n"
  43. sFile += "@ PSP+4 -> | R1 | |\n"
  44. sFile += "@ |----------------------------| |\n"
  45. sFile += "@ /--- PSP ----> | R0 | |\n"
  46. sFile += "@ | |----------------------------| /\n"
  47. sFile += "@ | | |\n"
  48. sFile += "@ |\n"
  49. sFile += "@ | *---------------------*\n"
  50. sFile += "@ | | LR return code | +36 [ 9]\n"
  51. sFile += "@ | *---------------------*\n"
  52. sFile += "@ \----------------------------------------- | R13 (PSP) | +32 [ 8]\n"
  53. sFile += "@ *---------------------*\n"
  54. sFile += "@ | R11 | +28 [ 7]\n"
  55. sFile += "@ *---------------------*\n"
  56. sFile += "@ | R10 | +24 [ 6]\n"
  57. sFile += "@ *---------------------*\n"
  58. sFile += "@ | R9 | +20 [ 5]\n"
  59. sFile += "@ *---------------------*\n"
  60. sFile += "@ | R8 | +16 [ 4]\n"
  61. sFile += "@ *---------------------*\n"
  62. sFile += "@ | R7 | +12 [ 3]\n"
  63. sFile += "@ *---------------------*\n"
  64. sFile += "@ | R6 | + 8 [ 2]\n"
  65. sFile += "@ *---------------------*\n"
  66. sFile += "@ | R5 | + 4 [ 1]\n"
  67. sFile += "@ *------------------------------------* *---------------------*\n"
  68. sFile += "@ | var.running.task.control.block.ptr +------> | R4 | + 0 [ 0]\n"
  69. sFile += "@ *------------------------------------* *---------------------*\n"
  70. sFile += "@\n"
  71. sFile += asSeparator () + "\n"
  72. sFile += " .section .bss.var.background.task.context, \"aw\", %nobits\n"
  73. sFile += " .align 2\n\n"
  74. sFile += "var.background.task.context:\n"
  75. sFile += " .space 4\n\n"
  76. sFile += asSeparator () + "\n"
  77. sFile += " .section .text.interrupt.SVC, \"ax\", %progbits\n\n"
  78. sFile += " .global interrupt.SVC\n"
  79. sFile += " .type interrupt.SVC, %function\n\n"
  80. sFile += "interrupt.SVC:\n"
  81. sFile += "@----------------------------------------- Save preserved registers\n"
  82. sFile += " push {r4, lr}\n"
  83. sFile += "@----------------------------------------- R4 <- thread SP\n"
  84. sFile += " mrs r4, psp\n"
  85. sFile += "@----------------------------------------- Restore R0, R1, R2 and R3 from saved stack\n"
  86. sFile += " ldmia r4!, {r0, r1, r2, r3} @ R4 incremented by 16\n"
  87. sFile += "@----------------------------------------- R4 <- Address of SVC instruction\n"
  88. sFile += " ldr r4, [r4, #8] @ 8 : 2 stacked registers before saved PC\n"
  89. sFile += "@----------------------------------------- R12 <- bits 0-7 of SVC instruction\n"
  90. sFile += " ldrb r12, [r4, #-2] @ R12 is service call index\n"
  91. sFile += "@----------------------------------------- R4 <- address of dispatcher table\n"
  92. sFile += " ldr r4, =svc.dispatcher.table\n"
  93. sFile += "@----------------------------------------- R12 <- address of routine to call\n"
  94. sFile += " ldr r12, [r4, r12, lsl #2] @ R12 = R4 + (R12 << 2)\n"
  95. sFile += "@----------------------------------------- R4 <- calling task context\n"
  96. sFile += " ldr r4, =var.running.task.control.block.ptr\n"
  97. sFile += " ldr r4, [r4]\n"
  98. sFile += "@----------------------------------------- Call service routine\n"
  99. sFile += " blx r12 @ R4:calling task context address\n"
  100. sFile += "@--- Continues in sequence to handle.context.switch\n\n"
  101. sFile += asSeparator ()
  102. sFile += "@\n"
  103. sFile += "@ H A N D L E C O N T E X T S W I T C H ( D O U B L E S T A C K M O D E )\n"
  104. sFile += "@\n"
  105. sFile += "@ On entry:\n"
  106. sFile += "@ - R4 contains the runnning task save context address,\n"
  107. sFile += "@ - R4 and LR of running task have been pushed on handler stack.\n"
  108. sFile += "@\n"
  109. sFile += asSeparator () + "\n"
  110. sFile += "handle.context.switch:\n"
  111. sFile += "@----------------------------------------- Select task to run\n"
  112. sFile += " bl kernel.select.task.to.run\n"
  113. sFile += "@----------------------------------------- R0 <- calling task context, R1 <- new task context\n"
  114. sFile += " ldr r1, =var.running.task.control.block.ptr\n"
  115. sFile += " mov r0, r4\n"
  116. sFile += " ldr r1, [r1]\n"
  117. sFile += "@----------------------------------------- Restore preserved registers\n"
  118. sFile += " pop {r4, lr}\n"
  119. sFile += "@----------------------------------------- Running task did change ?\n"
  120. sFile += " cmp r0, r1 @ R0:calling task context, R1:new task context\n"
  121. sFile += " bne running.state.did.change\n"
  122. sFile += " bx lr @ No change\n"
  123. sFile += "@----------------------------------------- Save context of preempted task\n"
  124. sFile += "running.state.did.change:\n"
  125. sFile += " mrs r12, psp\n"
  126. sFile += " cbz r0, save.background.task.context\n"
  127. sFile += "@--- Save registers r4 to r11, PSP (stored in R12), LR\n"
  128. sFile += " stmia r0, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
  129. sFile += " b perform.restore.context\n"
  130. sFile += "save.background.task.context:\n"
  131. sFile += " ldr r2, =var.background.task.context\n"
  132. sFile += " str r12, [r2]\n"
  133. sFile += "@----------------------------------------- Restore context of activated task\n"
  134. sFile += "perform.restore.context:\n"
  135. sFile += " cbz r1, restore.background.task.context\n"
  136. sFile += " ldmia r1, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
  137. sFile += " msr psp, r12\n"
  138. sFile += " bx lr\n"
  139. sFile += "@----------------------------------------- Restore background task context\n"
  140. sFile += "restore.background.task.context:\n"
  141. sFile += " ldr r2, =var.background.task.context\n"
  142. sFile += " ldr r2, [r2]\n"
  143. sFile += " msr psp, r2\n"
  144. sFile += " bx lr\n\n"
  145. return sFile
  146. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  147. def generateBreakpointHandler () :
  148. sFile = asSeparator ()
  149. sFile += "@\n"
  150. sFile += "@ B K P T H A N D L E R ( D O U B L E S T A C K M O D E )\n"
  151. sFile += "@\n"
  152. sFile += asSeparator ()
  153. sFile += "@\n"
  154. sFile += "@ | |\n"
  155. sFile += "@ PSP+32 -> |----------------------------| \\\n"
  156. sFile += "@ | xPSR | |\n"
  157. sFile += "@ PSP+28 -> |----------------------------| |\n"
  158. sFile += "@ | PC (BKPT instruction) | |\n"
  159. sFile += "@ PSP+24 -> |----------------------------| |\n"
  160. sFile += "@ | LR | |\n"
  161. sFile += "@ PSP+20 -> |----------------------------| |\n"
  162. sFile += "@ | R12 | | Saved by interrupt response\n"
  163. sFile += "@ PSP+16 -> |----------------------------| |\n"
  164. sFile += "@ | R3 | |\n"
  165. sFile += "@ PSP+12 -> |----------------------------| |\n"
  166. sFile += "@ | R2 | |\n"
  167. sFile += "@ PSP+8 -> |----------------------------| |\n"
  168. sFile += "@ | R1 | |\n"
  169. sFile += "@ PSP+4 -> |----------------------------| |\n"
  170. sFile += "@ | R0 | |\n"
  171. sFile += "@ PSP -> |----------------------------| /\n"
  172. sFile += "@\n"
  173. sFile += asSeparator () + "\n"
  174. sFile += " .section .text.interrupt.DebugMonitor, \"ax\", %progbits\n\n"
  175. sFile += " .global interrupt.DebugMonitor\n"
  176. sFile += " .type interrupt.DebugMonitor, %function\n\n"
  177. sFile += "interrupt.DebugMonitor:\n"
  178. sFile += "@--------------------- Save preserved registers\n"
  179. sFile += " push {r5, lr}\n"
  180. sFile += "@--------------------- R5 <- thread SP\n"
  181. sFile += " mrs r5, psp\n"
  182. sFile += " ldmia r5, {r0, r1, r2, r3}\n"
  183. sFile += "@--------------------- LR <- Address of BKPT instruction\n"
  184. sFile += " ldr lr, [r5, #24] @ 24 : 6 stacked registers before saved PC\n"
  185. sFile += "@--------------------- Set return address to instruction following BKPT\n"
  186. sFile += "@ adds lr, #2\n"
  187. sFile += "@ str lr, [r5, #24]\n"
  188. sFile += "@--------------------- R12 <- address of dispatcher\n"
  189. sFile += " ldr r12, =section.dispatcher.table\n"
  190. sFile += "@--------------------- LR <- bits 0-7 of BKPT instruction\n"
  191. sFile += " ldrb lr, [lr, #-2] @ LR is service call index\n"
  192. sFile += "@--------------------- r12 <- address of routine to call\n"
  193. sFile += " ldr r12, [r12, lr, lsl #2] @ R12 = [R12 + LR * 4]\n"
  194. sFile += "@--------------------- Call service routine\n"
  195. sFile += " blx r12\n"
  196. sFile += "@--------------------- Set return code (from R0 to R3) in stacked registers\n"
  197. sFile += " stmia r5!, {r0, r1, r2, r3}\n"
  198. sFile += "@--------------------- Restore preserved registers, return from interrupt\n"
  199. sFile += " pop {r5, pc}\n\n"
  200. return sFile
  201. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  202. def generateBreakpointSection (sectionName, idx):
  203. sFile = asSeparator () + "\n"
  204. sFile += " .section .text." + section + ", \"ax\", %progbits\n"
  205. sFile += " .global " + section +"\n"
  206. sFile += " .align 1\n"
  207. sFile += " .type " + section +", %function\n\n"
  208. sFile += section +":\n"
  209. sFile += " .fnstart\n"
  210. sFile += " mrs r12, IPSR @ r12 <- 0x??????00 in thread mode, 0x??????nn, nn ≠ 0 in handler mode\n"
  211. sFile += " ands r12, #255\n"
  212. sFile += " bne section." + section + " @ in handler mode, call implementation routine directly\n"
  213. sFile += " bkpt #" + str (idx) + "\n"
  214. sFile += " bx lr\n\n"
  215. sFile += ".Lfunc_end_" + section +":\n"
  216. sFile += " .size " + section +", .Lfunc_end_" + section +" - " + section +"\n"
  217. sFile += " .cantunwind\n"
  218. sFile += " .fnend\n\n"
  219. return sFile
  220. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  221. def generateSoftwareInterruptandler () :
  222. sFile = asSeparator ()
  223. sFile += "@\n"
  224. sFile += "@ SECTIONS: Software Interrupt Handler (two stack mode)\n"
  225. sFile += "@\n"
  226. sFile += asSeparator ()
  227. sFile += "@\n"
  228. sFile += "@ | |\n"
  229. sFile += "@ PSP+32 -> |----------------------------| \\\n"
  230. sFile += "@ | xPSR | |\n"
  231. sFile += "@ PSP+28 -> |----------------------------| |\n"
  232. sFile += "@ | PC | |\n"
  233. sFile += "@ PSP+24 -> |----------------------------| |\n"
  234. sFile += "@ | LR | |\n"
  235. sFile += "@ PSP+20 -> |----------------------------| |\n"
  236. sFile += "@ | R12 | | Saved by interrupt response\n"
  237. sFile += "@ PSP+16 -> |----------------------------| |\n"
  238. sFile += "@ | R3 | |\n"
  239. sFile += "@ PSP+12 -> |----------------------------| |\n"
  240. sFile += "@ | R2 | |\n"
  241. sFile += "@ PSP+8 -> |----------------------------| |\n"
  242. sFile += "@ | R1 | |\n"
  243. sFile += "@ PSP+4 -> |----------------------------| |\n"
  244. sFile += "@ | R0 | |\n"
  245. sFile += "@ PSP -> |----------------------------| /\n"
  246. sFile += "@\n"
  247. sFile += asSeparator () + "\n"
  248. sFile += " .section .text.interrupt.SWINT, \"ax\", %progbits\n\n"
  249. sFile += " .global interrupt.SWINT\n"
  250. sFile += " .type interrupt.SWINT, %function\n\n"
  251. sFile += "interrupt.SWINT:\n"
  252. sFile += "@--------------------- Save preserved registers\n"
  253. sFile += " push {r5, lr}\n"
  254. sFile += "@--------------------- R5 <- thread SP\n"
  255. sFile += " mrs r5, psp\n"
  256. sFile += "@--------------------- Restore R0, R1, R2 and R3 from saved stack\n"
  257. sFile += " ldmia r5, {r0, r1, r2, r3}\n"
  258. sFile += "@--------------------- R12 <- Address section routine\n"
  259. sFile += " ldr r12, [r5, #16] @ 16 : 4 stacked registers before saved R12\n"
  260. sFile += "@--------------------- Call section routine\n"
  261. sFile += " blx r12\n"
  262. sFile += "@--------------------- Set return code (from R0 to R3) in stacked registers\n"
  263. sFile += " stmia r5!, {r0, r1, r2, r3} @ R5 is thread SP\n"
  264. sFile += "@--------------------- Set R12 stacked register to 0\n"
  265. sFile += " mov r0, #0\n"
  266. sFile += " str r0, [r5]\n"
  267. sFile += "@--------------------- Restore preserved registers, return from interrupt\n"
  268. sFile += " pop {r5, pc}\n\n"
  269. sFile += asSeparator () + "\n"
  270. sFile += " .section .text.direct.call.or.call.software.interrupt, \"ax\", %progbits\n\n"
  271. sFile += " .type direct.call.or.call.software.interrupt, %function\n\n"
  272. sFile += "direct.call.or.call.software.interrupt: @ R12 contains the address of section implementation function\n"
  273. sFile += "@--------------------- Save preserved registers\n"
  274. sFile += " push {r6, r7}\n"
  275. sFile += " mrs r6, IPSR @ IPSR[8...0] ≠ 0 in handler mode, = 0 in thread mode\n"
  276. sFile += " mov r7, #511\n"
  277. sFile += " tst r6, r7\n"
  278. sFile += " bne direct.call\n"
  279. sFile += "@--------------------- Software interrupt\n"
  280. sFile += " ldr r6, = 0xE000EF00 @ Address of STIR control register\n"
  281. sFile += " movs r7, # (80 - 16) @ Software Interrupt has number #80\n"
  282. sFile += " str r7, [r6] @ Generate Software Interrupt\n"
  283. sFile += "@--------------------- Wait for the exception is carried out\n"
  284. sFile += "wait.software.interrupt.done: @ R12 is reset by interrupt handler\n"
  285. sFile += " cmp r12, #0\n"
  286. sFile += " bne wait.software.interrupt.done\n"
  287. sFile += "@--------------------- Restore preserved registers\n"
  288. sFile += " pop {r6, r7}\n"
  289. sFile += " bx lr\n"
  290. sFile += "@--------------------- Direct call\n"
  291. sFile += "direct.call:\n"
  292. sFile += " pop {r6, r7}\n"
  293. sFile += " bx r12 @ in handler mode, call implementation routine directly\n\n"
  294. return sFile
  295. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  296. def generateSoftwareInterruptSection (sectionName, idx):
  297. sFile = asSeparator () + "\n"
  298. sFile += " .section .text." + sectionName + ", \"ax\", %progbits\n"
  299. sFile += " .global " + sectionName +"\n"
  300. sFile += " .align 1\n"
  301. sFile += " .type " + sectionName +", %function\n\n"
  302. sFile += sectionName +":\n"
  303. sFile += " .fnstart\n"
  304. sFile += " ldr r12, =section." + sectionName + "\n"
  305. sFile += " b direct.call.or.call.software.interrupt\n\n"
  306. sFile += ".Lfunc_end_" + sectionName +":\n"
  307. sFile += " .size " + sectionName +", .Lfunc_end_" + sectionName +" - " + sectionName +"\n"
  308. sFile += " .cantunwind\n"
  309. sFile += " .fnend\n\n"
  310. return sFile
  311. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  312. def generateCppForBreakpointSection ():
  313. s = "#include \"all-headers.h\"\n\n"
  314. s += cppSeparator () + "\n"
  315. s += "static void enableDebugMonitorInterruption (BOOT_MODE) {\n"
  316. s += "//--- Enable DebugMonitor interrupt\n"
  317. s += " #define DEMCR (* ((volatile uint32_t *) 0xE000EDFC))\n"
  318. s += " DEMCR |= (1 << 16) ; // Set MON_EN\n"
  319. s += "}\n\n"
  320. s += cppSeparator () + "\n"
  321. s += "MACRO_BOOT_ROUTINE (enableDebugMonitorInterruption) ;\n\n"
  322. s += cppSeparator ()
  323. return s
  324. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  325. def generateCppForSoftwareInterruptSection ():
  326. s = "#include \"all-headers.h\"\n\n"
  327. s += cppSeparator () + "\n"
  328. s += "static void enableSoftwareInterrupt (BOOT_MODE) {\n"
  329. s += "//--- Enable software interrupt\n"
  330. s += " NVIC_ENABLE_IRQ (ISRSlot::SWINT) ;\n"
  331. s += "//--- Make STIR register accessible in unprivileged mode\n"
  332. s += " #define CCR (* ((volatile uint32_t *) 0xE000ED14))\n"
  333. s += " CCR |= (1 << 1) ;\n"
  334. s += "}\n\n"
  335. s += cppSeparator () + "\n"
  336. s += "MACRO_BOOT_ROUTINE (enableSoftwareInterrupt) ;\n\n"
  337. s += cppSeparator ()
  338. return s
  339. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  340. def generateDisableInterruptSection (sectionName):
  341. sFile = asSeparator ()
  342. sFile += "@ SECTION - " + sectionName + "\n"
  343. sFile += asSeparator () + "\n"
  344. sFile += " .section .text." + sectionName + ", \"ax\", %progbits\n"
  345. sFile += " .global " + sectionName +"\n"
  346. sFile += " .align 1\n"
  347. sFile += " .type " + sectionName +", %function\n\n"
  348. sFile += sectionName +":\n"
  349. sFile += " .fnstart\n"
  350. sFile += "@--- Save preserved registers\n"
  351. sFile += " push {r6, lr}\n"
  352. sFile += "@--- Save interrupt enabled state\n"
  353. sFile += " mrs r6, PRIMASK\n"
  354. sFile += "@--- Disable interrupt\n"
  355. sFile += " cpsid i\n"
  356. sFile += "@--- Call section, interrupts disabled\n"
  357. sFile += " bl section." + sectionName + "\n"
  358. sFile += "@--- Restore interrupt state\n"
  359. sFile += " msr PRIMASK, r6\n"
  360. sFile += "@--- Restore preserved registers and return\n"
  361. sFile += " pop {r6, pc}\n\n"
  362. sFile += ".Lfunc_end_" + sectionName +":\n"
  363. sFile += " .size " + sectionName +", .Lfunc_end_" + sectionName +" - " + sectionName +"\n"
  364. sFile += " .cantunwind\n"
  365. sFile += " .fnend\n\n"
  366. return sFile
  367. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  368. # ENTRY POINT
  369. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  370. #------------------------------ Interrupt dictionary
  371. interruptDictionary = interrupt_names_teensy_3_6.interruptNames ()
  372. # print "Dest " + destinationFile
  373. #------------------------------ Assembly destination file
  374. destinationCppFile = sys.argv [1]
  375. # print "Dest " + destinationAssemblerFile
  376. #------------------------------ Assembly destination file
  377. destinationAssemblerFile = sys.argv [2]
  378. # print "Dest " + destinationAssemblerFile
  379. #------------------------------ Service scheme
  380. serviceScheme = sys.argv [3]
  381. #------------------------------ Section scheme
  382. sectionScheme = sys.argv [4]
  383. #------------------------------ Header files
  384. headerFiles = []
  385. for i in range (5, len (sys.argv)):
  386. headerFiles.append (sys.argv [i])
  387. #print headerFiles
  388. #------------------------------ Destination file string
  389. cppFile = ""
  390. sFile = " .syntax unified\n"
  391. sFile += " .cpu cortex-m4\n"
  392. sFile += " .thumb\n\n"
  393. #------------------------------ Explore header files
  394. interruptServiceList = []
  395. interruptSectionList = []
  396. boolServiceSet = set ()
  397. serviceList = []
  398. sectionList = []
  399. for header in headerFiles:
  400. with open (header) as f:
  401. for line in f:
  402. splitStr = line.strip ().split ("//$interrupt-section ")
  403. if len (splitStr) == 2 :
  404. interruptName = splitStr [1].strip ()
  405. if interruptName in interruptDictionary :
  406. interruptSectionList.append (interruptName)
  407. del interruptDictionary [interruptName]
  408. else:
  409. print (BOLD_RED () + "Error, interrupt '" + interruptName + "' does not exist, or is already assigned." + ENDC ())
  410. sys.exit (1)
  411. splitStr = line.strip ().split ("//$interrupt-service ")
  412. if len (splitStr) == 2 :
  413. interruptName = splitStr [1].strip ()
  414. if interruptName in interruptDictionary :
  415. interruptServiceList.append (interruptName)
  416. del interruptDictionary [interruptName]
  417. else:
  418. print (BOLD_RED () + "Error, interrupt '" + interruptName + "' does not exist, or is already assigned." + ENDC ())
  419. sys.exit (1)
  420. splitStr = line.strip ().split ("//$service ")
  421. if len (splitStr) == 2 :
  422. serviceName = splitStr [1].strip ()
  423. serviceList.append (serviceName)
  424. splitStr = line.strip ().split ("//$bool-service ")
  425. if len (splitStr) == 2 :
  426. serviceName = splitStr [1].strip ()
  427. serviceList.append (serviceName)
  428. boolServiceSet.add (serviceName)
  429. splitStr = line.strip ().split ("//$section ")
  430. if len (splitStr) == 2 :
  431. sectionName = splitStr [1].strip ()
  432. sectionList.append (sectionName)
  433. #------------------------------ Has service ?
  434. if (len (serviceList) > 0) and (serviceScheme == "") :
  435. print (BOLD_RED ()
  436. + "As the project defines service(s), the makefile.json file should have a \"SERVICE-SCHEME\" "
  437. + "entry (asoociated value: \"svc\")"
  438. + ENDC ())
  439. sys.exit (1)
  440. #------------------------------ Has sections ?
  441. if (len (sectionList) > 0) and (sectionScheme == "") :
  442. print (BOLD_RED ()
  443. + "As the project defines section(s), the makefile.json file should have a \"SECTION-SCHEME\" "
  444. + "entry (possible associated value: \"disableInterrupt\", \"bkpt\", \"swint\")"
  445. + ENDC ())
  446. sys.exit (1)
  447. #------------------------------ Services
  448. if serviceScheme == "svc" :
  449. sFile += generateSVChandler ()
  450. del interruptDictionary ["SVC"]
  451. sFile += asSeparator ()
  452. sFile += "@ SERVICES\n"
  453. idx = 1
  454. for service in serviceList :
  455. sFile += asSeparator () + "\n"
  456. sFile += " .section .text." + service + ", \"ax\", %progbits\n"
  457. sFile += " .global " + service +"\n"
  458. sFile += " .align 1\n"
  459. sFile += " .type " + service +", %function\n\n"
  460. sFile += service +":\n"
  461. sFile += " .fnstart\n"
  462. sFile += " svc #" + str (idx) + "\n"
  463. if service in boolServiceSet :
  464. sFile += " b get.user.result\n\n"
  465. else:
  466. sFile += " bx lr\n\n"
  467. sFile += ".Lfunc_end_" + service +":\n"
  468. sFile += " .size " + service +", .Lfunc_end_" + service +" - " + service +"\n"
  469. sFile += " .cantunwind\n"
  470. sFile += " .fnend\n\n"
  471. idx += 1
  472. sFile += asSeparator ()
  473. sFile += "@ SERVICE DISPATCHER TABLE\n"
  474. sFile += asSeparator () + "\n"
  475. sFile += " .align 2\n"
  476. sFile += " .global svc.dispatcher.table\n\n"
  477. sFile += "svc.dispatcher.table:\n"
  478. sFile += " .word start.phase2 @ 0\n"
  479. idx = 1
  480. for service in serviceList :
  481. sFile += " .word service." + service + " @ " + str (idx) + "\n"
  482. idx += 1
  483. sFile += "\n"
  484. #------------------------------ Generate section handler
  485. if sectionScheme == "bkpt" :
  486. cppFile += generateCppForBreakpointSection ()
  487. sFile += generateBreakpointHandler ()
  488. del interruptDictionary ["DebugMonitor"]
  489. sFile += asSeparator ()
  490. sFile += "@ SECTIONS\n"
  491. idx = 0
  492. for section in sectionList :
  493. sFile += generateBreakpointSection (section, idx)
  494. idx += 1
  495. sFile += asSeparator ()
  496. sFile += "@ SECTION DISPATCHER TABLE\n"
  497. sFile += asSeparator () + "\n"
  498. sFile += " .global section.dispatcher.table\n\n"
  499. sFile += "section.dispatcher.table:\n"
  500. idx = 0
  501. for section in sectionList :
  502. sFile += " .word section." + section + " @ " + str (idx) + "\n"
  503. idx += 1
  504. sFile += "\n"
  505. elif sectionScheme == "swint" :
  506. cppFile += generateCppForSoftwareInterruptSection ()
  507. sFile += generateSoftwareInterruptandler ()
  508. del interruptDictionary ["SWINT"]
  509. sFile += asSeparator ()
  510. sFile += "@ SECTIONS\n"
  511. idx = 0
  512. for section in sectionList :
  513. sFile += generateSoftwareInterruptSection (section, idx)
  514. idx += 1
  515. elif sectionScheme == "disableInterrupt" :
  516. for section in sectionList :
  517. sFile += generateDisableInterruptSection (section)
  518. elif len (sectionList) > 0 :
  519. print (BOLD_RED ()
  520. + "In the makefile.json file, the \"SECTION-SCHEME\" key has an invalid \"" + sectionScheme + "\" value; "
  521. + "(possible value: \"disableInterrupt\", \"bkpt\", \"swint\")"
  522. + ENDC ())
  523. sys.exit (1)
  524. #------------------------------ Interrupts as service
  525. for interruptServiceName in interruptServiceList :
  526. sFile += asSeparator ()
  527. sFile += "@ INTERRUPT - SERVICE: " + interruptServiceName + "\n"
  528. sFile += asSeparator () + "\n"
  529. sFile += " .section .text.interrupt." + interruptServiceName + ", \"ax\", %progbits\n\n"
  530. sFile += " .align 1\n"
  531. sFile += " .global interrupt." + interruptServiceName + "\n"
  532. sFile += " .type interrupt." + interruptServiceName + ", %function\n\n"
  533. sFile += "interrupt." + interruptServiceName + ":\n"
  534. sFile += "@----------------------------------------- Save preserved registers\n"
  535. sFile += " push {r4, lr}\n"
  536. sFile += "@----------------------------------------- Activity led On\n"
  537. sFile += " ldr r0, =0x400FF084 @ Address of GPIOC_PSOR control register\n"
  538. sFile += " movs r1, # (1 << 5) @ Port D13 is PORTC:5\n"
  539. sFile += " str r1, [r0] @ turn on\n"
  540. sFile += "@----------------------------------------- R4 <- running task context\n"
  541. sFile += " ldr r4, =var.running.task.control.block.ptr\n"
  542. sFile += " ldr r4, [r4]\n"
  543. sFile += "@----------------------------------------- Call Interrupt handler\n"
  544. sFile += " bl interrupt.service." + interruptServiceName + "\n"
  545. sFile += "@----------------------------------------- Perform the context switch, if needed\n"
  546. sFile += " b handle.context.switch\n\n"
  547. #------------------------------ Interrupts as section
  548. for interruptSectionName in interruptSectionList :
  549. sFile += asSeparator ()
  550. sFile += "@ INTERRUPT - SECTION: " + interruptSectionName + "\n"
  551. sFile += asSeparator () + "\n"
  552. sFile += " .section .text.interrupt." + interruptSectionName + ", \"ax\", %progbits\n\n"
  553. sFile += " .align 1\n"
  554. sFile += " .global interrupt." + interruptSectionName + "\n"
  555. sFile += " .type interrupt." + interruptSectionName + ", %function\n\n"
  556. sFile += "interrupt." + interruptSectionName + ":\n"
  557. sFile += "@----------------------------------------- Activity led On\n"
  558. sFile += " ldr r0, =0x400FF084 @ Address of GPIOC_PSOR control register\n"
  559. sFile += " movs r1, # (1 << 5) @ Port D13 is PORTC:5\n"
  560. sFile += " str r1, [r0] @ turn on\n"
  561. sFile += "@----------------------------------------- Goto interrupt function\n"
  562. sFile += " b interrupt.section." + interruptSectionName + "\n\n"
  563. #------------------------------ Unused interrupts
  564. for unusedInterruptName in interruptDictionary.keys () :
  565. sFile += asSeparator ()
  566. sFile += "@ INTERRUPT - UNUSED: " + unusedInterruptName + "\n"
  567. sFile += asSeparator () + "\n"
  568. sFile += " .section .text.interrupt." + unusedInterruptName + ", \"ax\", %progbits\n\n"
  569. sFile += " .align 1\n"
  570. sFile += " .type interrupt." + unusedInterruptName + ", %function\n"
  571. sFile += " .global interrupt." + unusedInterruptName + "\n\n"
  572. sFile += "interrupt." + unusedInterruptName + ":\n"
  573. sFile += " movs r0, #" + str (interruptDictionary [unusedInterruptName]) + "\n"
  574. sFile += " b unused.interrupt\n\n"
  575. #------------------------------ Write destination file
  576. sFile += asSeparator ()
  577. f = open (destinationAssemblerFile, "wt")
  578. f.write (sFile)
  579. f.close()
  580. f = open (destinationCppFile, "wt")
  581. f.write (cppFile)
  582. f.close()
  583. #———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————