Find answers to some Frequently Asked Questions here! This FAQ page will be updated as we determine where people run into problems. If you have a FAQ suggestion, please email it to firstname.lastname@example.org.
A: There are small solutions, but they will not be fully ANSI-C compliant like printf and scanf.
The most common solution to the code size dilemma for running within a cramped memory space is to use non-standard libraries. Parallax Education is providing libraries that solve the size problems and provide practical solutions. The Propeller-C Learn web site is a great place to visit for more information on the education libraries.
To use fully ANSI-C compliant code for larger projects, Propeller-GCC provides XMM modes (XMMC, XMM-SINGLE, and XMM-SPLIT). XMM modes require external hardware. A 4 pin SPI-Flash (XMMC) is one of the more practical solutions because 1MByte devices are available cheaply, they are easy to connect/configure, and XMMC provides the fastest solution. To use the C++ standard name space (std) and functions such as std::cout and/or std::cin, an XMM-SINGLE or XMM-SPLIT solution is required. The Parallax C3 board can serve any of these needs.
It is important to realize that printf and scanf conform to the ANSI-C standard. Standards are created to serve many users and ease portability. In the case of printf and scanf, they are giant functions that provide char, char*, int, float, and double formatted output and input. Further the definition of char and char* allow for internationalization with UTF-8. All of this support is very costly on a micro-controller. Other things like enabling full math library compliance further complicate the memory footprint.
A: These memory models describe the way the Propeller GCC compiles and stores your program code. Depending on which memory model type you compile for defines how the Propeller will execute your compiled program.
A: All Propeller based boards share common features. Thus, Propeller GCC and Simple IDE supports every Propeller board when compiling in COG and LMM modes. Some boards are designed in a special configuration or have external peripherals that can be defined in a board configuration file. These board configuration files tell the compiler and loader how to map special functionality inside of your program. Many Propeller boards have configuration files already created, with more being added. The "HUB" configuration is the most common board type for 80 MHz with a 5 MHz crystal. The "SpinStamp" or "Hydra" board configuration files are good for 80 MHz with a 10 MHz crystal.
A: Yes it can! You should follow the guidelines on this page to reduce the footprint of C++. In particular, you'll need to give up exceptions and redefine the new and delete operators as shown. In addition, you should use stdio.h (printf, etc.) for input and output instead of iostream (cin, cout, etc.). Finally, you should stick to the basics of the C++ language and give up complex inheritance, templates, and other advanced features. If you follow these guidelines, you can have C++ programs that are roughly the same size as C programs.
To compile as a C++ program, make sure that you use a C++ file extension and use propeller-elf-g++ (instead of propeller-elf-gcc) to compile.
In one case, refactoring a C function to be a static member function of a C++ class actually resulted in a 4 byte code size reduction. If you can run C, you can run C++ and get the benefits of classes.
A: Most of the C language is supported by PropellerGCC, and you can get started without understanding anything about the Propeller architecture. There are, however, some key additions and limitations that the Propeller brings to GCC:
1. Specific hardware functionality, such as pin registers, multiple cores, and locks. These can be found documented in propeller.h.
2. The compiled memory model is a unique feature of PropellerGCC, and must be set at compile time.
3. The Propeller has very limited memory, so many of the larger standard library features and techniques will consume a high percentage of the available.
A: Not directly, but you can convert your Spin files to PropellerGCC files with the spin2cpp utility. Note that spin2cpp is now packaged with PropellerGCC, so you don't need to do anything special to install it.
A: It's constantly being improved, but post #3 in this forum thread has some good information. In short, the results are:
Benchmark using Fibo(26):
*PropellerGCC is using standard flags (-Os, etc.)
** C code, compiled directly to machine language (no run time overhead).
Note that this is only a rough ordering of the code types, and actual performance will vary. The above results are without the fast cache (-mno-fcache). With the fast cache, PropellerGCC was able to compile the FIBO loop to cog assembly and get a time of 927ms in both LMM and CMM mode.
Size comparisons with SPIN are misleading. The SPIN 2KB interpreter lives in Propeller ROM. For C we need to carry the 2KB kernel in the HUB RAM.
The FIBO CMM is only 25% smaller than LMM because of the 2KB kernel. Factoring out the 2KB kernel shows that CMM is 46% smaller than LMM (1-(3292-2048)/(4364-2048) = 46.3%).
A: For any questions that you may have, the best place to start would be to post on the PropellerGCC sub forum here.
Q: Can I use PropellerGCC, SimpleIDE, etc. on my phone, tablet, RaspberryPi, or other ARM based device?
A: At this time, not officially. There may be versions of PropellerGCC that have been prebuilt for ARM, but you won't be able to build it yourself. The problem is that the build relies on BSTC.linux for compiling some loaders during installation, and BSTC.linux is a closed source program built only for x86. Until OpenSpin replaces BSTC.linux in the build ARM architectures will not officially be supported (information out of date).
Update: Propeller-GCC is built on Rasberry Pi, and today one should be able to build the code from source. OpenSpin is now supported in Propeller-GCC release_1_0 and SimpleIDE. Propeller-GCC default uses spin2cpp to eliminate the need for BSTC and OpenSpin.
Parallax is testing an official Rasberry Pi build.
A: First off, make sure that the Propeller board is plugged in and powered on. Next, try running
If you don't, then make sure you have the FTDI drivers installed. Next, try running
A: COG, LMM, and CMM memory models start on COG0. The actual program code in XMM memory models may start on COG3 depending on the helper function COGs used prior to loading and running the XMM program.
A: There are 7 Propeller hardware locks available to use (one lock is used by the LMM interpreter, see crt0_lmm.s), and these have the hardware semantics specified in the Propeller manual. You can also use the 32 bit _atomic_t type from <sys/thread.h>, of which you can declare as many as you want.
A: We didn't think users would very often need the return value of lockclr, and to get that value reduces the performance. For recommended usage of Propeller locks, see the Propeller Manual v1.2 page 123. Also note that lockret does not automatically clear the lock! The only way to clear a lock is an explicit call to lockclr.
Q: My multi-cog program works when I turn off optimization, but it doesn't seem to to work with -O3 or -Os. What is wrong?
A: You probably forgot to add the "volatile" keyword to variables that are shared between cogs.
A: The cog remains allocated, and must be stopped with cogstop(id). The following line of code will allow a cog to stop itself, and should be used instead of a return statement:
A: There are a number of techniques. For a few techniques (including some C++ specific ones), see the PropGCCTightMemory page. Some other techniques that you can use:
1. Use link time garbage collection. Typical space savings range from 1-2KB and up, with no performance penalty.
If you're using the most recent build of PropGCC from the p2test branch (see below), then all you have to do is specify -ffunction-sections -fdata-sections -Wl,--gc-sections when you compile and link. If you want to see what sections were removed, use -Wl,--print-gc-sections.
If you are not using the most recent build, you will have to create a linker script that prevents the garbage collection from throwing out too much. To do that, compile and link a working program with -Wl,--verbose. In that output, you will see the default linker script that is being used. Copy that into a file called main.ld . Next, add a KEEP() directive around the .init*, .ctors*, and .dtors* sections. For example:
Save the file in the same directory as your makefile and source files. The next time that you compile and link your program, use -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--script=main.ld.
2. Use CMM mode instead of LMM mode. CMM mode can result in 40% smaller code than the same LMM code for large programs. There is a performance penalty, however.
Q: What is the error that I get about an invalid conversion when I try using cogstart on a function?
A: This error (or warning) may be something like this:
main.cpp:519:59: warning: invalid conversion from 'void (*)()' to 'void (*)(void*)' [-fpermissive]
You probably forgot to make the function parameter of type void *. The solution is to make your function have the following signature:
void name(void * parameter)
To learn more about starting a new cog, see the cogstart documentation.
A: C++ classes have an implicit
You may be getting an error like this:
MyClass.cpp:95:44: error: argument of type 'void (MyClass::)(void*)' does not match 'void (*)(void*)'
A: The Propeller has 3 I/O registers: INA, OUTA, and DIRA. These can be accessed by including propeller.h in your source. These registers follow the semantics found in the Propeller datasheet.
For an example of controlling an I/O pin, see pin.h.
A: The two most common causes of a hanging program are missing volatile and too small of a parameter to waitcnt(). Depending on the memory model, the fast cache status, and the optimization level, a parameter to waitcnt() may be too small for a particular combination.
A: There are lots, but here is a short list of problems:
The assembly sections of the Propeller Tricks and Traps document might be useful.
fcache #(PutByteEnd - PutByteStart)
... <asm code>
... <asm code>
... <asm code>
The format of __LMM_FCACHE_START+ is:
__LMM_FCACHE_START+(Label to jump to - Label at beginning of fcache'd code) ==> constant for jmp
If you don't have a loop, then you can ignore the section on the __LMM_FCACHE_START+. You will also likely need the final jmp (Confirmation? SRLM 2013-03-15).
A: PropellerGCC will put an extra \r whenever it sees a \n. To prevent this behavior, try
stdin->_flag &= ~_IOCOOKED;
For more information, see this forum thread.
It is impossible to turn off cooking for stdout without changing the library.
A: PropellerGCC includes most of the "regular" gcc options (such as -Os, -Wall, etc.), but includes a few extras:
Propeller Mode Options
-mcog (Generate code to run in internal cog space.)
-mlmm (Generate for large memory model (LMM) (code and data in hub))
-mcmm (Generate for compressed memory model (CMM) (code and data in hub))
-mxmm (code in external flash and data in external SRAM)
-mxmmc (code in external memory and data in HUB)
-mxmm-single (both code and data in one external memory)
-mxmm-split (same as -mxmm)
-mp2 (Generate code for Propeller 2)
Propeller Floating Point Options
-m32bit-doubles (can make code faster by defining double as 32-bit)
-m64bit-doubles (regular 64 bit doubles)
Propeller Cache Options
-mfcache (small routines may be cached in cog for faster performance (even in xmm mode))
-mno-fcache (no cache)
GCC Compiler Options
-Dprintf=__simple_printf (use smaller printf)
GCC Linker Options
-ltiny (inlude a smaller standard I/O library with no floating point)
A: PropellerGCC has all of the normal GCC defines, plus a few Propeller specific defines:
__PROPELLER__ is always defined by PropGCC, to note that we're compiling for the propeller)
__PROPELLER_LMM__ is defined in LMM mode
__PROPELLER_CMM__ is defined in CMM mode
__PROPELLER_XMM__ is defined in XMM mode
__PROPELLER_XMMC__ is defined in XMMC mode
__PROPELLER_USE_XMM__ is defined in either XMM or XMMC modes
__PROPELLER_64BIT_DOUBLES__ is defined when doubles are 64 bits long
__PROPELLER_32BIT_DOUBLES__ is defined when doubles are 32 bits long
__PROPELLER2__ is defined when compiling for P2
A: In XMM mode data is stored in external memory by default, but you can explicitly specify it goes in hub memory instead with the HUBDATA declaration. This is useful for commonly used data structures where performance is a concern.
HUBDATA char screen;
Here "slow" will be in external memory, "screen" will be in HUB. You can put code in the hub by using the HUBTEXT constraint.
Note that in XMMC mode, all data is in the hub.
A: Hmmm. I don't know. I'll have to get back to you on that one.
You have several options. One is at load time with board configuration variables. You could put a
Q: I tried converting an PASM cog assembly program from Spin to GCC GAS, and now it compiles but nothing happens. What's wrong?
A: Have you checked your addressing? In PASM you may see something like this:
When that's converted (by spin2cpp) to GNU GAS, you need to manually adjust the addressing. PASM uses long addresses while GAS uses byte address. So, you need to multiply each offset by 4:
Or, even better, just use a label for everything that you want to reference.
In short, double check that all compile time addressing is done with byte addresses.
A: In Spin you can use the <~ and ~> operators to rotate the bits of a variable. The Propeller even has a handy pair of instructions (ROR and ROL) to make this very efficient. In C you can use the following functions:
In most cases, with optimization on, PropellerGCC is smart enough to reduce this to a single instruction (see discussion here).
A: No. There is no provision for printing simultaneously from two cogs in Propeller-GCC. The common solution is to serialize access to printf by using locks. It is up to the user to manage resources using mutex locking for this purpose. See propeller.h documentation for lock functions.
A: Yes. Add the following in the GCC command line options: -Wl,--defsym,__stack_end=0x7000
I.E. $ propeller-elf-gcc -Os -Wl,--defsym,__stack_end=0x7000 -o test.elf test.c
That will make your program grow stack from 0x6FF8 down. It means that 0x7000 and above can be used for fixed address variables, etc....
A: Well... Hmm... We'll have to get back to you on that.
A: You're not alone! simpletools (also known as Simple Library) is packaged with SimpleIDE. The raw form can be found here. and the official releases can be found here.
A: There aren't that many places yet, but some of them are:
You may also have luck finding code attached to posts on the Parallax forums. If you find some Spin code that fits your requirements you can use the spin2cpp tool to convert it to C or C++.
A: propeller-elf-gcc and propeller-elf-g++ both can compile C or C++ code (they use the file extension to tell which is which). The difference comes in the final link step: g++ includes the standard C++ libraries, and gcc does not. For code which does not use any C++ libraries, it doesn't matter.
A: We have a great team. They are:
Want to say thanks? Make a great project using PropellerGCC, and post it up on the forums!
A: Note: This is not legal advice, just some comments to help augment your decisions. Please consult your counsel for any licensing information that you may need.
There are two distinct cases where you need to consider licensing:
Most users do not need to worry about licensing with PropellerGCC, whether they are developing an open source application or a proprietary application. These users do not need to worry about "viral GPL" licensing.
A: You should build the default branch directly from the PropellerGCC Mercurial repository, as described here. This branch now has Propeller 1 and 2 support, along with all the latest features. Current binary releases are packaged with SimpleIDE or available separately as a Propeller-GCC package.