How I Proved My Code Was Actually Running on Additional Propeller Cogs | by Maryclareok | Jul, 2026

Using the linker map, worker-reported cog IDs, an LED runtime test, simulation and oscilloscope measurements

By Maryclare

Press enter or click to view image in full size

Propeller Demo Board Propeller 1 Demo Board connected for a multicore execution-verification experiment, with the microcontroller board, breadboard area, and indicator LEDs visible.
Propeller 1 Demo Board used for the verification experiment. Image by the author.

My question was simple: How could I prove that code assigned to additional Propeller cogs was actually executing there, rather than merely existing somewhere in the compiled binary?

I was working with a Propeller 1 Demo Board, an older but unusual microcontroller built around multiple independent processors called cogs. Parallax lists the P8X32A as having eight 32-bit cores, 32 KB of shared hub RAM, and 512 32-bit words of local memory in each cog. This provides approximately 2 KB of local memory per cog.

The part that initially confused me was the relationship between the hub and the cogs. The hub stores shared program data and the compressed instruction stream. However, the hub does not execute instructions by itself. A cog still performs the processing. In my main program, Cog 0 ran the CMM kernel, which fetched and decompressed code stored in hub memory. The remaining cogs were available for worker code.

The PropGCC memory-model documentation explains that CMM stores code and data in hub memory and decompresses instructions through a runtime kernel. The mixed-mode documentation also explains that files ending in .cogc are compiled in the native COG memory model, even when the main project uses CMM. When a cog starts, it loads image it copied from hub memory into that cog’s local memory and execution begins there.

While working through the proofs, I realized that I needed evidence for these four claims:

· The worker cog images were included inside the hub.

· The main program successfully launched additional cogs other than cog 0.

· The worker code identified the cog it was running on (cog id or processor id).

· The worker paths continued executing at runtime on both the simulator and physical hardware.

1. Build evidence: the cog images existed in the linked program

I started with the linker map. The project contained two native worker modules: dummy.cogc and provecmm.cogc. The map file showed separate loadable sections for both images, including their sizes and hub load addresses.

Press enter or click to view image in full size

Figure 1Linker map Excerpt from the PropGCC linker map showing separate provecmm.cog and dummy.cog images, including their sizes and hub-memory load addresses.
Figure 1. Linker-map excerpt showing separate provecmm.cog and dummy.cog load images. Image by the author.

This was necessary evidence, but it was not evidence that this file was running in a separate cog. The map only showed that the compiler and linker placed the worker images into the final program. A load image can exist without ever being launched on a cog because every instruction in the cmm memory model compiles the instructions to the hub but we want the cog instructions to run on other cogs like cog 1 and 2 while the main code runs on cog 0 to take advantage of the multiple cogs or processors . I therefore treated the map as the first layer of the proof, not the conclusion.

2. Launch evidence: the main cog started two workers

The GCC (PROPGCC) for propeller 1 generates external arrays that point to each. cogc image. The main program passed those arrays to cognew() along with pointers to the struct which holds variables :

extern unsigned int _load_start_dummy_cog[];
extern unsigned int _load_start_provecmm_cog[];

dummy_cog = cognew(_load_start_dummy_cog,
&dummy_data.mailbox);
monitor_cog = cognew(_load_start_provecmm_cog,
&monitor_data.mailbox);

In my terminal output, the main program reported Cog 0, then cognew() returned Cog 1 for the dummy worker and Cog 2 for the monitor worker. This showed that two additional cog slots had been allocated.

Worker code:

In the worker code the cog id was passed into the mailbox and called during run time, The main program then read and printed those mailbox values.

The dummy worker reported Cog 1, while the monitor worker reported Cog 2. Because cogid() was called inside the worker code, these values provided worker-side evidence of which cogs were executing the two worker images.

Press enter or click to view image in full size

Figure 2. Cog id code from .cogc file. Image by the author.
Figure 2. Cog id code from .cogc file. Image by the author.
Press enter or click to view image in full size

Figure 3. SimpleIDE terminal output: Cog 0 launched workers that reported Cog IDs 1 and 2. Image by the author.
Figure 3. SimpleIDE terminal output: Cog 0 launched workers that reported Cog IDs 1 and 2. Image by the author.

3. LED runtime evidence: the monitor worker toggled the Pin 20 LED

I performed a simpler physical runtime check with the Demo Board LED connected to Pin 20. This test used the provecmm.cogc monitor worker. Inside that worker, Pin 20 was configured as an output and toggled repeatedly. Because the Pin 20 output instruction was located inside the worker loop, the visible LED activity showed that the monitor worker had reached and continued executing that runtime path.

Get Maryclareok’s stories in your inbox

Join Medium for free to get updates from this writer.

The code screenshot and board photograph below belong to this Pin 20 LED test.

Press enter or click to view image in full size

Figure 4. The provecmm.cogc LED-test code defines DEBUG_PIN as 20 and toggles that output from inside the worker loop. Image by the author.
Figure 4. The provecmm.cogc LED-test code defines DEBUG_PIN as 20 and toggles that output from inside the worker loop. Image by the author.

Similar Posts

Leave a Reply