Parallax took a major turn from its bread and butter Basic Stamps and SX processors with its new Propeller architecture (see “Eight 32-Bit Cores Take Flight In Multiprocessor Microcontroller,” ED Online 12235). The Propeller packs eight 32-bit processors, called cogs, into a single package (see Figure 1).
Packing eight identical processors in the same package with shared memory may seem like a straight forward architecture but the Propeller is a bit more complicated and novel. For example, all eight cogs have access to all of the same 32 IO pins at the same time. This can make debugging a bit difficult if two processors accidentally use the same pin at the same time in a different fashion. This simply means designers need to have a good understanding of the application and its implementation.
The other thing is that Propeller has a split personality. First there are the eight cogs that have 512 32-bit words of RAM for variables, stack and cog code (also called Propeller assembler). The second is the Spin interpreter. Spin is a high level language where the high level control aspects of an application occur. Spin code is stored in main memory that consists of 8Kwords of RAM and 8Kwords of ROM. The latter contains the Spin interpreter along with other system tables and the system boot loader. The interpreter is written in cog code and is designed to run on a cog. The variables for the interpreter are stored in the cog’s memory but the Spin code is found in main memory. The interpreter reads a Spin instruction and then interprets it.
Spinning Up A Propeller
The boot loader cog code is what is loaded into a cog when the chip starts up. The boot loader can load an application into the main memory from the serial port or from a serial flash memory (see Figure 2). This is the configuration found on the Propeller demo board (see Figure 3). A serial interface is connected via the Propeller Clip (see Figure 4). Other development tools include the Propeller Stick kit (see Figure 5) that you need to assemble (see Figure 6).
Once the program code is loaded into main memory it begins executing the Spin code for the “top object.” This in turn can start up additional cogs. This is done by aiming a cog at an “object” stored in main memory. The cog code for this object is then copied to the cog’s memory and it begins running. The newly running code has access to main memory and is passed a parameter that it can use as the basis for communication and utilization of main memory.
Starting cogs is where the Propeller’s novel architecture comes into play. Any cog code can run on any cog since every cog has the same interface to all the IO pins and to shared resources like main memory. Of course, you run into problems if you need to startup more than eight cogs simultaneously but that is essentially having eight tasks running at the same time. If a cog finishes running it simply shuts down and waits until a new cog is needed. A powered down cog uses minimal power so a Propeller only draws its full power complement when it is fully loaded.
Whether a logical cog is dedicated to continuous or transient operation depends upon the application. For example, a VGA display object (yes, a cog is powerful enough to generate video signals on the fly) would run continuously, or at least as long as you wanted to display something on the screen. A transient might be a filter that gets applied to data stored in main memory.
Now Parallax’s idea of an “object” is a bit different than say C++ or Java although there are some similarities. Parallax thinks of an object as a combination of Spin code, cog code, and main memory data. In fact, that is what a .spin file defines. The .spin file also includes constant definitions and documentation making an “object” definition a single file. In fact, the file is more of a class definition since an instance of an object occurs when it is loaded into cog memory and the cog’s local memory contain object’s variables. Shared variables in main memory could be considered class variables in a C++ or Java context. The big difference is that a Propeller can have only eight active objects at a time.
Actually, things are a bit more complicated. The Spin code associated with a .spin file provides the high level interface to an object. The cog code is what is run when it is instantiated on a cog processor. The two interface via the Spin (class) variables. Spin code from any object can call the Spin code of another object but not the cog code. Likewise, an object’s cog code can call functions defined within the object but not functions in other objects.
So if you can get your head around this concept then you are well on your way to coding a Propeller. It is actually quite elegant and simple once you understand it. It just tends to be very different from what you are used to with conventional architectures.
If you haven’t figured it out yet then check out the 400+ page manual for the Propeller. It is available as a free download from the Parallax website. It is actually that large because it gives you all the gory details for the system including the Propeller assembly language reference (i.e. cog code definitions).
In essence, cog code is designed to be tight and fast. The code tends to be dedicated to a particular aspect of the application. More complex problems need to be broken up into objects that will run sequentially or simultaneously in a cooperative fashion. The high level Spin code is designed to be slow but more flexible. Because it is interpreted, it is much slower than cog code but it has a higher code density.
SPINning A Program
The Propeller development tool (PDT) (see Figure 7) is designed for editing and downloading a program to a Propeller chip. It does not include a debugger hence I did not refer to it as an IDE (integrated development environment) (see Figure 8). In fact, Parallax does not provide any sort of debugger with the system. More on that later.
I found the PDT a bit confusing at first. This is because of the difference between the Propeller’s architecture and other microcontrollers as well as the syntactic and semantic nature of the .spin files. Parallax also tends to use their terminology. For example, building a project is done via Run/Compile Top/Update Status. Luckily the PDT is relatively simple and easy to use.
Lets start by looking at the organization of a .spin file in more detail. It is a text file and information is section dependent. Sections include CON (constants), VAR (class variables), OBJ (objects required by this object), PUB and PRIV (public and private Spin code) and DAT (cog code). There is also the hidden documentation section to complement the inline comments.
One thing to keep in mind is that indentation counts. For example, here is a simple SPIN program that toggles an LED attached to pin 16.
CON Pin = 16 Delay = 3_000_000 PUB Toggle dira\[Pin\]~~ repeat !outa\[Pin\] waitcnt(Delay + cnt)
The repeat statements use should be obvious but keep in mind that the two lines beneath it are the repeat block. Pasting in code like this:
CON Pin = 16 Delay = 3_000_000 PUB Toggle dira\[Pin\]~~ repeat !outa\[Pin\] waitcnt(Delay + cnt)
causes some interesting problems.
Spin code is very similar to Basic. I found it easy to read once I got used to the indentation requirements.
What was a little more difficult was learning how to multitask at the Spin and cog level. Multitasking at the Spin level is done by starting up another cog running the Spin interpreter. The cog is given a reference the Spin function to execute. There is no concept of yielding with Spin or cog code. In fact, there are no interrupts. Everything is designed to be polled although it is possible for cog code to wait for a change on the IO lines.
The PDT uses color coding of blocks to make text entry easier. It is also possible to view a file in full, condensed (no comments), summary, and documentation mode. This helps on navigation but summary mode only lists Spin functions, not cog functions.
The only options within the PDT are to edit and save a file or download it to RAM or flash on the target Propeller system. Once it is downloaded it begins to run. In general, debugging/testing an application is done by writing directly to RAM. This is very fast. Unfortunately, there is limited recourse if things go wrong.
Debugging A Spinning Propeller
Shades of PBasic. That is probably the best way to describe debugging with the Propeller. Actually it is a bit more primitive because there is no sense of a PRINT statement because even the serial USB interface to the Propeller chip has no special significance.
Luckily there are some tools that are available to provide debugging services. Likewise, the PDT and the object oriented nature of the system lend itself to incremental development and testing.
First, consider the growing set of predefined objects such as LCD and display (VGA and composite video) that are already available. There are even serial interfaces that provide very basic debug monitor type functions such as dumping memory. These objects make it possible to develop a PRINT/INPUT style of debugging.
Unfortunately there is no way to easily implement a single step debugger for either cog or Spin code. In the former case there is no debug or single step mode for a cog. In the latter, the Spin interpreter store in ROM is only available to execute instructions. There are no hooks exposed to implement debug features like breakpoints or single stepping.
The only thing that limits this problem is the size of memory in a cog and in main memory. Applications simply cannot get that large with only 8Kwords of main memory especially since that must be split between Spin code, cog code, data and stacks.
The actual method used to debug a program will vary depending upon the experience of the developer, the complexity of the project and the use of existing, debugged objects.
In general, I found the lack of debug support a hassle after moving past the small sample applications. I did depend upon objects like the display monitor support but it takes a good deal of memory. If I were doing a major project I would probably take some time to implement a very simple, cog-level object to provide access to main memory via a serial link to a PC-based application. This actually is a good example of how to take advantage of the Propeller architecture since it would use a small bit of code and utilize a single cog.
Propeller Gripes And Grins
The lack of a debugger is a definite problem. This means only a seasoned programmer should tackle the Propeller even at the Spin level. Sample applications and simple applications tend to be easy but venturing outside this boundary can be time consuming.
The mixing of online documentation with source code is a good idea but the implementation leaves a little to be desired. There is only one big documentation block. There is no correlation between it and any of the Spin or cog code. Jumping between the code and documentation to make changes is painful at best.
On the plus side, the Propeller has a really neat architecture. It is novel but extremely powerful. It will take some imagination to use the architecture effectively but it offers a platform that is unmatched at this time.
One interesting aspect of the architecture is that it is quite possible to have a system that is only running cog code. Well, actually that is always the case but it is possible to not be running the Spin interpreter while all the other cogs are active. In this case an application will have some Spin code to setup the system but it may then simply continue in a steady state running just high performance cog code that is part of the application. Very interesting.
The tools are free and the hardware is inexpensive. This definitely makes it easy to evaluate. The power advantages should appeal to portable device developers.
Ready For Prime Time
Parallax has some solid hardware but its software tools could use some work. This poses some interesting challenges for developers that plan to deploy a Propeller-based application. As with any processor, the applications that work well with the chip varies and there should be some very interesting applications for the Propeller. It will take developers that can think outside the current single processor or SMP (symmetrical multiprocessor) box in addition to ones that can also think at two levels (cog and Spin).
Unlike most microcontroller solutions, it is very easy to throw more compute power at a problem. Most other platforms require you to carefully allocate processing resources. On the other hand, the memory limitations and architecture of the Propeller are quite different. Still, it is not as if Parallax has an architecture that is totally unique. IBM’s Cell processor has a similar, although larger, multicore architecture that game designers will have to get used to if they plan on targeting the Sony Playstation 3.
For now, I think the Propeller is a neat thing to experiment with. I look forward to improvements in the IDE and in debugging but for designers willing to take off right now the Propeller is worth a spin. There are many control oriented problems that can be solved using the power of the Propeller.