Questions you think are too stupid to ask...
DavidZemon
Posts: 2,973
A thread with this title exists in another forum I'm on. It's wonderfully helpful.
I'll start.
In the propeller manual, the DIRA section contains the line: "[ensure] no two cogs cause logical contention on the same I/O pin"
What does this mean? Ensure that one cog outputs a 0 while another cog outputs a 1? If I were to accidentally do this, would the chip release it's magic blue smoke?
I'll start.
In the propeller manual, the DIRA section contains the line: "[ensure] no two cogs cause logical contention on the same I/O pin"
What does this mean? Ensure that one cog outputs a 0 while another cog outputs a 1? If I were to accidentally do this, would the chip release it's magic blue smoke?
Comments
But the scenario in the text that you've cited (in a good question, by the way) is not the blue-smoke case, as only ONE PIN is involved, and, at any one time, the pin, itself (with it's associated circuitry), can only be successfully set for either input or output (whether high or low, in the case of being an output), not set for being both an input and an output at the same time. But two (or more cogs) can still "request" (or attempt) to set a pin differently (from other cogs), but any cog that sets the pin as an output (using DIRA) will "win," and the pin will be an output pin, as JonnyMac said. In a sense, an attempt to set a pin as an input is a "request" (from the pin viewpoint) that is only honored if NO (zero) other cogs try to set it as an output. But an instruction to set a pin as an output will definitely be honored, so, in that sense, is not really a request but a command.
As the manual says just prior to the text you've cited, "no electrical contention between cogs is POSSIBLE" (emphasis added). So, this is not a blue-smoke generating scenario that one needs to worry about because electrical contention is precluded due to the way the pins are wired internally (which is quite nice or the only practical way for cogs to have access to the same pins). Note that the text that you've cited mentions "logical contention," not the electrical or physical kind. Logical contention is still quite possible, and while such wouldn't generate blue smoke, it's possible that such wouldn't consistently give the result desired. And it's up to the programmer to avoid any such logical contention that would be problematic (not all "contention" in terms of requested pin settings is problematic).
For example, suppose one cog "sets" (recall it's kind of a request) all the pins as inputs using DIRA but only uses the first 4 pins (0..3) as inputs (by the way, all pins being configured as inputs (high impedance) is, I believe, the default state, thank goodness). Further suppose that another cog comes along and sets (commands) pins 20 through 27 to be outputs using DIRA. That's NOT going to cause a problem, even though the requested/commanded pin states don't agree. The cog that sets pins 20..27 as outputs will "win" based on the TWO LAWS mentioned in the text just prior to the text you've cited (see the manual). But the fact that the second cog's setting won won't matter here because the first cog that had set or requested them to be inputs doesn't use them. In such a case, one could argue that the first cog shouldn't have bothered to set those pins (or any other pins other than the first four) as inputs (or outputs) because it doesn't use them, but, nonetheless, this disagreement in issued pin setting instructions won't cause electrical, blue-smoke contention; the pins will be outputs based on the two laws, case closed.
But there are other scenarios where such disagreement in pin settings would be problematic, not because it would create a blue smoke condition, but because one cog's use of a pin as an output pin (wherein such usage would prevail over another cog's request for usage as an input) *could* trample on some other signals from elsewhere. Thinking about it, if a cog has requested to use a pin as an input, then it's trying to read a signal from somewhere else. That somewhere else could be, for example, a sensor device. In such case, if another cog were trying to use the same pin as an output, then, obviously, such usage would tramp on the sensor's output. I believe it's the case that a cog can still read the state of a pin at any time regardless of how the pin is actually configured input/ouput-wise (someone correct me if I'm wrong, and I really shouldn't be writing this without knowing and or testing that, but I think it's the case). I assume that's how Hanno's ViewPort can read the state of all of the pins without requiring any other pins (assuming that's the case as I haven't used it yet), regardless of whether the pins are set as inputs or outputs (in various combinations). Similarly, the afforementioned "somewhere else" signal source could also be from another cog generating output. In that case, such "disagreement" in usage would be deliberate and not unwanted contention. One cog would use a pin as an output, setting it either high or low, possibly varying over time, while another cog "peeked" at the status. Such would, effectively, save a pin as an input pin wouldn't have to be connected to a separate output pin (in such an intercog communication scenario) and hub memory would not be involved. Someone please correct me if I'm wrong (I'm still a bit new at this).
But what one needs to keep in mind is that the above case is different from that of two (or more) cogs using a pin as an OUTPUT (that has been set to an output by at least one of the cogs using DIRA). In that case, if one cog outputs a high, while another cog outputs a low, then the cog outputting a high will prevail based on ANOTHER pair of laws (see the OUTA section of the manual). I mention this because I think it's easy to get DIRA and OUTA (or input and output usage) confused by the novice and/or not-so-novice. That situation also doesn't result in electrical, blue-smoke contention, as the internal pin wiring will let the output state of ANY one cog outputting a high win or prevail over any cogs that might be trying to output a low on the same pin (i.e., the low-attempting-outputters will "lose"). See, this current situation is different than the abovementioned discussion concerning contention as to the input or output condition of a pin (by "competing" cogs). Here, all cogs are agreeing that the pin is an output (and even if a cog didn't agree, its voice in the matter (or requested use as an input) would be overridden). But even if the cogs agree on a pin's usage in terms of input/output, such cogs all using the output mode, they might still try to set such a pin at different logical levels (at least one to high, and at least another to low). And by design, the cog or cogs that set it high will win. It's important to differentiate this situation from the above first scenario (the one existing for the OP's cited text of two cogs not agreeing on the input/output state). So, where might the current situation of two cogs ATTEMPTING (but not succeeding) to output different levels on the same pin be useful? Consider the following:
Sometimes it's necessary for code in one cog to "share" a pin with the same or different code in another cog for various reasons. For example, one might have one cog responsible for outputting a video signal with graphics and have another cog responsible for overlaying (super-imposing) text on top of that video. In such a case, the two cogs would likely share video output pins (such usage also being synchronized). The cog charged with overlaying text would likely be configured to "step on" the output of the graphics cog by setting an output pin high (to produce, for example, white lettering/pixels), potentially overriding a low setting from the graphics cog. In this case, both cogs would use the same pin (or pin group) for output. Both cogs could actually issue DIRA instructions to set the pin(s) to output, but, strictly speaking, I think it's sufficient for only one cog to do so. That is, I don't think (but I'm not currently too sure) that a cog is prevented from issuing an output command (OUTA) just because it hasn't set the pin direction as ouput using DIRA, at least I don't think that the compiler would object. But unless another cog has set the pin to output, I guess its output attempts wouldn't work (again, assuming it hadn't issued a DIRA instruction to make the pin an output). I'd test this now but I'm too wrapped up in writing this ever-expanding reply.
Anyway, to the original poster (OP) and any interested readers, in thinking about all of this, try to clearly distinguish between input and output usage, as, I think, it's easy to get them confused. I'm admittedly not so clear on all of this or related matters, either, as witnessed by my two requests for correction above. However, with a clear distinction between input and output usage, I think it makes the lack of electrical contention but the possibility of logical contention easier to understand (such a logical contention possibility applying to both cases). Incidentally, another intriguing thing you may come across (perhaps such as in reading a PS/2 keyboard or similar) is the rapid turing around of the pin direction using DIRA to effect signaling/clocking (I forget the details). That may throw (perplex) one at first, but that's probably a topic for a different post (or slightly/somewhat more "advanced" usage). As for me, after a year or two of occasional usage, I too am still casually attempting to create the blue smoke and expect to any day now (as I've just cursed myself with the foregoing, no doubt), but I think such will have to involve either connecting two output pins directly together, or connecting a single output pin to the outside world with a voltage differential and no current-limiting protection resistor therebetween. I'm sure my "failure" to fry a chip so far is due in large part to not experimenting/attempting enough (though I may have unknowingly compromised a pin's ability). However, I also think the Propeller is also rather robust given half a chance (i.e., not doing anything too too "stupid"). At any rate, best of luck with your efforts! Apologies in advance for any disinformatoin; I'm still learning, too. --Jim
Table 2-7: Counter Modes (CTRMODE Field Values)
Have you seen App Note AN001?
I had not! Thank you! Starting to read it now...
Here's another question:
Why didn't Parallax implement interrupts, watchdog timer, or extra peripherals?
I understand it's nice that we have 8 cores to utilize, and we can still do a lot without interrupts... but we could do SO MUCH more if we had them. It seems silly that I need to use an entire cog to poll a pin and wait on input to do something while a second cog runs foreground tasks. This is something that can easily be done with a single cog if it had interrupts, allowing the other 7 cogs to do other useful tasks.
WDT: self explanitory. Why no WDT?
Extra peripherals: As a relative newbie to the uC world, I'm always looking at specs for other uC that I hear about. It seems like every other chip out there has many many more peripherals on it than the prop (with the exclusion of the timers & video generators). Why no ADCs? No built-in serial communication modules? No built-in ____? Again, this chip would become even more versatile if it had these.
I know the prop2 prelim says it will have ADCs. I'm very grateful for that. But still not adding the rest of it?
Are there any other uC out there that have all of these? I know ARM makes some multi-core processors, but IIRC they are in the $50 range.
Thanks,
David
I can't wait til the Prop2 comes out...
By building your own peripherals, you can add the little bits of smarts you wish they would've had on any other micro.
As for ARMs, I know you can buy asymmetric multi-core MCUs. The OMAP5 series is a dual-core A15 with two M4s as well.
Can you expand on that? Doesn't make any sense to me. I would think that if interrupts were allowed, some people could use them, and if a different user didn't need them, they wouldn't have to use them. The only architecture (other than the prop) that I know very well at the assembly level is the Intel 8051. If you want to use interrupts with that, you simply ensure your main program starts with ORG 0x30 instead of ORG 0. If you don't want to use interrupts, you ignore them and program as if they didn't exist.
By not having interrupts, but having multiple processors ensures that at least one processor can be assigned to each device that may need servicing. It also ensures that the code's timing is predictable and reproducible. There are no "magic" external events that can delay processing. Although it can complicate the code significantly, it is possible to write multithreaded routines that run in a single cog. FullDuplexSerial handles the receive and transmit sides of the serial port as interleaved threads and there's a 4-port serial driver that uses separate threads for the receive and transmit sides of each of up to 4 ports. Some of the video drivers do their initialization as a separate thread that executes during the vertical retrace interval. The JMPRET instruction makes this very straightforward.
The Propeller is a software defined I/O device. The multiple cogs can either be used to implement one or more I/O devices or can run other code. You may worry about cogs sitting around occupying silicon real estate or just sitting around waiting for something to happen, but the same can be said for an unused UART or unused SPI interface. In addition, if you don't like how an I/O device is implemented or if it doesn't do something you need, you can change the code on the Propeller. If the device is implemented in silicon, you're stuck with workarounds until a new model comes out.
A WDT can be implement using a cog or an external CMOS 555 timer depending on how separate you want the WDT from the rest of the hardware.
WDT & other peripherals: So this was a cost savings thing?
So... for example. I have a product that is about to come out next week called the CMUcam4:
One core does serial. It runs a receive and transmit thread. Up to 150,000 baud.
One core does high speed SPI bus interactions to a uSD card.
One core inputs 8 MHz 8-bit parallel video data from a camera module and does basic image processing between video lines.
One core takes processed binary images and displays them on a TV screen in NTSC or PAL.
One core does all the up level code interaction, protocol, and functional stuff.
And one core drives two servos, de-bounces a button, and does PID control on the two servos from data produced by the cog that is looking at video data. It updates at 1 KHz. If I told it to do more stuff it would have to update at a slower speed. But, If I rewrote it in ASM it would go much faster.
I still have 2 cores left... I ran out of I/O pins before cores.
Moral lesson? Don't waste your cores.
A very good question, not to stupid at all, and one that many newcomers to the Propeller ask.
I might put it like this:
In an ideal situation when your code runs it runs, and because we are dealing with the real world and real time external events we really want to be sure that nothing holds our code up from doing what it has to do. Else it might miss it's hard real-time deadlines. If there are no interrupts we can instruction by instruction calculate how long it takes to do whatever it is we have to do and be sure if we meet the timing requirements or not. Lets say we are driving a video signal and any delay would upset synchronization of the display.
But now if we have some other real world even to handle what should we do?
The logically simplest solution to that is to feed this new event to another processor and have it handle it whilst our first processor continues with whatever it has to do.
Then if there were a third external stimulus to deal with, no problem, just feed it to another processor. And so on.
Of course historically we did not have enough transistors available to implement a whole processor per external event in a micro-controller. The work around for this is to implement a single CPU with interrupts. Logically the same. IF the processor has the speed to do all the work of all the events. But now you are into a whole world of complication, having to hook processes into interrupts, assign priorities etc. Plus if my software module uses, and needs, all the time available how are you going to use it in your project on a single CPU micro-controller?
Bottom line is: Interrupts are the poor mans way of getting multiple processes. They works as long as your CPU is fast enough. They introduce a whole world of pain when integrating software components from external sources (think Parallax OBEX) where you have to analyse everything to figure out the timing budget.
Now, about the extra peripherals:
Logically, any logical function that can be done in hardware can be done in software. Functionally they are equivalent. That is of course if the processor running the software is fast enough.
Given that idea, it would be grate to not have any specialized hardware peripherals. Just have a lot of processors and implement those peripheral functions in software. That would mean instead of having to search out and find the correct chip with the right combination of peripheral for you next job you just pull another one of your multi-core chips out of stock and configure it how you like. If your design changes, no prob, no need to find a new chip, just reconfigure the one you have. By the way, with the Prop any COG can use any pin so there is no rearranging of board design to shuffle things around.
So, there you have it. No interrupts because they are a cludge to get around not having processors and make software integration and timing analysis hard. No peripherals because they are a cludge to getting around not having a fast enough processor(s) and inhibit flexibility of design.
At this point I should point out that XMOS (oops I said it) has the same idea with their line of multi-core MCUs.
Having said all that, following the "no periphals, no interrupts, multi-core philosophy has its limits. Perhaps you really need USB 2 or ethernet speeds that really can't be done on the Prop. A product designer has to choose what works.
Still the Prop II will push those limits further out without giving up the central idea.
Sweet. Sounds like I have lots to learn about efficiency still. I'll probably post up questions regarding that efficiency once I get further into the project and start needing it.
The Propeller does have some special purpose hardware. They're not complex enough to be labelled "peripheral blocks" and they do need the support of a cog. These would be the two counters in each cog and the video output shift register. They can be used for a variety of time dependent tasks. On the other hand, a cog can easily track the time since any of several pulses have begun. It may require some brute-force coding rather than making use of some of the special instructions like WAITPxx. It depends on the details of what you need to do. The system-wide clock counter can be used to mark the start of a measurement period.
The Prop-1 can do multiple ADCs (2 per cog) using 2 I/O pins, a pair of resistors, and a pair of capacitors per ADC. They're not as good as you can get using an external ADC, but they're good enough for audio in the voice range.
No one here is claiming that the Propeller is the "best microcontroller", whatever that means. It happens to be carefully and very well designed. It's reliable and resistant to a lot of abuse. There's good support for it. The decisions made in its design make it extremely useful for a variety of tasks, particularly where signal processing is involved. It's also different from many other microcontrollers and that may require rethinking how things need to be done.
True except:
When you are mixing and matching software components from different sources, like OBEX or just the forum or whatever, if they all have their different timing requirements and use various interrupts in different ways you are going to have to analyze the complete ensemble to figure out if it is going to work or not.
With multi-cores and no interrupts you can be sure that throwing in that serial driver you suddenly realized you need is not going to upset any of the carefully timed code in your project already.
This is a situation that happens all the time around here.
Mike: That clears up a lot more, as always.
Does the SX have interrupts? If it's as similar the prop as I'm hearing, it might work beautifully as a "peripheral" to the prop. I might use that to communicate with all the engine sensors and then stream data back to the prop.
I figure I should be able to do coil-on-plug spark timing, ion sensing, and crank-position capture with one cog, watch multiple MAPs and IATs with a second, leaving a third to run the fuel-flow servo, and a fourth do all the math, and 4 more for whatever else I decide to tack on later. Maybe VVT?
- R/C receiver - Measures pulses from 8 incoming pins. The pulses don't have to be in any order, and it has 1us accuracy
- Sensor I/O - A digital gyro and accelerometer are read at between 200 and 2000 hz, depending on the software settings
- Servo output - 8 pins are simultaneously pulsed at either 250Hz or 50Hz, with pulse lengths between 1ms and 2ms, with 1us accuracy
- Serial IO - For debugging or viewing sensor readings in a debug app
- Flight control - All of the above is controlled by a main loop, taking the readings, doing some math, and setting the servo output values to balance the craft, at 250hz
- SD card logging - 16 different readings are written to an SD card at 250 hz
And I still have two hardware threads left over. I have another version of the software that uses those extra cogs to run an "orientation estimator" and a floating point math library, allowing the craft to balance itself with no user input. The closest thing to this on a single-threaded chip requires a lot of very skilled coding to handle all the timing requirements and interrupt priorities, and even then it'll still be a bit less accurate than the Prop if one of those interrupts fires at a bad time. In this case the design of the Propeller is very well suited to the problem.
Also, you don't need to use a whole cog to monitor one pin - The R/C receiver cog mentioned above is a good example - It polls 8 pins in a loop, and if anything changes, it writes the pulse duration to the hub where other cogs can read it. It does 8 pins at better than 1us, which is the highest resolution I need. With clever use of the counter registers, you could monitor two pins with 80MHz accuracy, and that's with very minimal support from a cog. You could use the same cog to monitor additional pins in software.
It may seem strange to use threads for things that other micros provide in hardware. I always found it strange that on other chips I had to write my code around which peripherals are supported on which pins, and how to arrange them so I can use the UART, timers, and ADC at the same time.
I wrote some code for an embedded Hitachi processor to do datalogging of automobile sensors. There were several time based inputs (system timer, injector cycle, ignition timing, VSS) and these were implemented with interrupts.
If you venture into interrupts, you have to treat interrupt handlers as lightweight threads that do the timing critical work, then offload that data to the main loop to process at a lower priority. In essence, interrupts are where all the work gets done, not the main loop, because the main loop isn't deterministic. While you are executing an interrupt, the timing of that interrupt is deterministic. You can use nested interrupts, but I don't consider that a good practice because you may be re-entrant (executing the same routine again before the first invocation is finished) or you may interrupt a handler to run another handler, both situations prevent the interrupts from running in a deterministic timeframe.
The flip side of interrupts is that the interrupt has to complete before another interrupt can run, which means you might miss an event because interrupts are disabled (like Intel), or it might queue interrupts (where an interrupt mask is used).
And if your main loop doesn't complete in time to poll the "interrupt" pin???