In my previous post I described some basic options when starting developing for the ESP8266, and also described the NON-OS SDK briefly. I have choosen not to use the NON-OS SDK mainly based on three resons:

  • ESP8266 comes with built in software and API, your application don’t “own” the hardware by itself (this is the main reason)
  • Threading can be a good tool for creating simpler code.
  • I have never used FreeRTOS, it seems more challenging and fun to explore it rather than using f.i. the Arduino IDE and just hack away.

The first reason is the most important to me, let me explain the reasoning.

Lets consider an example, you want to build a remote sensor that monitor temperature and reports it back to a central server. Using a simpler plattform to build this, when you are finished your binary will consist of your application code, some library code to use sensor and RF and a “main” binary from the arduino SDK which bootstraps the application and calls your application entry points (setup() and loop()).

The flow in the application is very simple:

  1. The CPU starts into “main” from the SDK, it initializes itself and then call your setup() function.
  2. When your setup function returns, the “main” module runs again and probably sets up a timer function, which will call your loop() function.
  3. Thats all, everything else that happens in the application are handled by your application.

When building the same solution with the ESP8266 using the NON-OS SDK, the solution whould be very similar. The only difference would be that you had to setup the timer yourself.

Ok, but why would this be a problem when using the ESP8266 and not using the Arduino?

As I see it, the problem is that your application must “share” the hardware with firmware developed by ExpressIf. The ExpressIf code is closed source, so you will never know in detail what it does, the only thing that you can be sure off is that it does some very important and time critical stuff (communicating over Wifi, e.t.c.).

When reading the documentation from ExpressIf, clearly point this out (from ESP8266 SDK programming guide by ExpressIf):


• Using non-OS SDK which is single-threaded, the CPU should not take long to execute tasks:

‣ If a task occupies the CPU too long, ESP8266 can’t feed the dog, it will cause a watchdog reset;

‣ If interrupt is disabled, CPU can only be occupied in us range and the time should not be more than 10 us; if interrupt is not disabled,  it is suggested that CPU should not be occupied more than 500 ms.

• We suggest using a timer to check periodically, if users need to call os_delay_us or function while, or function for in timer callback, please do not occupy CPU more than 10 ms.

• Using non-OS SDK, please do not call any function defined with  ICACHE_FLASH_ATTR in the interrupt handler.

• We suggest using RTOS SDK, RTOS to schedule different tasks.

In most cases it will not be a problem if guidelines from ExpressIf is taken into account, however in practical work they are not that easy to follow. For instance, you have some code that for some reason disables interrupts, how long in us does it take to execute ? Does it take less than 10us ?

I generally think it is hard to develop software according to some rules, it is much more easy to have the rules enforced by an API, and this is what you get by using the RTOS-SDK instead of the NON-OS SDK.

A really simple and stupid example (if you called someFunc from a timer it would work)

	/* using the NON-OS SDK */
	void someFunc()
		/* Do some lengthy stuff */

	void ICACHE_FLASH_ATTR user_init(void)
		/* Will cause Watch dog reset */

Call someFunc as a RTOS task, scheduler will make sure that firmware can do what it needs.

	/* using the RTOS-SDK */
	void someFunc(void *pvParameters)
		/* Do some lengthy stuff */
	void ICACHE_FLASH_ATTR user_init(void)
		/* will work just fine */
		xTaskCreate(someFunc, (const signed char *)"task", 256, NULL, 2, &t);