The esp8266 run loop and messaging

The basic esp8266 examples have the following basic format:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Main code function
static void ICACHE_FLASH_ATTR loop(os_event_t *events) {
 
  // DO STUFF
 
  os_delay_us(100);
  system_os_post(user_procTaskPrio, 0, 0 );
}
 
//Init function
void ICACHE_FLASH_ATTR user_init() {
 
  // init system
 
  //Start os task
  system_os_task(loop, user_procTaskPrio,user_procTaskQueue, user_procTaskQueueLen);
  system_os_post(user_procTaskPrio, 0, 0 );
}

The support libraries appear to manage a message queuing system, system_os_task adds a new task type, with a given priority and sets it’s callback function. Tasks are then fired by sending them messages with system_os_post. I would guess that they have scheduler which waits for messages to be posted and schedules them appropriately. The basic examples provided create a single task, with the call back of “loop”. “loop” then sends itself a message at exit, insuring it is queued to be called again at some point in the future.

I would guess they also use the same system to schedule various internal processes, and that if “loop” never returns your going to have a bad time.

You can also use the messaging system for your own purposes, for example in my previous uart example, rather than busy waiting for input you can post a message for the uart ISR directly i.e.:

user_main.c:
//Main code function
static void ICACHE_FLASH_ATTR loop(os_event_t *events) {

  int c = uart0_rx_one_char();

  if(c != -1) {
   uart_tx_one_char(c);
  }
}

uart.c:
LOCAL void uart0_rx_intr_handler(void *para) {

...

   system_os_post(user_procTaskPrio, 0, 0 );
}

And loop will still regularly get called when there’s new data. I’d be slightly careful here, as the documentation is incomplete and there may be issues I’m unaware of. A modified version of that UART example I previously posted using modified to use this messaging method can be downloaded here:uart_test_messaging.tar

This is a continuation of my notes on the esp8266 microcontroller, you can find a complete list of my esp8266 posts here

6 Comments

  1. I’m kind of confused by this… I have the manual and I’m still no further forward. So I can see how you might send a message – say from the UART and loop gets called when the system has a free spot.. but.. is this set-up only capable of creating one of these callbacks? I ask because system_OS_post does not seem to pass the address or a reference to “loop”.

  2. That delay also seems pointless.. if this is something that runs in the background, then the delay is just causing 100us dead spot.. for example if you’re running WIFI and, say MQTT I am assuming that the MQTT code cannot be checking anything incoming while you’re in that delay… of course I could be completely wrong.

  3. new299 says:

    The delay largely is pointless, but IIRC the SDK examples use it as a way of enforcing a delay between loop calls. It’s kind of a lazy timer.

    Interrupts aren’t masked however, so you should be able to receive Wifi packets during the delay. Werther the user code will be called or not I don’t know. I don’t think it’s called by the ISR so packets might be buffered until the loop exits.

  4. new299 says:

    My understanding is you can register multiple tasks with system_os_task. They will all get scheduled to run when you call system_os_post. In order for a task to run you need to call system_os_post periodically. This could be in a timer, or as above a task can reschedule itself to run on exit.

  5. Mike Kulasinski says:

    To be honest I can’t get anything working on the esp8266, I followed all the examples and what I get is a lot of weird characters that makes no sense. I have tried multiple baud rates and other options. I can only see one human readable string which is MEM CHECK FAIL!!! I am on the newest sdk which is 1.0.1b. Could you please help me

  6. Stan says:

    I have got the same problem. I have solved it by adding following line at the beginning of the user_init function:

    uart_div_modify(0,UART_CLK_FREQ / 115200);

    Now set baud rate to 115200.

Leave a Reply