FreeRTOS stack size on ESP32 - words or bytes?

Although FreeRTOS1 is an indispensible tool for working on anything more than the simplest application on ESP32, there are some difficulties to master, such as multitasking. Multitasking using FreeRTOS is accomplished by creating tasks with xTaskCreate() or xTaskCreatePinnedToCore(). In both of these calls, one of the parameters is uxStackDepth which is the allocated stack size for the task. The FreeRTOS documentation on the subject is clear about the units for uxStackDepth:

The number of words (not bytes!) to allocate for use as the task’s stack. For example, if the stack is 16-bits wide and uxStackDepth is 100, then 200 bytes will be allocated for use as the task’s stack. As another example, if the stack is 32-bits wide and uxStackDepth is 400 then 1600 bytes will be allocated for use as the task’s stack.

The FreeRTOS declaration of xTaskCreate() is:

BaseType_t xTaskCreate(    TaskFunction_t pvTaskCode,
                            const char * const pcName,
                            const configSTACK_DEPTH_TYPE uxStackDepth,
                            void *pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t *pxCreatedTask
                          );

where the units of uxStackDepth are words not bytes.

So that’s the story in vanilla FreeRTOS. Then we would expect on ESP32 with 4-byte wide words that if wanted to provide a 4096 byte deep stack, we would use a uxStackDepth value of 1024. But, the plot thickens. In the ESP-IDF implementation of FreeRTOS, the function declaration of xTaskCreate() (and friends) differs:

static inline BaseType_t xTaskCreate(
	TaskFunction_t pxTaskCode, 
	const char *const pcName, 
	const configSTACK_DEPTH_TYPE usStackDepth, 
	void *const pvParameters, 
	UBaseType_t uxPriority, 
	TaskHandle_t *const pxCreatedTask
	);

Notice that the the stack size parameter is now const configSTACK_DEPTH_TYPE usStackDepth and the documentation makes it clear:

IDF FreeRTOS also changes the units of ulStackDepth in the task creation functions. Task stack sizes in Vanilla FreeRTOS are specified in a number of words, whereas in IDF FreeRTOS, the task stack sizes are specified in bytes.2

So on ESP-IDF (and the ESP Arduino core), task creation is in bytes not words.


However, we also sometimes want to see how much of the stack allocation we’re using in order to fine-tune the allocation. In FreeRTOS, we can use the uxTaskGetStackHighWaterMark API to inspect the stack high water mark. For example:

void vTask1( void * pvParameters ) {
    UBaseType_t uxHighWaterMark;
    /* Inspect our own high water mark on entering the task. */
    uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
    for( ;; )
    {
        /* Call any function. */
        vTaskDelay( 1000 );
        /* Calling the function will have used some stack space, we would 
        therefore now expect uxTaskGetStackHighWaterMark() to return a 
        value lower than when it was called on entering the task. */
        uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
    }
}

So does uxTaskGetStackHighWaterMark() returns words or bytes? In the official FreeRTOS documentation for uxTaskGetStackHighWaterMark() we read:

The value returned is the high water mark in words (for example, on a 32 bit machine a return value of 1 would indicate that 4 bytes of stack were unused). If the return value is zero then the task has likely overflowed its stack. If the return value is close to zero then the task has come close to overflowing its stack.3

So, then the answer is words. But does the ESP-IDF implementation differ? Here’s what the documentation says about it:

So the type returned by uxTaskGetStackHighWaterMark() is determined by configSTACK_DEPTH_TYPE. Out-of-the box in the ESP-IDF flavour of FreeRTOS.h, this is defined in FreeRTOS.h as:

#ifndef configSTACK_DEPTH_TYPE

/* Defaults to uint16_t for backward compatibility, but can be overridden
 * in FreeRTOSConfig.h if uint16_t is too restrictive. */
    #define configSTACK_DEPTH_TYPE    uint16_t
#endif

Further, several comments on the official Espressif ESP32 forums posted by Espressif developers point to this function returning bytes not words. For example,

Stack is in bytes…4

and

Vanilla freertos is using dword for creating task and stack watermark. esp-idf is using bytes as base size in both functions.5

Conclusion

In the end, the short version of this story is that on ESP32, working in ESP-IDF and friends, that stack size is assigned and reported in bytes.

References


  1. FreeRTOS documentation ↩︎

  2. ESP-IDF documentation: FreeRTOS task creation ↩︎

  3. FreeRTOS documentation for uxTaskGetStackHighWaterMark ↩︎

  4. Comment on ESP32.com ↩︎

  5. Another comment about stack size type on ESP32.com ↩︎

Our vermiculture process: A sustainable contribution

Several people have asked me how we manage a very productive vegetable garden; so I’ve written this post as a brief description of one aspect our our approach - vermiculture.

One of our overarching family goals is sustainable living. It’s basically about leaving a small footprint. A practical component of this philosophical stance is dealing with food waste. We deal with kitchen waste with a combination of bokashi composting and vermicomposting (also known as vermiculture) It’s not for the faint-of-heart and some are horrified to learn that I keep thousands - possibly hundreds of thousands - of worms in our basement. But some have asked me to describe our process; so this article is meant just to document it. There is a lot of art and science to vermiculture and this is not meant to be a definitive guide to vermiculture.

TL;DR;

Worms can consume food scraps and other organic material, turning it into worm castings (aka “poop”) that enriches garden soil. We raise composting worms as part of our strategy to reduce waste and to enrich the organic content of our garden.

Composting worms

It’s important to distinguish between two types of worms:

  • Composting worms
  • Earthworms

The worms that you find when digging in the garden or that you see on the sidewalk after a rainfall, are not composting worms. These earthworms do consume organic material but they live in deep burrows and do not tolerate the high living density that compost worms do. Basically, they are loners. Composting worms naturally live together in much higher density, just under the veneer of leaf litter and can be voracious consumers of organic material. So the bottom line is that you cannot just pick up some earthworms off the sidewalk and start a vermiculture operation. For the most part, you have to purchase them.

Our composting worms

We play host to three different types of composting worms:

  • Red wrigglers (Eisenia foetida) - this is the most common “workhorse” of the vermiculture world and are the easiest to purchase. They are like the Dodge Stratus of the worm world. Commonplace and not likely to win any speed records, but they get the job done.
  • African nightcrawlers (Eudrilus eugeniae) - these are fast composters and not as easy to find commercially. They are a much larger worm than the red wriggler; and they are fairly picky about temperatures. They cannot tolerate cold temperatures like the Eisenia foetida but they work fast and furiously, consuming huge amounts of organic material. If the red wriggler is the Dodge Stratus, these are the Ferrari’s of the the vermiculture world.
  • Some unknown worm - I harvested a bunch of worms from an outdoor compost pile. Despite my best efforts, I have never identified exactly what they are.

Worm husbandry - our approach

Composting worms, known for their generally non-fussy eating habits, do have a few dislikes, including onions, citrus, and fatty foods. However, I’ve found a way to make these items worm-friendly. The secret lies in a Japanese composting method called bokashi pre-composting, which ferments food waste anaerobically. We use a 5-gallon bucket for this, adding food scraps and sprinkling them with a special lactobacilli-infused dried rice bran, facilitating the fermentation process. Once the bucket is full, we leave it for a two-week fermentation period.

Typically, after fermentation, bokashi compost is buried in garden soil, where soil microorganisms complete the decomposition quickly. However, I discovered that this pre-compost is also a fantastic food source for worms in a worm bin. The acidity of the bokashi compost requires a bit of dolomitic lime to balance the pH for the worms. We also limit the amount of bokashi compost to what the worms can process in 10-14 days to maintain their health. An added bonus is the heat produced during the bokashi breakdown, which benefits our worms living in a cold basement.

Another critical aspect of successful worm composting is bedding, which should be about 80% of the bin’s content. Bedding, typically carbon-rich material, aids in aeration, moisture management, and preventing compaction. It also moderates the heat from the decomposition of nitrogen-rich food. While many materials are suitable for worm bedding, I prefer shredded cardboard, like Amazon boxes. Shredded into strips and added to the bin, this bedding not only serves its purpose but eventually becomes worm food too. Yes, our worms even munch through our Amazon delivery boxes!

Our operation is large; but it’s not the largest, certainly not at a commercial level of operation. However we currently have 12 bins of various worms - about half Eisenia foetida and half African nightcrawlers. Most of the tubs are simple 4" high restaurant bus tubs that can be purchased in bulk from restaurant supply facilities.

And that’s our process.

Frequently answered questions

Where do you keep the worms?

They live in plastic tubs in our unfinished basement.

You’re working with decaying food matter. Doesn’t it smell bad?

There really isn’t any odor. The bokashi doesn’t smell great; but most of the time it is sealed in air-tight containers. It’s open to air, of course, when I feed the worms which is about once every 10-14 days.

Isn’t it a lot of work?

The worms can go many days with no attention at all. They work 24/7 in the dark. Periodically I feed them and about every 3 months, the worm castings need to be harvested; and that takes a bit of time.

It sounds gross.

That’s not a question; but have you actually considered how food gets to your table? Do you wonder why food warnings about E. coli are so common? And if you consume meat, have you considered how that slab of flesh ends up on your plate? It’s not pretty. And it’s shameful.

Is it expensive?

In our area, worms go for about $50-60/lb. I’ve probably purchased about 3-4 lbs of worms. The rest come from reproduction which under optimal conditions is quite rapid. The African nightcrawlers are champions of reproduction. Remember, worms are hemaphrodites, so there’s a lot of reproduction that can happen in those bins!

An approach to interleaved and variable musical practice: Tools and techniques

“How do you get to Carnegie Hall” goes the old joke. “Practice, practice, practice.” But of course there’s no other way. If the science of talent development has taught us anything over the last fifty years, it’s that there is no substitute for strategic practice. Some even argue that innate musical abilities don’t exist. Whether it’s nature, nurture, or both, show me a top-notch musician and I’ll show you a person who has learned to practice well.

Telling Hazel not to match locked files

Hazel is a centrepiece of my automation suite on macOS. I rely on it to watch directories and take complex actions on files contained within them. Recently I discovered an issue with files that are locked in the Finder. If files that otherwise match all the rules are locked, then Hazel will attempt to execute the rules. But the locked status may preclude execution. For example, I began seeing frequent Hazel notifications popups such as:

Quickly change playlist view options on macOS

While Apple is slowly coming around to recognizing that some of its users listen to classical music, there is one quirk in the Music app on macOS that betrays its deep bias toward pop music. It’s this: when you create a new playlist, the application defaults to displaying the tracks in its “Playlist” view, which as far as I can tell serves no other function than to consume real-estate in the UI by displaying a thumbnail of the album art.

Obsidian file creation date debacle and a solution

Obsidian is pretty reckless with file creation dates. If you modify a note in Obsidian, it updates the file creation date. This renders Dataview queries that rely on it useless. For an introduction to this issue, see this lengthy thread on the Obsidian forums. Workarounds There are a several solutions to this problem.

  1. YAML-based dates One can include a cdate (or similar) field in the note’s front matter and just direct the Dataview query against that, e.

Changing the file creation date on macOS

If you modify a file in-place using sed with the -i option, you will get a file that has a new file creation date. On macOS 13.3.1, this is absolutely 100% true, although you will read claims otherwise. I ran into this problem while implementing a Hazel rule that updates YAML automatically in my Obsidian notes. Background I have use YAML frontmatter in my Obsidian notes. It looks like: —uid:20221120152124aliases:[20221120152124,AllAboutShell]cdate:2022-11-2015:21mdate:2023-05-1805:14type:zettel— My goal is to update the mdate field whenever the file changes.

Flatten airports in X-Plane

Some airports in X-Plane have terrain issues that can be quite entertaining. This Delta 737-800 got lost in the maze of cargo ramps at PANC and was trying to taxi back to the terminal when it encountered a steep icy taxiway. It required 65% N1 just to get up the slope. Clearly a fix is required. It turns out to be quite simple. In the global airports file apt.

Hazel deletes custom file icons, and a workaround

I use Hazel extensively for automating file management tasks on my macOS systems. Recently I found that Hazel aggressively matches an invisible system file that appears whenever you use a custom file or folder icon. I’ll describe the problem and present a workaround. In a handful of directories, I have a rule that prevents users (me) from adding certain file types. So the rule just matches any file that is not an image, for example, and deletes it.

AwesomeTTS Anki add-on: Use Amazon Polly

As its name implies, the AwesomeTTS Anki add-on is awesome. It’s nearly indispensable for language learners. You can use it in one of two ways: Subscribe on your own to the text-to-speech services that you plan to use and add those credentials to AwesomeTTS. (à la carte) Subscribe to the AwesomeTTS+ service and gain access to these services. (prix fixe) Because I had already subscribed to Google and Azure TTS before AwesomeTTS+ came on the scene, there was no reason for me to pay for the comprehensive prix fixe option.