RPI.CPU.Mod 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. (* Runtime support for CPU internals *)
  2. (* Copyright (C) Florian Negele *)
  3. MODULE CPU;
  4. IMPORT SYSTEM;
  5. CONST StackSize* = 2048;
  6. CONST Quantum* = 100000;
  7. CONST CacheLineSize* = 32;
  8. CONST StackDisplacement* = 0;
  9. PROCEDURE Backoff-;
  10. CODE
  11. MOV R2, #0x100
  12. loop:
  13. SUBS R2, R2, #1
  14. BNE loop
  15. END Backoff;
  16. (* cpu control *)
  17. PROCEDURE Delay- (cycles: SIZE);
  18. CODE
  19. LDR R2, [FP, #cycles]
  20. delay:
  21. SUBS R2, R2, #1
  22. BNE delay
  23. END Delay;
  24. PROCEDURE {NORETURN} Reset-;
  25. BEGIN {UNCOOPERATIVE, UNCHECKED}
  26. WriteWord (WDOG, PASSWORD + 1);
  27. WriteWord (RSTC, PASSWORD + FULLRESET);
  28. Halt;
  29. END Reset;
  30. PROCEDURE {NORETURN} Halt-;
  31. CODE
  32. MRS R2, CPSR
  33. ORR R2, R2, #0b1100000
  34. MSR CPSR_c, r2
  35. WFI
  36. END Halt;
  37. (* memory management *)
  38. CONST MemorySize* = 964 * MB; MB = 1024 * 1024;
  39. VAR pageTable: RECORD entry {ALIGNED (4000H)}: ARRAY 4096 OF SIZE END;
  40. PROCEDURE IdentityMapMemory-;
  41. CONST Section = 2H; Domain0 = 0H; FullAccess = 0C00H; NormalWriteBackAllocate = 100CH; StronglyOrdered = 0H; Shareable = 10000H;
  42. CONST NormalMemory = Section + Domain0 + FullAccess + NormalWriteBackAllocate + Shareable;
  43. CONST StronglyOrderedMemory = Section + Domain0 + FullAccess + StronglyOrdered;
  44. VAR index: SIZE;
  45. BEGIN {UNCOOPERATIVE, UNCHECKED}
  46. FOR index := 0 TO MemorySize DIV MB - 1 DO pageTable.entry[index] := index * MB + NormalMemory END;
  47. FOR index := MemorySize DIV MB TO LEN (pageTable.entry) - 1 DO pageTable.entry[index] := index * MB + StronglyOrderedMemory END;
  48. END IdentityMapMemory;
  49. PROCEDURE EnableMemoryManagementUnit-;
  50. CODE
  51. load:
  52. LDR R0, [PC, #page-$-8]
  53. MCR P15, 0, R0, C2, C0, 0
  54. B grant
  55. page:
  56. d32 pageTable
  57. grant:
  58. MOV R0, #0b11
  59. MCR P15, 0, R0, C3, C0, 0
  60. enable:
  61. MCR P15, 0, R0, C1, C0, 0
  62. ORR R0, R0, #0b1 ; memory protection
  63. ORR R0, R0, #0b100 ; data and unified cache
  64. ORR R0, R0, #0b100000000000 ; branch prediction
  65. ORR R0, R0, #0b1000000000000 ; instruction cache
  66. MCR P15, 0, R0, C1, C0, 0
  67. END EnableMemoryManagementUnit;
  68. (* hardware registers *)
  69. CONST WDOG* = 03F100024H; RSTC* = 03F10001CH; PASSWORD = 05A000000H; FULLRESET = 000000020H;
  70. CONST GPFSEL0* = 03F200004H; FSEL0* = 0; FSEL1* = 3; FSEL2* = 6; FSEL3* = 9; FSEL4* = 12; FSEL5* = 15; FSEL6* = 18; FSEL7* = 21; FSEL8* = 24; FSEL9* = 27;
  71. CONST GPFSEL1* = 03F200008H; FSEL10* = 0; FSEL11* = 3; FSEL12* = 6; FSEL13* = 9; FSEL14* = 12; FSEL15* = 15; FSEL16* = 18; FSEL17* = 21; FSEL18* = 24; FSEL19* = 27;
  72. CONST GPSET0* = 03F20001CH; GPSET1* = 03F200020H;
  73. CONST GPCLR0* = 03F200028H; GPCLR1* = 03F20002CH;
  74. CONST GPPUD* = 03F200094H; PUD* = 0;
  75. CONST GPPUDCLK0* = 03F200098H; GPPUDCLK1* = 03F20009CH;
  76. CONST IRQBasicPending* = 03F00B200H; IRQPending1* = 03F00B204H; IRQPending2* = 03F00B208H;
  77. CONST IRQEnable1* = 03F00B210H; IRQEnable2* = 03F00B214H; IRQEnableBasic* = 03F00B218H;
  78. CONST IRQDisable1* = 03F00B21CH; IRQDisable2* = 03F00B220H; IRQDisableBasic* = 03F00B224H;
  79. CONST STCS* = 03F003000H; M0* = 0; M1* = 1; M2* = 2; M3* = 3;
  80. CONST STCLO* = 03F003004H; STCHI* = 03F003008H;
  81. CONST STC0* = 03F00300CH; STC1* = 03F003010H; STC2* = 03F003014H; STC3* = 03F003018H;
  82. CONST FUARTCLK* = 3000000;
  83. CONST UART_DR* = 03F201000H;
  84. CONST UART_FR* = 03F201018H; RXFE* = 4; TXFF* = 5; TXFE* = 7;
  85. CONST UART_IBRD* = 03F201024H;
  86. CONST UART_FBRD* = 03F201028H;
  87. CONST UART_LCRH* = 03F20102CH; FEN* = 4; WLEN8* = {5, 6};
  88. CONST UART_CR* = 03F201030H; UARTEN* = 0; TXE* = 8; RXE* = 9;
  89. CONST UART_IMSC* = 03F201038H; RXIM* = 4;
  90. CONST UART_ICR* = 03F201044H; RXIC* = 4;
  91. PROCEDURE ReadWord- (register: ADDRESS): WORD;
  92. CODE
  93. LDR R2, [FP, #register]
  94. LDR R0, [R2, #0]
  95. END ReadWord;
  96. PROCEDURE ReadMask- (register: ADDRESS): SET;
  97. CODE
  98. LDR R2, [FP, #register]
  99. LDR R0, [R2, #0]
  100. END ReadMask;
  101. PROCEDURE WriteWord- (register: ADDRESS; value: ADDRESS);
  102. CODE
  103. LDR R2, [FP, #register]
  104. LDR R3, [FP, #value]
  105. STR R3, [R2, #0]
  106. END WriteWord;
  107. PROCEDURE WriteMask- (register: ADDRESS; value: SET);
  108. CODE
  109. LDR R2, [FP, #register]
  110. LDR R3, [FP, #value]
  111. STR R3, [R2, #0]
  112. END WriteMask;
  113. PROCEDURE Mask- (register: ADDRESS; value: SET);
  114. CODE
  115. LDR R2, [FP, #register]
  116. LDR R3, [FP, #value]
  117. LDR R4, [R2, #0]
  118. ORR R4, R4, R3
  119. STR R4, [R2, #0]
  120. END Mask;
  121. PROCEDURE Unmask- (register: ADDRESS; value: SET);
  122. CODE
  123. LDR R2, [FP, #register]
  124. LDR R3, [FP, #value]
  125. LDR R4, [R2, #0]
  126. BIC R4, R4, R3
  127. STR R4, [R2, #0]
  128. END Unmask;
  129. (* interrupt handling *)
  130. CONST Interrupts* = 7;
  131. CONST UndefinedInstruction* = 1; SoftwareInterrupt* = 2; PrefetchAbort* = 3; DataAbort* = 4; IRQ* = 5; FIQ* = 6;
  132. TYPE InterruptHandler* = PROCEDURE (index: SIZE);
  133. VAR handlers: ARRAY Interrupts OF InterruptHandler;
  134. PROCEDURE InstallInterrupt- (handler: InterruptHandler; index: SIZE): InterruptHandler;
  135. VAR previous: InterruptHandler;
  136. BEGIN {UNCOOPERATIVE, UNCHECKED}
  137. ASSERT (handler # NIL); ASSERT (index < Interrupts);
  138. REPEAT previous := CAS (handlers[index], NIL, NIL) UNTIL CAS (handlers[index], previous, handler) = previous;
  139. RETURN previous;
  140. END InstallInterrupt;
  141. PROCEDURE HandleInterrupt (index: SIZE);
  142. BEGIN {UNCOOPERATIVE, UNCHECKED}
  143. SYSTEM.SetActivity (NIL);
  144. IF index = IRQ THEN WriteMask (IRQDisable1, ReadMask (IRQPending1)); WriteMask (IRQDisable2, ReadMask (IRQPending2)) END;
  145. IF handlers[index] # NIL THEN handlers[index] (index) ELSE HALT (1234) END;
  146. END HandleInterrupt;
  147. PROCEDURE DisableInterrupt- (index: SIZE);
  148. VAR previous: InterruptHandler;
  149. BEGIN {UNCOOPERATIVE, UNCHECKED}
  150. ASSERT (index < Interrupts);
  151. IF index = IRQ THEN WriteMask (IRQDisable1, ReadMask (IRQEnable1)); WriteMask (IRQDisable2, ReadMask (IRQEnable2)) END;
  152. REPEAT previous := CAS (handlers[index], NIL, NIL) UNTIL CAS (handlers[index], previous, NIL) = previous;
  153. END DisableInterrupt;
  154. PROCEDURE Initialize-;
  155. CODE
  156. ADD R2, PC, #vector
  157. MOV R3, #0
  158. ADD R4, R3, #vector_end - vector
  159. copy:
  160. CMP R3, R4
  161. BEQ vector_end
  162. LDR r5, [R2], #4
  163. STR r5, [R3], #4
  164. B copy
  165. vector:
  166. LDR PC, [PC, #header-$-8]
  167. LDR PC, [PC, #undefined_instruction-$-8]
  168. LDR PC, [PC, #software_interrupt-$-8]
  169. LDR PC, [PC, #prefetch_abort-$-8]
  170. LDR PC, [PC, #data_abort-$-8]
  171. MOV R0, R0
  172. LDR PC, [PC, #irq-$-8]
  173. fiq:
  174. STMDB SP!, {R0, R1, R2, R3, R4, R5, R6, R7, LR}
  175. MOV R2, #UndefinedInstruction
  176. STR R2, [SP, #-4]!
  177. LDR R2, [PC, #handle-$-8]
  178. BLX R2
  179. ADD SP, SP, #4
  180. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, LR}
  181. SUBS PC, LR, #4
  182. header:
  183. d32 0x8000
  184. undefined_instruction:
  185. d32 UndefinedInstructionHandler
  186. software_interrupt:
  187. d32 SoftwareInterruptHandler
  188. prefetch_abort:
  189. d32 PrefetchAbortHandler
  190. data_abort:
  191. d32 DataAbortHandler
  192. irq:
  193. d32 IRQHandler
  194. handle:
  195. d32 HandleInterrupt
  196. vector_end:
  197. MOV R2, #0b10001
  198. MSR CPSR_c, R2
  199. MOV SP, #0x7000
  200. MOV R2, #0b10010
  201. MSR CPSR_c, R2
  202. MOV SP, #0x6000
  203. MOV R2, #0b10111
  204. MSR CPSR_c, R2
  205. MOV SP, #0x5000
  206. MOV R2, #0b11011
  207. MSR CPSR_c, R2
  208. MOV SP, #0x4000
  209. MOV R2, #0b10011
  210. MSR CPSR_c, R2
  211. END Initialize;
  212. PROCEDURE {NOPAF} UndefinedInstructionHandler;
  213. CODE
  214. STMDB SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  215. MOV R2, #UndefinedInstruction
  216. STR R2, [SP, #-4]!
  217. LDR R2, [PC, #handle-$-8]
  218. BLX R2
  219. ADD SP, SP, #4
  220. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  221. MOVS PC, LR
  222. handle:
  223. d32 HandleInterrupt
  224. END UndefinedInstructionHandler;
  225. PROCEDURE {NOPAF} SoftwareInterruptHandler;
  226. CODE
  227. STMDB SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  228. MOV R2, #SoftwareInterrupt
  229. STR R2, [SP, #-4]!
  230. LDR R2, [PC, #handle-$-8]
  231. BLX R2
  232. ADD SP, SP, #4
  233. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  234. MOVS PC, LR
  235. handle:
  236. d32 HandleInterrupt
  237. END SoftwareInterruptHandler;
  238. PROCEDURE {NOPAF} PrefetchAbortHandler;
  239. CODE
  240. STMDB SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  241. MOV R2, #PrefetchAbort
  242. STR R2, [SP, #-4]!
  243. LDR R2, [PC, #handle-$-8]
  244. BLX R2
  245. ADD SP, SP, #4
  246. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  247. SUBS PC, LR, #4
  248. handle:
  249. d32 HandleInterrupt
  250. END PrefetchAbortHandler;
  251. PROCEDURE {NOPAF} DataAbortHandler;
  252. CODE
  253. STMDB SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  254. MOV R2, #DataAbort
  255. STR R2, [SP, #-4]!
  256. LDR R2, [PC, #handle-$-8]
  257. BLX R2
  258. ADD SP, SP, #4
  259. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  260. SUBS PC, LR, #4
  261. handle:
  262. d32 HandleInterrupt
  263. END DataAbortHandler;
  264. PROCEDURE {NOPAF} IRQHandler;
  265. CODE
  266. STMDB SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  267. MOV R2, #IRQ
  268. STR R2, [SP, #-4]!
  269. LDR R2, [PC, #handle-$-8]
  270. BLX R2
  271. ADD SP, SP, #4
  272. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR}
  273. SUBS PC, LR, #4
  274. handle:
  275. d32 HandleInterrupt
  276. END IRQHandler;
  277. END CPU.