<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:Helvetica;
        panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"Apple Color Emoji";
        panose-1:0 0 0 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
p.p1, li.p1, div.p1
        {mso-style-name:p1;
        margin:0cm;
        font-size:7.5pt;
        font-family:Helvetica;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=DE-CH link=blue vlink=purple style='word-wrap:break-word'><div class=WordSection1><p class=p1><span lang=EN-US style='font-size:11.0pt;font-family:"Calibri",sans-serif'>Gray<o:p></o:p></span></p><p class=p1><span lang=EN-US style='font-size:11.0pt;font-family:"Calibri",sans-serif'><o:p> </o:p></span></p><p class=p1><span lang=EN-US style='font-size:11.0pt;font-family:"Calibri",sans-serif'>Indeed, from the CPU’s point of view, interrupt handlers <b><span style='color:#C00000'>have to store all registers they use</span></b>.<o:p></o:p></span></p><p class=p1><span lang=EN-US style='font-size:11.0pt;font-family:"Calibri",sans-serif'>“No register values are saved, because every interrupt handler is assumed to save (at least) registers R0 and R1.”<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p><p class=MsoNormal><span lang=EN-US>For interrupt procedures, the compiler automatically generates code to put R0 .. R2 onto the stack. If your interrupt routine has complex calculations involving more registers or calling procedures you have to store all used registers yourself. Especially, when calling procedures where you don’t have a clue what registers they are going to use, you best put the whole register set onto the stack.<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p><p class=MsoNormal><span lang=EN-US>br<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US>Jörg<o:p></o:p></span></p><p class=MsoNormal><span lang=EN-US style='mso-fareast-language:EN-US'><o:p> </o:p></span></p><div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm'><p class=MsoNormal><b><span style='font-size:12.0pt;color:black'>Von: </span></b><span style='font-size:12.0pt;color:black'>Oberon <oberon-bounces@lists.inf.ethz.ch> im Auftrag von gray <gray@grayraven.org><br><b>Antworten an: </b>ETH Oberon and related systems <oberon@lists.inf.ethz.ch><br><b>Datum: </b>Mittwoch, 31. März 2021 um 04:39<br><b>An: </b><oberon@lists.inf.ethz.ch><br><b>Betreff: </b>Re: [Oberon] Emulating interrupts in oberon-risc-emu as in the RISC5 specification<o:p></o:p></span></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>For the multiple interrupt handling in software approach, if I understand Jörg's proposal correctly, it's important not to forget to explicitly store the link register before, and restore it after invoking the individual handler procedures. The processor does not do this. Thanks to Paul Reed for relieving my related headaches last year. :)<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>As an aside, with an FPGA it's not too complicated to implement a hardware-based interrupt controller with several input lines as a "front end" to the one interrupt of the processor. I have used mine for months now and it works well. I currently use it mostly for handling errors detected by hardware devices (eg. watchdog, stack overflow monitor).<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Regards<o:p></o:p></p></div><div><p class=MsoNormal>-- gray<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>On Wed, 31 Mar 2021, at 04:45, Jörg wrote:<o:p></o:p></p></div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt' id=qt><div><p class=MsoNormal>Although TestInt is low-level, it should use Kernel.Install (SYSTEM.ADR(Int), 4) to make it a little bit less low-level<span style='font-family:"Apple Color Emoji"'>😀</span><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>This little wrapper makes interrupts a little bit better consumable:<o:p></o:p></p></div><div><p class=MsoNormal>MODULE Interrupts; (* jr/31mar21 *)<o:p></o:p></p></div><div><p class=MsoNormal>IMPORT S := SYSTEM, Kernel;<o:p></o:p></p></div><div><p class=MsoNormal>PROCEDURE Install*(handler: PROCEDURE);<o:p></o:p></p></div><div><p class=MsoNormal>  BEGIN Kernel.Install(S.ADR(handler), 4) END Install;<o:p></o:p></p></div><div><p class=MsoNormal>PROCEDURE Set*(on: BOOLEAN);<o:p></o:p></p></div><div><p class=MsoNormal>  BEGIN S.LDPSR(ORD(on)) END Set;<o:p></o:p></p></div><div><p class=MsoNormal>END Interrupts.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>With it TestInt.Mod gets<o:p></o:p></p></div><div><p class=MsoNormal>MODULE TestInt;<o:p></o:p></p></div><div><p class=MsoNormal>IMPORT Interrupts;<o:p></o:p></p></div><div><p class=MsoNormal>VAR led, cnt: INTEGER;<o:p></o:p></p></div><div><p class=MsoNormal>PROCEDURE* MyInterrupt;<o:p></o:p></p></div><div><p class=MsoNormal>  BEGIN<o:p></o:p></p></div><div><p class=MsoNormal>    INC(cnt); IF cnt = 500 THEN led := 3-led; LED(led); cnt := 0 END<o:p></o:p></p></div><div><p class=MsoNormal>  END MyInterrupt;<o:p></o:p></p></div><div><p class=MsoNormal>PROCEDURE On*; BEGIN Interrupts.Set(TRUE) END On;<o:p></o:p></p></div><div><p class=MsoNormal>PROCEDURE Off*; BEGIN Interrupts.Set(FALSE) END Off;<o:p></o:p></p></div><div><p class=MsoNormal>BEGIN<o:p></o:p></p></div><div><p class=MsoNormal>  led := 1; cnt := 0; Interrupts.Install(MyInterrupt)<o:p></o:p></p></div><div><p class=MsoNormal>END<o:p></o:p></p></div><div><p class=MsoNormal>TestInt.On<o:p></o:p></p></div><div><p class=MsoNormal>TestInt.Off<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Interrupts.Mod could be enhanced servicing multiple interrupt handlers. Comparable to the background tasks in Oberon.Mod. This enhancement would install its own interrupt handler doing the scheduling, and the user‘s „interrupt handlers“ are normal procedures without * marking of the procedure. You would then install your handler like this<o:p></o:p></p></div><div><p class=MsoNormal>PROCEDURE MyTask; BEGIN led := 3 - led; LED(led) END MyTask;<o:p></o:p></p></div><div><p class=MsoNormal>BEGIN led := 1; Interrupts.Install(MyTask, 500) END TestInt.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><div><p class=MsoNormal>br, Jörg<o:p></o:p></p></div><div><div><p class=MsoNormal><o:p> </o:p></p></div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><p class=MsoNormal>Am 30.03.2021 um 23:45 schrieb Charles Perkins <chuck@kuracali.com>:<o:p></o:p></p></div></blockquote></div><blockquote style='margin-top:5.0pt;margin-bottom:5.0pt'><div><div><p class=MsoNormal><o:p></o:p></p></div><div><div><p class=MsoNormal>Hello Everybody,<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>I wanted to explore interrupt handling in Oberon and I discovered that Peter De Wachter's excellent emulator did not implement them, which is not surprising, as the current Project Oberon source doesn't use them as far as I can tell and the only example source code showing how to use interrupts is the TestInt module on Professor Wirth's own 2018 update to RISC5: <a href="https://people.inf.ethz.ch/wirth/ProjectOberon/RISC5.Update.pdf">https://people.inf.ethz.ch/wirth/ProjectOberon/RISC5.Update.pdf</a><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Since I wanted to compile and run that small example I forked Peter's emulator and added support for Interrupts in a branch here: <a href="https://github.com/io-core/oberon-risc-emu">https://github.com/io-core/oberon-risc-emu</a> (only a few small changes were needed.)<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>With those changes I am able to compile the TestInt module and execute it in the emulator using the 2019 disk image in the repo. Emulated LEDs update once per second as expected.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>I don't intend to maintain a fork of Peter's emulator, I just wanted to experiment with interrupts and share the implementation in case anyone else is interested.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Best Regards,<o:p></o:p></p></div><div><p class=MsoNormal>Chuck<o:p></o:p></p></div></div><div><p class=MsoNormal>--<o:p></o:p></p></div><div><p class=MsoNormal>Oberon@lists.inf.ethz.ch mailing list for ETH Oberon and related systems<o:p></o:p></p></div><div><p class=MsoNormal>https://lists.inf.ethz.ch/mailman/listinfo/oberon<o:p></o:p></p></div></div></blockquote></div><div><p class=MsoNormal>--<o:p></o:p></p></div><div><p class=MsoNormal><a href="mailto:Oberon%40lists.inf.ethz.ch">Oberon@lists.inf.ethz.ch</a> mailing list for ETH Oberon and related systems<o:p></o:p></p></div><div><p class=MsoNormal><a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon">https://lists.inf.ethz.ch/mailman/listinfo/oberon</a><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div></blockquote><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>-- Oberon@lists.inf.ethz.ch mailing list for ETH Oberon and related systems https://lists.inf.ethz.ch/mailman/listinfo/oberon <o:p></o:p></p></div></body></html>