EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Has someone tried to add interrupt support to Riscy Pygness?

Started by wzab May 21, 2011
I just started to play with Riscy Pygness ( http://pygmy.utoh.org/riscy/cortex/
) on target part of LPCXpresso 1769 board. The system works quite good
as interactive environment for experimenting with ARM CORTEX
processor, and seems to be an efficient development platform.

The only thing which seems to be lacking is interrupt support.
Well, I can write the interrupt service routine in assembly and add it
to the kernel, and it will be the most efficient solution. However for
interactive experiments it would be much nicer to have possibility to
implement ISR as a Forth word. Such functionality is available in the
latest version of amforth for ATmega's (http://amforth.sf.net).

Has anybody added this functionality to Riscy Pygness? Maybe someone
could suggest the best way to implement such functionality? Is it
possible to make use of multitasking functionalities provided
by the kernel to service interrupts in a reasonable way?
What are the traps, which may badly affect the interrupt servicing
latency?
--
TIA & Best Regards,
Wojtek


On 5/21/11 7:03 AM, wzab wrote:
> I just started to play with Riscy Pygness ( http://pygmy.utoh.org/riscy/cortex/ > ) on target part of LPCXpresso 1769 board. The system works quite good > as interactive environment for experimenting with ARM CORTEX > processor, and seems to be an efficient development platform. > > The only thing which seems to be lacking is interrupt support. > Well, I can write the interrupt service routine in assembly and add it > to the kernel, and it will be the most efficient solution. However for > interactive experiments it would be much nicer to have possibility to > implement ISR as a Forth word. Such functionality is available in the > latest version of amforth for ATmega's (http://amforth.sf.net). > > Has anybody added this functionality to Riscy Pygness? Maybe someone > could suggest the best way to implement such functionality? Is it > possible to make use of multitasking functionalities provided > by the kernel to service interrupts in a reasonable way? > What are the traps, which may badly affect the interrupt servicing > latency?
I am not familiar with Riscy Pygness, but I can comment generally about interrupt handling. The problem with writing your interrupt handler in high-level Forth is that the interrupt must first instantiate a Forth environment: stacks, registers, whatever the implementation requires, and do so in such a way as to not affect whatever task was running when the interrupt occurred. This adds some inevitable overhead. IMO the faster approach is to write the interrupt handler itself in assembler, and make it do a bare minimum: only those things that absolutely have to be done *right now*, and let a high-level word do the less time-critical functions. For example, if you are doing some data acquisition, your application task can set up the operation and then go into a wait state. When the interrupt occurs, the ISR can read the value, store it somewhere, and set the task to wake up again to do whatever additional processing is necessary. Of course, I am viewing this from a multitasking perspective. Cheers, Elizabeth -- ================================================== Elizabeth D. Rather (US & Canada) 800-55-FORTH FORTH Inc. +1 310.999.6784 5959 West Century Blvd. Suite 700 Los Angeles, CA 90045 http://www.forth.com "Forth-based products and Services for real-time applications since 1973." ==================================================
On May 21, 2:55=A0pm, Elizabeth D Rather <erat...@forth.com> wrote:
> On 5/21/11 7:03 AM, wzab wrote: > > > > > I just started to play with Riscy Pygness (http://pygmy.utoh.org/riscy/=
cortex/
> > ) on target part of LPCXpresso 1769 board. The system works quite good > > as interactive environment for experimenting with ARM CORTEX > > processor, and seems to be an efficient development platform. > > > The only thing which seems to be lacking is interrupt support. > > Well, I can write the interrupt service routine in assembly and add it > > to the kernel, and it will be the most efficient solution. However for > > interactive experiments it would be much nicer to have possibility to > > implement ISR as a Forth word. Such functionality is available in the > > latest version of amforth for ATmega's (http://amforth.sf.net). > > > Has anybody added this functionality to Riscy Pygness? Maybe someone > > could suggest the best way to implement such functionality? Is it > > possible to make use of multitasking functionalities provided > > by the kernel to service interrupts in a reasonable way? > > What are the traps, which may badly affect the interrupt servicing > > latency? > > I am not familiar with Riscy Pygness, but I can comment generally about > interrupt handling. > > The problem with writing your interrupt handler in high-level Forth is > that the interrupt must first instantiate a Forth environment: stacks, > registers, whatever the implementation requires, and do so in such a way > as to not affect whatever task was running when the interrupt occurred. > =A0 This adds some inevitable overhead. > > IMO the faster approach is to write the interrupt handler itself in > assembler, and make it do a bare minimum: only those things that > absolutely have to be done *right now*, and let a high-level word do the > less time-critical functions. > > For example, if you are doing some data acquisition, your application > task can set up the operation and then go into a wait state. =A0When the > interrupt occurs, the ISR can read the value, store it somewhere, and > set the task to wake up again to do whatever additional processing is > necessary. > > Of course, I am viewing this from a multitasking perspective.
I can't say I follow your idea of what an interrupt handler in forth has to do. The stacks are already there. If an interrupt works on top of that there shouldn't be any issues other than possibly overflowing the stacks. If the interrupt routine needs storage between invocations that would be variable memory, no? That is one of the things I've never understood. Forth is a language based on a virtual machine. That virtual machine is perfectly capable of handling interrupts from what I can see. The only limitation would be if interrupts are allowed during the execution of an assembly language defined word, then that word needs to protect any section of code that should not be interrupted at the Forth level. Otherwise I don't see the issues. Rick
On 5/21/11 1:33 PM, rickman wrote:
> On May 21, 2:55 pm, Elizabeth D Rather<erat...@forth.com> wrote:
...
>> The problem with writing your interrupt handler in high-level Forth is >> that the interrupt must first instantiate a Forth environment: stacks, >> registers, whatever the implementation requires, and do so in such a way >> as to not affect whatever task was running when the interrupt occurred. >> This adds some inevitable overhead. >> >> IMO the faster approach is to write the interrupt handler itself in >> assembler, and make it do a bare minimum: only those things that >> absolutely have to be done *right now*, and let a high-level word do the >> less time-critical functions. >> >> For example, if you are doing some data acquisition, your application >> task can set up the operation and then go into a wait state. When the >> interrupt occurs, the ISR can read the value, store it somewhere, and >> set the task to wake up again to do whatever additional processing is >> necessary. >> >> Of course, I am viewing this from a multitasking perspective. > > I can't say I follow your idea of what an interrupt handler in forth > has to do. The stacks are already there. If an interrupt works on > top of that there shouldn't be any issues other than possibly > overflowing the stacks. If the interrupt routine needs storage > between invocations that would be variable memory, no? > > That is one of the things I've never understood. Forth is a language > based on a virtual machine. That virtual machine is perfectly capable > of handling interrupts from what I can see. The only limitation would > be if interrupts are allowed during the execution of an assembly > language defined word, then that word needs to protect any section of > code that should not be interrupted at the Forth level. Otherwise I > don't see the issues.
As I said, I'm viewing this from a multitasking perspective: when an interrupt occurs there's no telling which task is running and has its stacks instantiated. If you know there is only one task, and it is idle waiting for the interrupt, you can use its stacks, but what then is the purpose of using interrupts? Why not just poll? To a limited extent you can get away with pushing something temporarily on whatever is the current data stack, provided you get it off again before exiting the ISR. But that's a far cry from executing high level Forth. And, of course you want interrupts to occur during executing of assembly language words in an ITC Forth. A lot of your kernel may be written that way. If all your primitives, so identified because those are the ones you want to run fast, have to disable and re-enable interrupts that's just more overhead. To me, the point of having an interrupt is to be able to respond to an event in the shortest amount of time and with minimum impact on the rest of the running application. On our systems, you can get into an ISR in one or two instruction times, and out in one. Why add further overhead? Cheers, Elizabeth -- ================================================== Elizabeth D. Rather (US & Canada) 800-55-FORTH FORTH Inc. +1 310.999.6784 5959 West Century Blvd. Suite 700 Los Angeles, CA 90045 http://www.forth.com "Forth-based products and Services for real-time applications since 1973." ==================================================
On 05/22/2011 02:18 AM, Elizabeth D Rather wrote:
> On 5/21/11 1:33 PM, rickman wrote: >> On May 21, 2:55 pm, Elizabeth D Rather<erat...@forth.com> wrote: > .... >>> The problem with writing your interrupt handler in high-level Forth is >>> that the interrupt must first instantiate a Forth environment: stacks, >>> registers, whatever the implementation requires, and do so in such a way >>> as to not affect whatever task was running when the interrupt occurred. >>> This adds some inevitable overhead. >>> >>> IMO the faster approach is to write the interrupt handler itself in >>> assembler, and make it do a bare minimum: only those things that >>> absolutely have to be done *right now*, and let a high-level word do the >>> less time-critical functions. >>> >>> For example, if you are doing some data acquisition, your application >>> task can set up the operation and then go into a wait state. When the >>> interrupt occurs, the ISR can read the value, store it somewhere, and >>> set the task to wake up again to do whatever additional processing is >>> necessary. >>> >>> Of course, I am viewing this from a multitasking perspective. >> >> I can't say I follow your idea of what an interrupt handler in forth >> has to do. The stacks are already there. If an interrupt works on >> top of that there shouldn't be any issues other than possibly >> overflowing the stacks. If the interrupt routine needs storage >> between invocations that would be variable memory, no? >> >> That is one of the things I've never understood. Forth is a language >> based on a virtual machine. That virtual machine is perfectly capable >> of handling interrupts from what I can see. The only limitation would >> be if interrupts are allowed during the execution of an assembly >> language defined word, then that word needs to protect any section of >> code that should not be interrupted at the Forth level. Otherwise I >> don't see the issues. > > As I said, I'm viewing this from a multitasking perspective: when an > interrupt occurs there's no telling which task is running and has its > stacks instantiated. If you know there is only one task, and it is idle > waiting for the interrupt, you can use its stacks, but what then is the > purpose of using interrupts? Why not just poll?
I presume that there is some sort of 'current task' that points to the task currently executing, and that you can find the current stack from there. Alternatively, use a dedicated interrupt stack.
> To a limited extent you can get away with pushing something temporarily > on whatever is the current data stack, provided you get it off again > before exiting the ISR. But that's a far cry from executing high level > Forth.
Why for a limited extent ? And of course you have to pop everything from the stack that you put on.
On 5/21/11 8:33 PM, Arlet Ottens wrote:
> On 05/22/2011 02:18 AM, Elizabeth D Rather wrote: >> On 5/21/11 1:33 PM, rickman wrote: >>> On May 21, 2:55 pm, Elizabeth D Rather<erat...@forth.com> wrote: >> .... >>>> The problem with writing your interrupt handler in high-level Forth is >>>> that the interrupt must first instantiate a Forth environment: stacks, >>>> registers, whatever the implementation requires, and do so in such a >>>> way >>>> as to not affect whatever task was running when the interrupt occurred. >>>> This adds some inevitable overhead. >>>> >>>> IMO the faster approach is to write the interrupt handler itself in >>>> assembler, and make it do a bare minimum: only those things that >>>> absolutely have to be done *right now*, and let a high-level word do >>>> the >>>> less time-critical functions. >>>> >>>> For example, if you are doing some data acquisition, your application >>>> task can set up the operation and then go into a wait state. When the >>>> interrupt occurs, the ISR can read the value, store it somewhere, and >>>> set the task to wake up again to do whatever additional processing is >>>> necessary. >>>> >>>> Of course, I am viewing this from a multitasking perspective. >>> >>> I can't say I follow your idea of what an interrupt handler in forth >>> has to do. The stacks are already there. If an interrupt works on >>> top of that there shouldn't be any issues other than possibly >>> overflowing the stacks. If the interrupt routine needs storage >>> between invocations that would be variable memory, no? >>> >>> That is one of the things I've never understood. Forth is a language >>> based on a virtual machine. That virtual machine is perfectly capable >>> of handling interrupts from what I can see. The only limitation would >>> be if interrupts are allowed during the execution of an assembly >>> language defined word, then that word needs to protect any section of >>> code that should not be interrupted at the Forth level. Otherwise I >>> don't see the issues. >> >> As I said, I'm viewing this from a multitasking perspective: when an >> interrupt occurs there's no telling which task is running and has its >> stacks instantiated. If you know there is only one task, and it is idle >> waiting for the interrupt, you can use its stacks, but what then is the >> purpose of using interrupts? Why not just poll? > > I presume that there is some sort of 'current task' that points to the > task currently executing, and that you can find the current stack from > there. Alternatively, use a dedicated interrupt stack. > >> To a limited extent you can get away with pushing something temporarily >> on whatever is the current data stack, provided you get it off again >> before exiting the ISR. But that's a far cry from executing high level >> Forth. > > Why for a limited extent ? And of course you have to pop everything from > the stack that you put on.
My point is that all of what you describe adds unnecessary overhead. If you follow the model I described above, you only need a few instructions in your ISR (typically 3-5 for a simple "read a value and put it somewhere"), and it would cost more than that just to get into a high-level Forth routine. Much easier to just do the bare minimum at interrupt time and let the task responsible for the interrupting device do the high level processing. Cheers, Elizabeth -- ================================================== Elizabeth D. Rather (US & Canada) 800-55-FORTH FORTH Inc. +1 310.999.6784 5959 West Century Blvd. Suite 700 Los Angeles, CA 90045 http://www.forth.com "Forth-based products and Services for real-time applications since 1973." ==================================================
On 05/22/2011 10:15 AM, Elizabeth D Rather wrote:

>> >>> To a limited extent you can get away with pushing something temporarily >>> on whatever is the current data stack, provided you get it off again >>> before exiting the ISR. But that's a far cry from executing high level >>> Forth. >> >> Why for a limited extent ? And of course you have to pop everything from >> the stack that you put on. > > My point is that all of what you describe adds unnecessary overhead. If > you follow the model I described above, you only need a few instructions > in your ISR (typically 3-5 for a simple "read a value and put it > somewhere"), and it would cost more than that just to get into a > high-level Forth routine. Much easier to just do the bare minimum at > interrupt time and let the task responsible for the interrupting device > do the high level processing.
If you defer the work to a task, you have the extra overhead of context switches, which are generally more expensive than saving state in the ISR. If you can do all the work in the ISR, or at least do all the work in the majority of cases, this actually costs less overall.
In article <Hr-dneayMvMBl0XQnZ2dnUVZ_vmdnZ2d@supernews.com>,
Elizabeth D Rather  <erather@forth.com> wrote:
>On 5/21/11 7:03 AM, wzab wrote: >> I just started to play with Riscy Pygness ( http://pygmy.utoh.org/riscy/cortex/ >> ) on target part of LPCXpresso 1769 board. The system works quite good >> as interactive environment for experimenting with ARM CORTEX >> processor, and seems to be an efficient development platform. >> >> The only thing which seems to be lacking is interrupt support. >> Well, I can write the interrupt service routine in assembly and add it >> to the kernel, and it will be the most efficient solution. However for >> interactive experiments it would be much nicer to have possibility to >> implement ISR as a Forth word. Such functionality is available in the >> latest version of amforth for ATmega's (http://amforth.sf.net). >> >> Has anybody added this functionality to Riscy Pygness? Maybe someone >> could suggest the best way to implement such functionality? Is it >> possible to make use of multitasking functionalities provided >> by the kernel to service interrupts in a reasonable way? >> What are the traps, which may badly affect the interrupt servicing >> latency? > >I am not familiar with Riscy Pygness, but I can comment generally about >interrupt handling. > >The problem with writing your interrupt handler in high-level Forth is >that the interrupt must first instantiate a Forth environment: stacks, >registers, whatever the implementation requires, and do so in such a way >as to not affect whatever task was running when the interrupt occurred. > This adds some inevitable overhead.
Isn't this overly pessimistic? Compared to interrupting an arbitrary program (and provided there is one program space) you need to save two less registers, containing the return stack pointer and the data stack pointer. Instead, use them, which saves initialisation. They must balance out on return. This assumes that the Forth uses its stacks properly, i.e. no data is stored outside of the area "protected" by the data stack pointer. 1) For the rest the usual caveat's for interrupts apply: save all registers that you use. By the way, in some processors (z80) you had no choice, interrupts just use the z80-stack, which Forth uses undoubtedly either as data or return stack. So what you need to do in the end is store the code start address of a Forth word that is executed upon interrupt in the interrupt table. This is probably a code word that save registers. You also need a code word that restores and does a return from interrupt. The interrupt handler better end with a call to that word.
> >IMO the faster approach is to write the interrupt handler itself in >assembler, and make it do a bare minimum: only those things that >absolutely have to be done *right now*, and let a high-level word do the >less time-critical functions.
If the above facilities are not in the Forth already, you can't get around writing assembler. Then you might as well take this approach. <SNIP>
> >Cheers, >Elizabeth
1) You have to take that into account anyway, whenever interrupts are used. -- -- Albert van der Horst, UTRECHT,THE NETHERLANDS Economic growth -- being exponential -- ultimately falters. albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
On Sat, 21 May 2011 10:03:04 -0700 (PDT), wzab <wzab01@gmail.com>
wrote:

>I just started to play with Riscy Pygness ( http://pygmy.utoh.org/riscy/cortex/ >) on target part of LPCXpresso 1769 board. The system works quite good >as interactive environment for experimenting with ARM CORTEX >processor, and seems to be an efficient development platform.
Adding native Forth ISRs (Interrupt Service Routine) to a threaded code Forth is an exercise in futility. If you want to write an ISR in Forth you need speed. If you need speed, you need an optimising native code compiler. These are provided by Forth vendors such as MPE and Forth Inc. Speaking for MPE, I haven't written an ARM or Cortex ISR in anything but high-level Forth for over ten years. The VFX code generator does a very good job. The downside of such tools is that they are neither Open Source nor free (beer). However, the MPE ARM/Cortex Stamp edition compiler for ARM and Cortex is not expensive GBP 75, EU 87, USD 124 and supports LPC17xx directly. There's a limit of 120kb Flash and 64kb RAM. Stephen -- Stephen Pelc, stephenXXX@mpeforth.com MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads
On Sat, 21 May 2011 22:15:28 -1000, Elizabeth D Rather
<erather@forth.com> wrote:

>My point is that all of what you describe adds unnecessary overhead. If >you follow the model I described above, you only need a few instructions >in your ISR (typically 3-5 for a simple "read a value and put it >somewhere"), and it would cost more than that just to get into a >high-level Forth routine. Much easier to just do the bare minimum at >interrupt time and let the task responsible for the interrupting device >do the high level processing.
Although I agree with much of what you say in theory, I'm going to disagree with you here in relationship to modern CPUs such as ARM and Cortex. When you have a really good Forth compiler, the performance enabled by it permits us to write more complex interrupt handlers in high level Forth. The example I always use was a four channel 9600 baud bit-banged serial driver fitted to a vending machine. It ran from a 38400 Hz timer interrupt and had a worst case interrupt duration (measured) of 1.5us on a 60MHz LPC2148. On a Cortex LPC17xx, it would be faster still. A really good Forth compiler is enabling technology. Stephen -- Stephen Pelc, stephenXXX@mpeforth.com MicroProcessor Engineering Ltd - More Real, Less Time 133 Hill Lane, Southampton SO15 5AF, England tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 web: http://www.mpeforth.com - free VFX Forth downloads

The 2024 Embedded Online Conference