From: Dave N. <n6...@ar...> - 2008-08-09 05:56:34
|
Hello, A handful of us in the Silicon Valley Homebrew Robotics club are trying out amforth. We plan to use it in some robotics projects. I have only gotten as far as getting amforth running in a mega168 in my stk500, but so far everything has gone smoothly. I am very impressed so far. My next step is to get some basic motor control and wheel encoder code working. This evening I have been looking at the interrupt system trying to understand it. In reading amforth.asm, I see where the current interrupt number is stored away in 'intcur' and then interrupts are re-enabled. It seems to me that there is a race with multiple simultaneous interrupts -- if a second interrupt comes in before the value of 'intcur' has been consumed it will be over written and the interrupt will have been lost to forth. It seems to me like intcur should be a bit mask so that all pending interrupts could be represented, not a single interrupt number. Is there something that I am missing? Thanks, Dave |
From: Matthias T. <mt...@we...> - 2008-08-13 19:17:55
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Dave N6NZ schrieb: > This evening I have been looking at the interrupt system trying to > understand it. In reading amforth.asm, I see where the current interrupt > number is stored away in 'intcur' and then interrupts are re-enabled. > It seems to me that there is a race with multiple simultaneous > interrupts -- if a second interrupt comes in before the value of > 'intcur' has been consumed it will be over written and the interrupt > will have been lost to forth. It seems to me like intcur should be a > bit mask so that all pending interrupts could be represented, not a > single interrupt number. Is there something that I am missing? You hit all points. The interrupt system has been designed to have access to timer interrupts. Later I extended it to play with other interrupt sources that sometimes work sometimes dont. To be honest: I never had the need to implement interrupts beyond the timers in forth, and now exists an assembler in amforth with an PS/2 keyboard example so I'm open for suggestions and patches but not very motivated to implement a new interrupt system myself ;=) Cheers Matthias -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFIozNu9bEHdGEMFjMRAp1aAJ4sZwhcN8ODxNhknA4oI4Ujh1O71ACdEHeX QCeiNxxDnbnJ8s7jhr3zENM= =FGOu -----END PGP SIGNATURE----- |
From: Dave N. <n6...@ar...> - 2008-08-14 06:04:00
|
Matthias Trute wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Dave N6NZ schrieb: >> This evening I have been looking at the interrupt system trying to >> understand it. In reading amforth.asm, I see where the current interrupt >> number is stored away in 'intcur' and then interrupts are re-enabled. >> It seems to me that there is a race with multiple simultaneous >> interrupts -- if a second interrupt comes in before the value of >> 'intcur' has been consumed it will be over written and the interrupt >> will have been lost to forth. It seems to me like intcur should be a >> bit mask so that all pending interrupts could be represented, not a >> single interrupt number. Is there something that I am missing? > You hit all points. The interrupt system has been designed to have > access to timer interrupts. Later I extended it to play with other > interrupt sources that sometimes work sometimes dont. To be > honest: I never had the need to implement interrupts beyond the > timers in forth, and now exists an assembler in amforth with > an PS/2 keyboard example so I'm open for suggestions and patches > but not very motivated to implement a new interrupt system myself ;=) OK, thanks for the confirmation of my reading. When digging into a new source code I am always wary of making misguided assumptions. I've been thinking about the problem somewhat, but haven't had time to code up any alternatives. I did a quick study of a bit vector approach, where each interrupt maps to a bit in a double cell. While it is quick and simple to set the bit, I haven't yet found a fast, tight way to dispatch interrupts off a bit vector in DO_INTERRUPT. Another thought is to simply have ISR return with a RET instead of a RETI, thus interrupts are still locked out. DO_INTERRUPT would SEI just before rjmp'ing to DO_EXECUTE. The T but function could be replaced by simply testing the status of the I flag in DO_EXECUTE. Interrupts would be locked out for the duration of the interrupted word, which should be short. This method would require that no other word ever execute an SEI -- a word that needs to lock interrupts needs to deal with the case where interrupts are already disabled -- it would have to save the SREG before any CLI, and then restore the SREG to its previous state instead of doing a blind SEI. This method still allows (as the current method does) nested interrupts. Allowing nested interrupts may not be a good thing. And a third idea that I haven't thought about much at all is to essentially turn 'intcur' into a ring buffer instead of a simple variable. This should be nearly as quick at dispatching interrupts as the current scheme and is no fundamental change to the architecture. I believe this method can preclude nested interrupts, which eliminates a source of hard to find (hard to sensitize!) interrupt handler bugs. In any case, I'll need to address interrupts in some way. For my robotics applications, in addition to timers and serial comms, I want to track the wheel encoders with a pin change interrupt. For now, I will probably write a complete low level pin-change interrupt handler that keeps the encoder counts, and provide forth words to interface to the critical section that contains the counts. In many ways it makes sense to push the robot platform infrastructure down into the forth VM anyway. There are 4 of us now in the Homebrew Robotics Club trying out amforth. It's a very nice fit for our projects. -dave |
From: Matthias T. <mt...@we...> - 2008-08-14 08:39:42
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Dave, > I've been thinking about the problem somewhat, but haven't had time to > code up any alternatives. I did a quick study of a bit vector approach, > where each interrupt maps to a bit in a double cell. While it is quick > and simple to set the bit, I haven't yet found a fast, tight way to > dispatch interrupts off a bit vector in DO_INTERRUPT. That approach work for Atmegas with less than 32 interrupt sources. There are variants with more. Thats why I think that the bitmap is the least better (uhm, well, difficult) way to improve the ISRs. ISRs by nature interrupt at any time. Since the forth inner interpreter is not re-entrant, the handling of the interrupts needs to be synchronized with the DO_NEXT call. In that moment the state of the forth system is well known and needs only a few pointers to be saved/restored. The main task will be therefore to build a way from the asynchronous interrupt to a synchronous forth interrupt. Making the inner interpreter re-entrant is surely possible, but it would need a lot more information to keep (just like a RTOS task or the push/pop giants generated by the gcc). In amforth I tried to avoid such huge (and stupid) things... > Another thought is to simply have ISR return with a RET instead of a > RETI, thus interrupts are still locked out. DO_INTERRUPT would SEI just > before rjmp'ing to DO_EXECUTE. DO_INTERRUPT is already part of the synchronous forth interrupt handling. > And a third idea that I haven't thought about much at all is to > essentially turn 'intcur' into a ring buffer instead of a simple > variable. This should be nearly as quick at dispatching interrupts as > the current scheme and is no fundamental change to the architecture. I > believe this method can preclude nested interrupts, which eliminates a > source of hard to find (hard to sensitize!) interrupt handler bugs. That would indeed solve the problem of lost interrupts. There is only one remaining point (beside coding of course): how long is the buffer? Could be something different (a (return- ?) stack perhaps). It would not solve the problem with the hardware interrupt flags that need to be acknowledged within the "real" interrupt handler (eg the usart flags) however. But it will be definitly better than now. > In any case, I'll need to address interrupts in some way. For my > robotics applications, in addition to timers and serial comms, I want to > track the wheel encoders with a pin change interrupt. These interrupts work similiar to the timer interrupts. They do not need to be acknowledged. I tried them with some push buttons (see the appl/pollin/blocks/hello-world.frt file). Therefore I think, that the major redesign you've outlined at the beginning can still be avoided ;=) > There are 4 of us now in the Homebrew Robotics Club trying out amforth. > It's a very nice fit for our projects. I'm glad (and proud of) to hear. thank you all. Matthias -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFIo+9P9bEHdGEMFjMRAtBzAKDJ7s3vfJtJrb0rqdm1lgfM8GboBACgoFBj fPy25AeihzjZT7tNqDiDJnw= =t3cy -----END PGP SIGNATURE----- |
From: Kalus M. <mic...@on...> - 2008-08-14 20:41:00
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Dave. maybe this thread is helpfull: http://groups.google.com/group/comp.lang.forth/browse_thread/thread/ 8045e6b5d1043043/8e1084d416820324?lnk=gst&q=ISR# (Search comp.lang.forth for "ISR" - find Elizabeth D. Rather, 26 Jan. 2005, 20:47; "multitasker question": provide multitasker to do interrupt service routines.) The essence is: "In the main multitasker loop, if it goes around fully once with no task active, it sets low power mode. This only takes one instruction, so it's done in the code of the multitasker loop itself, not in any task. The assumption is that an event will generate an interrupt which will wake up the device and then awaken the task responsible for the interrupting device." Michael -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (Darwin) iD8DBQFIpJhEJ3DLQCvSXtcRAnv7AJ0TKu0VH2AMVhKVA6XWyQGTMBr9CgCfclLK eTnOUL3qwXvGafxX6amnYBk= =gjCP -----END PGP SIGNATURE----- |