RPI.CPU.Mod 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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 skip
  162. LDR r5, [R2], #4
  163. STR r5, [R3], #4
  164. B copy
  165. vector:
  166. (*
  167. ldr pc, [pc, offset (header)]
  168. ldr pc, [pc, offset (undefined_instruction)]
  169. ldr pc, [pc, offset (software_interrupt)]
  170. ldr pc, [pc, offset (prefetch_abort)]
  171. ldr pc, [pc, offset (data_abort)]
  172. nop
  173. ldr pc, [pc, offset (irq)]
  174. .macro invoke
  175. .alias CPU.#0
  176. stmdb sp!, #1
  177. mov r2, #0
  178. stmdb sp!, {r2}
  179. stmdb sp!, {pc}
  180. ldr pc, [pc, offset (handler)]
  181. add sp, sp, 4
  182. ldmia sp!, #1
  183. .endmacro
  184. fiq:
  185. invoke FIQ, {r0, r1, r2, r3, r4, r5, r6, r7, lr}
  186. subs pc, lr, 4
  187. header:
  188. .qbyte @_header
  189. undefined_instruction:
  190. .qbyte @CPU.UndefinedInstruction
  191. software_interrupt:
  192. .qbyte @CPU.SoftwareInterrupt
  193. prefetch_abort:
  194. .qbyte @CPU.PrefetchAbort
  195. data_abort:
  196. .qbyte @CPU.DataAbort
  197. irq:
  198. .qbyte @CPU.IRQ
  199. handler:
  200. .qbyte HandleInterrupt
  201. *)
  202. vector_end:
  203. (*
  204. invoke UndefinedInstruction, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
  205. movs pc, lr
  206. invoke SoftwareInterrupt, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
  207. movs pc, lr
  208. invoke PrefetchAbort, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
  209. subs pc, lr, 4
  210. invoke DataAbort, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
  211. subs pc, lr, 4
  212. invoke IRQ, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
  213. subs pc, lr, 4
  214. *)
  215. skip:
  216. MOV R2, #0b10001
  217. MSR CPSR_c, R2
  218. MOV SP, #0x7000
  219. MOV R2, #0b10010
  220. MSR CPSR_c, R2
  221. MOV SP, #0x6000
  222. MOV R2, #0b10111
  223. MSR CPSR_c, R2
  224. MOV SP, #0x5000
  225. MOV R2, #0b11011
  226. MSR CPSR_c, R2
  227. MOV SP, #0x4000
  228. MOV R2, #0b10011
  229. MSR CPSR_c, R2
  230. END Initialize;
  231. END CPU.