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
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”.
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.
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.
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.
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
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.