The stack size is hard-coded to 32 kB (8000H) in two places.
Kernel.Init:
Code: Select all
PROCEDURE Init*;
BEGIN
(* ... *)
stackSize := 8000H;
(* ... *)
END Init;
Code: Select all
PROCEDURE Init*;
BEGIN
(* ... *) DEC(limit, 8000H)
END Init;
Interestingly, the (final) stack size could be set lower than the 10k -- if we're sure all modules loaded upon system start don't use the addresses the range Kernel.stackOrg - 10k. Nothing stops the stack pointer of "reaching" into module memory space (unless we have some stack overflow protection in place and active). As long as that space is not used by modules, nothing bad will happen. Hence, the stack size could be set to, say, 8k, and upon startup, the stack would temporarily "borrow" some 2k of module space.
The required changes should be obvious and straight-forward:
Code: Select all
MODULE Kernel;
(* ... *)
CONST StackSize = 4000H; (* 16k *)
(* ... *)
PROCEDURE Init*;
BEGIN
(* ... *)
stackSize := StackSize;
(* ... *)
END Init;
END Kernel.
Code: Select all
MODULE Modules;
IMPORT SYSTEM, Files, Kernel;
(* ... *)
PROCEDURE Init*;
BEGIN
(* .. *) DEC(limit, Kernel.stackSize)
END Init;
(* ... *)
END Modules.
Alternatively, the stack size can be passed from the boot loader, together with the values for MemLim and stackOrg. Address 4 can be used for that. It works well, too. This has the advantage that the memory configuration parameters for different boards and RAM layouts are in one place, but it requires to recreate the FPGA implementation for a stack size change, as we do now for, say, a heap size change. The boot file is the same for all memory layout variants. I am not sure yet which of the two solutions I prefer.
Code: Select all
MODULE* BootLoad;
(* ...*)
CONST StackSize = 4000H;
(* ... *)
BEGIN
(* ... *)
SYSTEM.PUT(12, MemLim); SYSTEM.PUT(24, stackOrg); SYSTEM.PUT(4, StackSize); LED(84H)
END BootLoad.
Code: Select all
MODULE Kernel;
(* ... *)
PROCEDURE Init*;
BEGIN
(* ... *)
SYSTEM.GET(4, stackSize)
(* ... *)
END Init;
END Kernel.
A concluding note about really, really squeezing out the last byte of available RAM for the stack.
The body of Modules:
Code: Select all
BEGIN Init; Load("Oberon", M);
LED(res); REPEAT UNTIL FALSE (*only if load fails*)
END Modules.
Code: Select all
BEGIN
(* ... *)
Modules.Load("System", Mod); Mod := NIL;
Loop
END Oberon.
Code: Select all
PROCEDURE Reset*;
BEGIN
IF CurTask.state = active THEN Remove(CurTask) END ;
SYSTEM.LDREG(14, Kernel.stackOrg); (*reset stack pointer*) Loop
END Reset;
Code: Select all
BEGIN
(* ... *)
Modules.Load("System", Mod); Mod := NIL;
SYSTEM.LDREG(14, Kernel.stackOrg);
Loop
END Oberon.
Of course, executing the command 'Oberon.Reset' from the Astrobe terminal has the same effect.