-->
Page 1 of 4

Is there any alternative to OS_delay_us()?

PostPosted: Fri Aug 21, 2015 6:45 am
by sean_intez
Hi Folks,

I need to use OS_delay_us(9000) almost 30-40 times a second. This works fine but causes the WiFi to disconnect and esp8266 to reset.
I tried to use timers but they are not precise enough.
There was something like hw_timer() mentioned in the programming guide but I could not find any reference to it! does anyone know anything about it? or is there any other way to this?

Re: Is there any alternative to OS_delay_us()?

PostPosted: Fri Aug 21, 2015 6:05 pm
by pvvx
Code: Select all 
typedef void (* tfunc_tsk)(void *);
typedef struct _sargc_tsk
{
   uint32 x1;
   uint32 x2;
}sargc_tsk;

typedef struct _ss_task{
   tfunc_tsk func;      //+0
   sargc_tsk * argc;   //+4
   uint8 size;         //+8
   uint8 ch_09;      //+9
   uint8 cnts;         //+10
   uint8 cnte;         //+11
   uint32 bitn;      //+12
}ss_task;

/* Add eagle.rom.addr.v6.ld:
PROVIDE ( ets_bit_task_priority = 0x3FFFC6FC );
PROVIDE ( ets_idle_cb = 0x3FFFDAB0 );
PROVIDE ( ets_idle_arg = 0x3FFFDAB4 );
PROVIDE ( ets_bit_count_task = 0x3FFFDAB8 );
PROVIDE ( ets_tab_task = 0x3FFFDAC0 );
*/
// RAM_BIOS:3FFFC6FC 
extern uint8 ets_bit_task_priority;
// RAM_BIOS:3FFFDAB0
extern tfunc_tsk ets_idle_cb;
// RAM_BIOS:3FFFDAB4
extern void * ets_idle_arg;
// RAM_BIOS:3FFFDAB8
extern uint32 ets_bit_count_task;
// RAM_BIOS:3FFFDAC0
extern ss_task ets_tab_task[32]; // 512 bytes, 32x16

extern uint32 phy_get_mactime(void);

uint32 tt;
volatile uint32 ets_run_ret;

void  ets_run_new(void)
{
   uint8 bnum;
   uint8 bctp = ets_bit_task_priority = 0;
   while(1) {
      while(1) {
         ets_intr_lock();
         bnum = ets_bit_count_task;
         asm volatile ("nsau %0, %1;" :"=r"(bnum) : "r"(bnum)); // Normalization Shift Amount Unsigned
         bnum = 32 - bnum;
         if(bctp < bnum) break;
         if(SPI0_CTRL & SPI_ENABLE_AHB) {
            if(ets_idle_cb != NULL) ets_idle_cb(ets_idle_arg);
            else if(ets_run_ret) {
               ets_run_ret = 0;
               ets_intr_unlock();
               return;
            }
         }
         asm volatile ("waiti 0;"); // Wait for Interrupt
         ets_intr_unlock();
      };
      ss_task * cur_task = &ets_tab_task[bnum-1];
      sargc_tsk * argc = &cur_task->argc[cur_task->cnts++];
      if(cur_task->size == cur_task->cnts) cur_task->cnts = 0;
      if(--cur_task->cnte == 0) {
         ets_bit_count_task &= ~cur_task->bitn;
      }
      ets_bit_task_priority = bnum;
      ets_intr_unlock();
      cur_task->func(argc);
      ets_bit_task_priority = bctp;
   };
}

void delay_wait_cb(void *px)
{
   tt = phy_get_mactime();
   ets_run_ret = 1;
}

void task_delay_us(uint32 us)
{
   if(us < 512) ets_delay_us(us);
   else   {
      ETSTimer delay_timer;
      ets_timer_disarm(&delay_timer);
      ets_timer_setfn(&delay_timer, (ETSTimerFunc *)(delay_wait_cb), NULL);
      ets_timer_arm_new(&delay_timer, us - 128, 0, 0);
      ets_run_new();
   }
}

void run_sdk_tasks(void)
{
   uint32 t = phy_get_mactime();
   if(t-tt > 20480) {
      ETSTimer delay_timer;
      ets_timer_disarm(&delay_timer);
      ets_timer_setfn(&delay_timer, (ETSTimerFunc *)(delay_wait_cb), NULL);
      ets_timer_arm_new(&delay_timer, 1024, 0, 0);
      ets_run_new();
               tt=t;
   }
}


while(1) { os_delay_us(x); run_sdk_tasks(); } :D

task_delay_us(1000000) - No WDT, work WiFi ...

NMI -> https://github.com/pvvx/MinEspSDKLib/bl ... -vectors.c

Re: Is there any alternative to OS_delay_us()?

PostPosted: Sat Aug 22, 2015 6:33 am
by eriksl
What do you need the precise timer for?

os_delay_timer is just as (in)accurate as the timer.

I think the appropriate approach is:

- find out what is the max deviation of the sdk timer against accurate "wall clock"
- double this value, to be sure, subtract this value from the time you want to wait and create a timer for this period
- when the timer fires and your callback function is called, run a busy loop that counts the cpu cycles (there is a special command for that, or you may want to use the system time api call, I guess it gives the same value, this timer IS accurate).
- the busy loop should only run for a very short timespan, I guess it will boil down to a few microseconds, maybe even nanoseconds.

With this approach you won't starve the wlan system nor the watchdog and only keep the cpu busy when necessary.

Re: Is there any alternative to OS_delay_us()?

PostPosted: Tue Aug 25, 2015 7:02 am
by sean_intez
Thanks guys. Neither work. I have esphttpd running on my esp8266. and no matter what, it disconnects when I try to retrieve /access a webpage while the interrupt is getting triggered constantly.

I am trying to work with a AC dimmer. here is the AC module I have purchased.
http://www.inmojo.com/store/inmojo-mark ... -lite-v.2/

So it basically triggers the interrupt 50 times a second.
so this code executes 50 times a second.
Code: Select all  delayMicroseconds(7000);    // Off cycle
  digitalWrite(pin_no4, HIGH);   // triac firing
  delayMicroseconds(10);   // triac On propogation delay
  digitalWrite(pin_no4, LOW);    // triac Off


I replaced the delay function by a while loop to make the cpu busy for 7000 us. It works, but ESP restarts as soon as I try to access any web pages stored in it.