//KM 2018 03 23: getting lots of form spam; screen out dates before 2000 (book publication date) How do I use eTPU semaphores? | Byte Craft Limited

How do I use eTPU semaphores?

eTPU_C

The short answer: assign a number from 0 to 3 to channel.SMPR, and loop until channel.SMPR tests true. Perform the sensitive work to be protected by the semaphore, and assign -1 to channel.SMPR.

Alternatively, use these macros in eTPUC_common.h:

// Semaphore operations
#define IsSemaphoreLocked()   (channel.SMPR == 1)
#define LockSemaphore(num)    (channel.SMPR = num)
#define FreeSemaphore()       (channel.SMPR = -1)

Semaphores are intended for communication between eTPU engines, when two (or potentially more) of them appear in an eTPU subsystem. A channel can set a semaphore, (non-destructively) test whether the other engine set the same semaphore, and clear the semaphore it set.

Simply use the above statements in two ETPU_functions that differ in their channel assignment.

There's little reason to use them within one channel context: eTPU threads are run-to-completion. The end of a thread clears the semaphore, but leaving it that long is not recommended as it could significantly delay the work of the other execution engine.

[Important] Important

While you can set one of 4 different semaphore values, you don't need to test which number was set. Simply test channel.SMPR: if it's true, you've set the same semaphore as the other engine, and your work might interfere with its ETPU_function's work. Wait until channel.SMPR is clear before proceeding.

Semaphores

This example demonstrates semaphore operations. The two functions below would be called by ETPU_functions running on different engines. Since they both use semaphore 2, the protected sections will not execute at the same time.

                                        void one(void)
                                        {
                                          do
                                            {
                                              channel.SMPR = 2;
                                            }
0200 F7A0101F   if smlck==0 jump 0200,    while (channel.SMPR == 0);
                    noflush.
0204 FFFFF7DB   ram lock_g2.

                                          /* Do protected work */

                                          channel.SMPR = -1;

                                          /* Continue */
0208 FFFFCCF9   return,noflush.         }
020C FFEFF7FB   ram free_g.

                                        void theother(void)
                                        {
                                          do
                                            {
                                              channel.SMPR = 2;
                                            }
0210 F7A0109F   if smlck==0 jump 0210,    while (channel.SMPR == 0);
                    noflush.
0214 FFFFF7DB   ram lock_g2.

                                          /* Do protected work */

                                          channel.SMPR = -1;

                                          /* Continue */
0218 FFFFCCF9   return,noflush.         }
021C FFEFF7FB   ram free_g.