Kernel.Mos 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. MODULE Kernel;
  2. (*
  3. *)
  4. IMPORT SYSTEM, Platform, Caches, Interrupts, GlobalTimer, Trace, Bit;
  5. CONST
  6. kVersion* = "Ayk 1.0e";
  7. TYPE
  8. (* The prototype of an interrupt handler *)
  9. ExceptionHandler* = PROCEDURE {INTERRUPT} ( );
  10. (* The prototype of an interrupt handler *)
  11. Handler* = PROCEDURE();
  12. (* The prototype of a timer interrupt handler
  13. should be used to implement the scheduler *)
  14. TimerHandler* = PROCEDURE();
  15. (* The prototype of a trap handler
  16. As soon as the systen is up and running, a custom trap handler can be install *)
  17. TrapHandler* = PROCEDURE(type, adr, fp: LONGINT; VAR resFP: LONGINT);
  18. (* The prototype of a undefined instruction trap handler
  19. Can be used to decode custom instructions *)
  20. UDFHandler* = PROCEDURE(adr: LONGINT);
  21. VAR
  22. (* Consists of the delay used to call MicroWait(0)
  23. Is used to make MicroWait as accurate as possible *)
  24. delayCompensation: LONGINT;
  25. DelayDivisor: LONGINT;
  26. (* not necessary on ARM Cortex 9: we have an autoreset
  27. (* the time, when the next timer interrupt shall occur *)
  28. nextTimerInterrupt: LONGINT;
  29. *)
  30. (* main irq handlers *)
  31. irqHandlers: ARRAY Platform.MaxNumIrq OF Handler;
  32. (* Handlers for GPIO interrupts *)
  33. gpioHandlers: ARRAY Platform.NumGPIOPins OF Handler;
  34. (* The system time in milliseconds. Is updated by the primary timer interrupt
  35. handler *)
  36. timer: LONGINT;
  37. (* User installable handlers for timer, traps and Udefinded instruction traps *)
  38. timerHandler: TimerHandler; trapHandler: TrapHandler;
  39. udfHandler: UDFHandler;
  40. (* Temporary variable that stores the lnk register. Must be a global variable to be
  41. accessible in all processor modes *)
  42. lnk: PROCEDURE;
  43. cnt: LONGINT;
  44. snoop: LONGINT;
  45. lr: ADDRESS;
  46. toggle : BOOLEAN;
  47. (* Copy procedure like SYSTEM.MOVE. src and dst must be Aligned to LONGINT *)
  48. PROCEDURE Move*(src, dst, len: LONGINT);
  49. VAR i, word: LONGINT; chr: CHAR;
  50. BEGIN
  51. IF len > 0 THEN
  52. (* Copy Integerwise if possible *)
  53. IF (src MOD 4 # 0) OR (dst MOD 4 # 0) THEN
  54. WHILE len > 0 DO
  55. SYSTEM.GET(src, chr); SYSTEM.PUT(dst, chr);
  56. INC(src); INC(dst); DEC(len);
  57. END;
  58. ELSE
  59. i := len DIV 4;
  60. WHILE i > 0 DO
  61. SYSTEM.GET(src, word); SYSTEM.PUT(dst, word);
  62. INC(src, 4); INC(dst, 4); DEC(i);
  63. END;
  64. i := len MOD 4;
  65. WHILE i > 0 DO
  66. SYSTEM.GET(src, chr); SYSTEM.PUT(dst, chr);
  67. INC(src); INC(dst); DEC(i);
  68. END;
  69. END;
  70. END;
  71. END Move;
  72. (* Assumes interrupts are disabled *)
  73. PROCEDURE CleanCache*;
  74. BEGIN
  75. Caches.CleanDCache();
  76. END CleanCache;
  77. PROCEDURE EnableIRQs*;
  78. VAR cpsr: LONGINT;
  79. BEGIN
  80. SYSTEM.STPSR(0, cpsr);
  81. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) - {7, 8});
  82. SYSTEM.LDPSR(0, cpsr);
  83. END EnableIRQs;
  84. (* Taken from Minos/Kernel.Mos *)
  85. PROCEDURE DisableIRQs*;
  86. VAR cpsr: LONGINT;
  87. BEGIN
  88. SYSTEM.STPSR(0, cpsr);
  89. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) + {7, 8});
  90. SYSTEM.LDPSR( 0, cpsr);
  91. END DisableIRQs;
  92. (*
  93. (* Enable the system clock *)
  94. PROCEDURE EnableIOCLK*;
  95. BEGIN
  96. GPIOInit(Platform.MHZ3686K, TRUE , 1);
  97. END EnableIOCLK;
  98. (* Enable/Disable the system clock to a specific device *)
  99. PROCEDURE EnableClock*(num: LONGINT; enable: BOOLEAN);
  100. VAR reg: SET;
  101. BEGIN
  102. IF(num >= Platform.MinValidClock) & (num <= Platform.MaxValidClock) THEN
  103. SYSTEM.GET(Platform.CKEN, reg);
  104. IF enable THEN reg := reg + {num} ELSE reg := reg - {num} END;
  105. SYSTEM.PUT32(Platform.CKEN, reg);
  106. END;
  107. END EnableClock;
  108. *)
  109. (*
  110. PROCEDURE Timer0IrqHandler( );
  111. VAR a: SET;
  112. BEGIN
  113. (*Trace.StringLn("TimerIRQ");*)
  114. IF timerHandler # NIL THEN
  115. (* Context Switch *)
  116. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.IRQDisabled + Platform.FIQDisabled);
  117. lr := SYSTEM.LNK();
  118. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.FIQDisabled);
  119. timerHandler;
  120. (* Go back to IRQ mode Context Switch *)
  121. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.IRQDisabled + Platform.FIQDisabled);
  122. SYSTEM.SETLNK(lr);
  123. SYSTEM.LDPSR( 0, Platform.IRQMode + Platform.IRQDisabled + Platform.FIQDisabled);
  124. END;
  125. Trace.String(".");
  126. END Timer0IrqHandler;
  127. *)
  128. (* Get the internal hardware clock cycle counter *)
  129. PROCEDURE GetOSTimer*(): LONGINT;
  130. VAR i: LONGINT;
  131. BEGIN
  132. RETURN GlobalTimer.GetTimerLowValue();
  133. END GetOSTimer;
  134. PROCEDURE Reset*();
  135. BEGIN
  136. END Reset;
  137. (* the main interrupt timer routine. Used for doing the timecritical work in the main scheduler *)
  138. (*
  139. PROCEDURE Timer0IrqHandler;
  140. VAR lr, lirq, cpsr, fp: LONGINT;
  141. BEGIN
  142. (*
  143. Trace.String("0");
  144. INC(snoop);
  145. *)
  146. (* Set timer to new timeout *)
  147. nextTimerInterrupt := nextTimerInterrupt + (Platform.OSDELAY);
  148. (*
  149. IF ( snoop = 1 ) THEN
  150. Trace.String("N ");
  151. Trace.Hex( nextTimerInterrupt, -8);
  152. Trace.Ln;
  153. Trace.String(" O ");
  154. Trace.Hex( GetOSTimer(),-8);
  155. Trace.Ln;
  156. END;
  157. *)
  158. SYSTEM.PUT32( Platform.OSMR0, nextTimerInterrupt );
  159. (* clear match *)
  160. SYSTEM.PUT32(Platform.OSSR, 1); (* Clear Match *)
  161. SYSTEM.PUT32(Platform.OSIER, 1); (* Enable Interrupt on Match0 *)
  162. INC(timer, Platform.UNIT);
  163. (*
  164. IF timerHandler # NIL THEN
  165. (*
  166. cpsr := Platform.SVCMode;
  167. cpsr := Bit.ORR(cpsr, 0C0H);
  168. SYSTEM.LDPSR(0, cpsr);
  169. *)
  170. CODE
  171. MRS R0, CPSR
  172. BIC R0,R0,#01FH (* clear the mode bits *)
  173. ORR R0,R0,#013H (* enable supervisor mode *)
  174. ORR R0,R0,#0C0H (* disable IRQ *)
  175. MSR CPSR_c,R0 (* store the status register *)
  176. END;
  177. lr:= SYSTEM.LNK();
  178. CODE
  179. MRS R0, CPSR
  180. BIC R0,R0,#0C0H (* clear the IRQ bits, enable the global IRQ *)
  181. MSR CPSR_c,R0 (* store the status register *)
  182. END;
  183. (*
  184. SYSTEM.LDPSR(0, Platform.SVCMode );
  185. *)
  186. timerHandler;
  187. (*
  188. (* disable the IRQs *)
  189. SYSTEM.STPSR(0, cpsr);
  190. cpsr := Bit.ORR(cpsr, 0C0H);
  191. SYSTEM.LDPSR(0, cpsr);
  192. *)
  193. CODE
  194. MRS R0, CPSR
  195. ORR R0,R0,#0C0H (* disable IRQ *)
  196. MSR CPSR_c,R0 (* store the status register *)
  197. END;
  198. (* restore the link register *)
  199. SYSTEM.SETLNK( lr );
  200. CODE
  201. MRS R0, CPSR
  202. BIC R0,R0,#01FH (* clear the mode bits, IRQ is still disabled *)
  203. ORR R0,R0,#012H (* enable IRQ processor mode *)
  204. MSR CPSR_c,R0 (* store the status register *)
  205. END;
  206. (*
  207. (* return to IRQ mode *)
  208. SYSTEM.LDPSR(0, Platform.IRQMode + Platform.IRQDisabled+ Platform.FIQDisabled );
  209. *)
  210. END;
  211. *)
  212. END Timer0IrqHandler;
  213. *)
  214. (*
  215. (* Reset the watchdog. Do this periodically, otherwise the system will reboot *)
  216. PROCEDURE ResetWatchdog;
  217. VAR reg: LONGINT;
  218. BEGIN
  219. SYSTEM.GET(Platform.OSCR, reg);
  220. reg := reg + Platform.WatchdogTimerIntervall;
  221. SYSTEM.PUT32(Platform.OSMR3, reg);
  222. END ResetWatchdog;
  223. (* Enable the system Watchdog. Once enabled, the watchdog can only be disabled by rebooting the system *)
  224. PROCEDURE EnableWatchdog;
  225. BEGIN
  226. ResetWatchdog;
  227. (* Set bit 0 to enable the watchdog. The watchdog can only be disabled by resettting the cpu *)
  228. SYSTEM.PUT32(Platform.OWER, {0});
  229. END EnableWatchdog;
  230. (* Get the internal hardware clock cycle counter *)
  231. PROCEDURE GetOSTimer*(): LONGINT;
  232. VAR i: LONGINT;
  233. BEGIN
  234. SYSTEM.GET(Platform.OSCR, i); RETURN i
  235. END GetOSTimer;
  236. *)
  237. (* Wait uSec microseconds, max allowed is 429000 uSecs *)
  238. (* min @ 100Mhz is 2.1 usec *)
  239. (*
  240. PROCEDURE MicroWait*(uSec: LONGINT);
  241. VAR current, wait: LONGINT;
  242. BEGIN
  243. SYSTEM.GET(Platform.OSCR, current);
  244. wait := current +((uSec * DelayDivisor) DIV 1000H) - delayCompensation;
  245. REPEAT SYSTEM.GET(Platform.OSCR, current);
  246. UNTIL current > wait;
  247. END MicroWait;
  248. (* Wait mSec milliseconds *)
  249. PROCEDURE MilliWait*(mSec: LONGINT);
  250. BEGIN
  251. WHILE mSec > 0 DO MicroWait(1000); DEC(mSec); END;
  252. END MilliWait;
  253. (* Calculate the overhead of calling MicroWait(0) *)
  254. PROCEDURE SetDelayCompensation*;
  255. VAR startTime, stopTime: LONGINT;
  256. BEGIN
  257. delayCompensation := 0;
  258. DelayDivisor := ENTIER(REAL(Platform.CLOCKDIVISOR) / 2.44140625);
  259. DisableIRQs; SYSTEM.GET(Platform.OSCR, startTime); MicroWait(0);
  260. SYSTEM.GET(Platform.OSCR, stopTime); (*EnableIRQs; *)
  261. IF stopTime > startTime THEN delayCompensation := stopTime - startTime;
  262. ELSE delayCompensation := startTime - stopTime;
  263. END;
  264. END SetDelayCompensation;
  265. *)
  266. (* Get the system time in milliseconds, driven by the timer interrupt, rel to system boot up *)
  267. PROCEDURE GetTime*(): LONGINT;
  268. BEGIN
  269. RETURN timer
  270. END GetTime;
  271. PROCEDURE UpdateTime*( irq: LONGINT );
  272. BEGIN
  273. INC( timer );
  274. (*
  275. IF ( timer MOD 1000 ) = 0 THEN
  276. Trace.String("c");
  277. END;
  278. *)
  279. (*IF ( toggle ) THEN
  280. IoControl.ClearPin( 26 );
  281. ELSE
  282. IoControl.SetPin( 26 );
  283. END;
  284. toggle := ~toggle;*)
  285. END UpdateTime;
  286. PROCEDURE ShowTime*();
  287. BEGIN
  288. Trace.String("Time : "); Trace.Int( timer, 8 ); Trace.Ln;
  289. END ShowTime;
  290. (* Init the system *)
  291. PROCEDURE Init;
  292. VAR val: SET;
  293. BEGIN
  294. timer := 0;
  295. delayCompensation := 0;
  296. Interrupts.RegisterTimerHandler( UpdateTime );
  297. Trace.StringLn("Init Finished()");
  298. END Init;
  299. PROCEDURE EnableMMU*(translationBase, flags: ADDRESS);
  300. BEGIN
  301. Trace.String("tb = "); Trace.Hex(translationBase,-8); Trace.Ln;
  302. CODE
  303. ldr r0, [FP, #translationBase]
  304. orr r0, r0, #05BH
  305. mcr p15, 0, r0, c2, c0, 0
  306. mvn r0, #0 ; mmu domains: 1111 = manager
  307. mcr p15, 0, r0, c3, c0, 0
  308. ldr r0, [FP, #flags ]
  309. mcr p15, 0, r0, c1, c0, 0
  310. END;
  311. Trace.StringLn("enabled");
  312. (*
  313. dsb();
  314. isb();
  315. *)
  316. END EnableMMU;
  317. CONST
  318. PageTableBaseAddress = 10000000H - 100000H; (* 1 MB below highest address *);
  319. (* 1 MB page table entry *)
  320. PROCEDURE MapPage*(virtual, physical: LONGINT; flags: LONGINT);
  321. CONST
  322. PageSize = 100000H; (* 1 MB pages *)
  323. BEGIN
  324. ASSERT(virtual >= 0);
  325. ASSERT(virtual < 1000H);
  326. ASSERT(physical >= 0);
  327. ASSERT(physical < 1000H);
  328. SYSTEM.PUT(PageTableBaseAddress + virtual*4, physical * PageSize + flags);
  329. (*IF PageTableBaseAddress MOD 40H = 0 THEN
  330. UartMin.Str("map: "); UartMin.Hex(PageTableBaseAddress+virtual*4);
  331. UartMin.Str(" -> "); UartMin.Hex(physical*PageSize + flags);
  332. UartMin.Ln;
  333. END;
  334. *)
  335. END MapPage;
  336. CONST
  337. (* bits *)
  338. NS = 80000H;;
  339. nG = 20000H;
  340. S = 10000H;
  341. AP2 = 8000H;
  342. TEX = 1000H;
  343. AP = 400H;
  344. IMP = 200H;
  345. Domain = 20H;
  346. XN=10H;
  347. C=8H;
  348. B=4H;
  349. Section = 2;
  350. MappedCached* = B + AP*3H + TEX*5H + S + Section + 0FH * Domain;
  351. MappedNonCached* = Section;
  352. Unmapped* = 0;
  353. BEGIN
  354. Trace.StringLn("Init kernel Init()");
  355. Init;
  356. toggle := FALSE;
  357. Trace.StringLn("Module init of kernel completed.");
  358. END Kernel.