Shop OBEX P1 Docs P2 Docs Learn Events
Duplicating AVR Interrupts With The Propeller — Parallax Forums

Duplicating AVR Interrupts With The Propeller

idbruceidbruce Posts: 6,197
edited 2015-04-07 10:38 in Propeller 1
As everyone knows, I have recently admitted defeat in the battle of the Teacup port :(

It was a bloody battle.... I tore that code to shreds, and in return, the code tore me to shreds. I suppose it is needless to say that I underestimated my advesary, and that was a huge mistake on my part. Before going into battle against such a worthy opponent, it would have been wise of me to study my opponents tactics and preplan counter measures.

As Propeller enthusiasts, we might as well face the fact that we have been outflanked, at least for the moment. It is still my opinion, that the Propeller would perform much better than the AVR in a CNC environment, but the AVR has many years of coding support, for this particular application, and that coding support is based around the use of interrupts.

As it pertains to the Propeller, there is a plethora of existing C code that is most likely unusable, because of the use of interrupts within the existing code, and a lot of this code is open source, which means it is up for grabs. To extend all of our capabilities and open ourselves up to a much wider array of existing source code, as a team, we must find a valid solution to replacing these interrupts. It would be in all of our best interest to accomplish this task, and in my opinion, the sooner we accomplish this task, the sooner we will have access to many more capabilities.

Someone recently said, and I am paraphrasing, "Or you could roll up your sleeves and write you own". While I agree with this comment 101%, I do believe there are times when it is highly beneficial to just use someone elses work, such as the Teacup firmware, which has years of coding effort behind it, from several people. For one person to write similar firmware, they would be at the keyboard an awful long time.

So instead of rolling up our sleeves and spending years behind the keyboard, let's open ourselves up to a broader horizon, by overcoming the use of interrupts. Of course I am still jumping the gun, because I do not know my advesary very well or the tactics that may be implemented, but I do know that we need counter-tactics to the AVR cli() and sei() functions, interrupts, and the use of timers.

I am hoping that this will become a serious thread of discussion that works toward a solution of this problem.

Comments

  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-05 06:22
    Obviously it would have to be implemented by taking advantage of multiple cores on the Propeller. Not knowing how the Prop compilers handle C code very well, I can not say much more on the topic.

    It is an interesting task you present.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 06:32
    David
    Obviously it would have to be implemented by taking advantage of multiple cores on the Propeller. Not knowing how the Prop compilers handle C code very well, I can not say much more on the topic.

    Well I think there will be a lot more involved than cog usage. I think it will be a combination of multiple cogs, flags, while loops, and functions. For example, let's say you have the main cog that runs it code until it comes to a place where a cli() or sei() would be, at which point, that cog would execute a while loop ending on flag value X. Just a thought.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-04-05 06:55
    My personal opinion: don't. The Propeller wasn't made to use interrupts, don't try and force it. Yes, it's possible. You could devise some scheme that would act vaguely like interrupts... but don't.I think it will take you less time to re-develop the architecture to not use interrupts than it would to create, implement, and perfect some weird interrupt-driven scheme on a Prop.
  • kwinnkwinn Posts: 8,697
    edited 2015-04-05 06:59
    Simulating interrupts is the easy part. Dedicate a cog running a pasm program to monitor the interrupt pins and use a tight loop or waitpne to to detect the interrupt. External latches may be needed if the interrupt signal is very short, but other than that it's pretty simple.

    Using that interrupt in the C program is more of a problem. How do you get it to stop executing the current code, save the state, and start executing the isr code? Simple enough to do with byte code where it could be done as part of the byte code interpreter, but how would that be done for C on the propeller? Seems like the folks at Parallax who are working on C would have to have a hand in it.

    PS - I'm with SwimDude.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 07:13
    kwinn and Dave

    Okay, so you are both against the idea. I say consider ALL the available source code, not just one project or set of source code files. ALL of the source code which utilizes interrupts would probably be more than millions upon millions of hours of coding. Consider GitHub and ALL the AVR source code. By achieving a solution, ALL that code would be at our disposal.

    One battle for millions of hours of coding..... Seems like it would be a worthy effort.
    Seems like the folks at Parallax who are working on C would have to have a hand in it.

    I say it would be time well spent.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-05 07:14
    idbruce wrote: »
    David



    Well I think there will be a lot more involved than cog usage. I think it will be a combination of multiple cogs, flags, while loops, and functions. For example, let's say you have the main cog that runs it code until it comes to a place where a cli() or sei() would be, at which point, that cog would execute a while loop ending on flag value X. Just a thought.
    Is the interrupt code really strewn throughout the program or is it concentrated in individual "drivers"? It seems like it would be better to just rewrite those drivers to use a more Propeller-like approach and dispense with the interrupts entirely rather than trying to simulate them.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 07:28
    David
    Is the interrupt code really strewn throughout the program or is it concentrated in individual "drivers"? It seems like it would be better to just rewrite those drivers to use a more Propeller-like approach and dispense with the interrupts entirely rather than trying to simulate them.

    You and I were typing and posting at approximately the same time, please refer to Post #6.

    Teacup is just an example in this case. AVR is a quick solution for me, one purchase and I am done.

    The point and goal of this thread is to promote a solution to all the available AVR source code, not just Teacup. One solution for numerous projects and firmware, instead of a solution for each piece of firmware.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 07:46
    Over the years, I have grown very fond of the Propeller chip and Chip's creation. Beyond any doubt, it is very unique. There are many benefits to this uniqueness, but there is also the hindrance of available source code, based upon this uniqueness. By developing interrupt routines, we could greatly expand the boundaries of the Propeller and make it much more appealing to the marketplace.

    By developing interrupt routines or a common workaround procedure, we gain access to a whole lot of currently unusable code, but still retain the extreme benefit of having an eight core processor. Now that sounds soooo much more appealing than a single core processor that runs on interrupts.

    As stated below, "Necessity is the mother of invention."

    - WE WANT MORE SOURCE CODE - WE WANT MORE SOURCE CODE - WE WANT MORE SOURCE CODE -

    Chant with me :)
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-05 07:50
    idbruce wrote: »
    Over the years, I have grown very fond of the Propeller chip and Chip's creation. Beyond any doubt, it is very unique. There are many benefits to this uniqueness, but there is also the hindrance of available source code, based upon this uniqueness. By developing interrupt routines, we could greatly expand the boundaries of the Propeller and make it much more appealing to the marketplace.

    By developing interrupt routines or a common workaround procedure, we gain access to a whole lot of currently unusable code, but still retain the extreme benefit of having an eight core processor. Now that sounds soooo much more appealing than a single core processor that runs on interrupts.
    Maybe it would help if you could point out an example of the type of interrupt code you're trying to port to the Propeller. Really, it seems to me that interrupts are generally used inside of device driver code and that is exactly the code that usually needs to be rewritten when moving to a new and substantially different architecture. There may not be any shortcut to this.
  • Heater.Heater. Posts: 21,230
    edited 2015-04-05 07:55
    Even if you cooked up some cunning scheme to simulate interrupt like behaviour on the Propeller I'm guessing it would not help in getting those millions of hours worth of Arduino code over to the Prop.

    It would not work exactly the same.

    It would probably be horrible slow,

    There would still be a lot of work to do to adapt the Arduino code. Nobody would bother.

    You would just be importing a huge tangled mess of unintelligible code to the Propeller world.

    It's impossible :)
    (No really)
  • kwinnkwinn Posts: 8,697
    edited 2015-04-05 08:01
    idbruce wrote: »
    kwinn and Dave

    Okay, so you are both against the idea. I say consider ALL the available source code, not just one project or set of source code files. ALL of the source code which utilizes interrupts would probably be more than millions upon millions of hours of coding. Consider GitHub and ALL the AVR source code. By achieving a solution, ALL that code would be at our disposal.

    One battle for millions of hours of coding..... Seems like it would be a worthy effort.



    I say it would be time well spent.

    I am a long way from being a C guru, and only have a bit of general knowledge about compilers so I am not sure if the effort would be worth it or not. My guess is that implementing simulated interrupts is possible with some effort. How much of those millions of hours of code become useful as a result is another matter. Seems like we loose all the advantages a multi core mcu to make use of software that makes very little use of it's potential. Better IMHO to learn from and use the existing code as a guide to create code more suited to the propeller.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-05 08:08
    Heater. wrote: »
    Even if you cooked up some cunning scheme to simulate interrupt like behaviour on the Propeller I'm guessing it would not help in getting those millions of hours worth of Arduino code over to the Prop.

    It would not work exactly the same.

    It would probably be horrible slow,

    There would still be a lot of work to do to adapt the Arduino code. Nobody would bother.

    You would just be importing a huge tangled mess of unintelligible code to the Propeller world.

    It's impossible :)
    (No really)
    The other point about trying to imitate interrupts on the Propeller is that you would not be using the Propeller to its best advantage. Why not just continue using the AVR or PIC or ARM if you're happy with interrupt code. It will run much faster than interrupts simulated on the Propeller. I think you need to buy into the Propeller philosophy if you want to get the most out of what the Propeller has to offer.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 09:07
    David
    Maybe it would help if you could point out an example of the type of interrupt code you're trying to port to the Propeller. Really, it seems to me that interrupts are generally used inside of device driver code and that is exactly the code that usually needs to be rewritten when moving to a new and substantially different architecture. There may not be any shortcut to this.

    I am not exactly sure where all this source code lies, but I do know that there is a lot of AVR code out there that rely upon the ISR timers. In my current case and in the case of most 3D printers, most variants are of RepRap, which is AVR based. You can find a lot of CNC code based upon the AVR, which utilizes the ISR timers. Other options are Linux, which I have not investigated.

    Using Teacup as an example, there are two comparators, which are initialised as follows:
    /// comparator B is the system clock, happens every TICK_TIME
    ISR(TIMER1_COMPB_vect) {
    	// set output compare register to the next clock tick
    	OCR1B = (OCR1B + TICK_TIME) & 0xFFFF;
    
      clock_tick();
      dda_clock();
    }
    
    #ifdef	MOTHERBOARD
    
    /// comparator A is the step timer. It has higher priority then B.
    ISR(TIMER1_COMPA_vect) {
    	// Check if this is a real step, or just a next_step_time "overflow"
    	if (next_step_time < 65536) {
    		// step!
    		#ifdef DEBUG_LED_PIN
    			WRITE(DEBUG_LED_PIN, 1);
    		#endif
    
    		// disable this interrupt. if we set a new timeout, it will be re-enabled when appropriate
    		TIMSK1 &= ~MASK(OCIE1A);
    		
    		// stepper tick
    		queue_step();
    
    		// led off
    		#ifdef DEBUG_LED_PIN
    			WRITE(DEBUG_LED_PIN, 0);
    		#endif
    
    		return;
    	}
    
    	next_step_time -= 65536;
    
    	// similar algorithm as described in setTimer below.
    	if (next_step_time < 65536) {
    		OCR1A = (OCR1A + next_step_time) & 0xFFFF;
    	} else if(next_step_time < 75536){
    		OCR1A = (OCR1A - 10000) & 0xFFFF;
    		next_step_time += 10000;
    	}
    	// leave OCR1A as it was
    }
    
    Source: Teacup Firmware


    ComparatorB has the tasks of running clock_tick() and dda_clock(), basically this pops off every 2ms and has the tasks of updating various program time flags and updating the current position of all axes during a movement, as well as maintaining the current status of other variables. During this time frame, the ISR has control over these variables, which are in various locations throughout the firmware. This routine really isn't a HUGE issue, but still an important issue nonetheless.

    ComparatorA has the task of telling an individual axis when to step, with the queue_step() function. Handling queue_step() is actually quite complicated, because it can be run both inside and outside of the interrupt service routines, or at least that is the way I understand it. Meanwhile, the queue is modified both inside and outside of the interrupt service routines, which further complicates the issues by many fold. Very complicated stuff, just to describe it.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-05 09:18
    David
    The other point about trying to imitate interrupts on the Propeller is that you would not be using the Propeller to its best advantage. Why not just continue using the AVR or PIC or ARM if you're happy with interrupt code. It will run much faster than interrupts simulated on the Propeller.

    My point is why not have the best of both worlds.

    For example, let's say that you have a complicated task to perform, for which there is AVR source code readily available, but you also have other tasks that would be highly suited to work with individual cogs. Why not have the option of dedicating say perhaps three cogs to ISRs, and have the remaining five cogs available to do what ever you want.

    For all those partaking in this discussion, I am not suggesting that the ISR limit our options, I am suggesting that they provide us with more options. Perhaps a single header and source code file may be all that is needed to add such type of support.
  • prof_brainoprof_braino Posts: 4,313
    edited 2015-04-05 09:28
    Using interupts is the "hard way" but its the only way on a single core process. The prop eliminates interuptes, we just assign a dedicated core to the task and we're done very straight forward.

    Making the prop use code written for interupts will be doing the hard way the hard way.

    Consider writing a C compiler using your own version of BASIC writtien in SPIN. This might be considered the long way around the block.

    You really should simply figure out your functional requirements up front, and write an application that does that. Code Re-use is very misunderstood, and gets folks in all kinds of trouble. Code re-use means "use it for reference" but as some point you actually have to do the effort of figuring out and understanding exactly what you are doing, and make sure you do that. Otherewise you end up pissing in the dark.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-04-05 12:27
    I've translated a few Arduino programs into Spin. I know enough about interrupts to know they all pretty much need to be handled on a case by case basis.

    There are timer interrupts and there are pin state interrupts (I think these are called external interrupts). So much of the way the code gets converted to Spin or PASM depends on what the code is doing.

    Some timer interrupts can be simulated with a waitcnt. Other timer interrupts are better simulated with "if nowTime - earlierTime > timeInterval" type of code.

    Similarly the various external interrupts can be handled in a variety of ways. If the state of the pin change is fast, you may want to use a waitpxx statement (which will block the cog) alternately you many want to poll the pin. I know the standard way to read quadrature encoders with an AVR is to use pin interrupts while with a Propeller quadrature encoders are generally read by polling the input pins. However there are also quadrature encoder objects which use waitpxx statements. The best substitution depends on the specifics of the project.

    As others have suggested, usually the Propeller offers an alternate way of accomplishing the same thing in a more elegant way than using interrupts.
  • jmgjmg Posts: 15,173
    edited 2015-04-05 13:18
    idbruce wrote: »
    In my current case and in the case of most 3D printers, most variants are of RepRap, which is AVR based. You can find a lot of CNC code based upon the AVR, which utilizes the ISR timers. ....
    Using Teacup as an example, there are two comparators, which are initialised as follows:

    A universal swallow-any-code solution is a mirage. - it is not only interrupts you seek to clone, it is the underlying peripherals as well.

    However, porting code using PropGCC could have some 'assists', but all this is not really novice territory.

    First step should be to extract from the AVR tools, all the interrupts, their Code sizes and the variables they use, and some indication of fire rates.

    Main flow C code, does not know where/when the interrupts are, but it does interact via flags (see your example where the INT stops itself, expecting something else to restart).

    There is scope to have AVR ISR() compiler directives guide a PropGCC user to a COG targeted compile, where you try to [pack/map one interrupt => one COG]

    This is non trivial, as your example shows INTs calling other functions - if you are lucky they may be simple expanded in-line.

    Obvious ceilings are when you run out of COGS, or run out of code space in any one COG.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-05 13:37
    Bruce, look at the last version of code that I posted on the Teacup thread. This is doing exactly what you are asking for.
  • GenetixGenetix Posts: 1,754
    edited 2015-04-07 10:13
    Bruce,

    C is supposed to be portable but that's possible when people add chip-specific code or use chip-specific libraries.
    Another problem is that C was not designed for microcontrollers which tend to be very limited especially in memory.
    C libraries tend to be large especially for things like Floating Point.

    What library functions does Teacup need?
    Do any of these already exist as Spin, PASM, or C?

    As you said if this were on a PC then this would never be an issue.
    Also you keep saying that you need more memory.
    The Propeller can use an external EEPROM and there is already code for that including C.
    The Hydra uses a 128K EEPROM since games require a lot of space for graphics.

    As others have said if you want to cripple the Propeller then implement interrupts on it otherwise tell us what you need done and if it doesn't exist we can make something.
  • Heater.Heater. Posts: 21,230
    edited 2015-04-07 10:38
    Genetix,
    Another problem is that C was not designed for microcontrollers which tend to be very limited especially in memory.
    It's true C was designed for micro-controllers, there were no such things at the time.

    However, because C was designed on machines with very limited memory spaces, comparable to todays micro-controllers, and because it is basically a simple abstraction over what many computers actually do in hardware, it actually works very well for micro-controllers.

    The success of the Arduino is a testament to that fact. C is used effectively with even smaller devices than that.

    C on the Propeller is problematic. prop-gcc can compile to native code but then you are stuck with having to fit your code into 500 odd instructions. After that you need LMM to put the generated code into HUB space. Basically an interpreter. This is not nice because LLM slows execution down by a factor of 4 or more and the code space get's quickly eaten as all the instructions are 32 bits wide.

    Basically the Propeller does not conform to the abstraction C is making. I believe this is true for all other compiled languages like Pascal, Ada, etc etc.
Sign In or Register to comment.