Author Topic: Adding a delay without using a task  (Read 6471 times)

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Adding a delay without using a task
« on: October 09, 2017, 04:01:50 PM »
Hi Mark,
  I wish to have a function to simply have a delay before jumping to the next line. I have the below for adding a milli or micro second delay. How many channels in the timer are there used by utasker? Im using channel 1 , but dont know if there are others available.

Below I call the Delayms(.) for a delay, do you see any issues doing this?

Regards
Neil


volatile char DelayTimeout;
void Delayms(int Delay)
{
    DelayTimeout=0;
    SetOneShotTimerG2(Delay,1);
    while(!DelayTimeout)
      ;
}

void G2TimerProcedure(void)
{
  DelayTimeout=1;
}
 
void SetOneShotTimerG2(int Tme,char IsMS)
{
   DMA_TIMER_SETUP timer_setup;
   timer_setup.int_type = DMA_TIMER_INTERRUPT;                       
   timer_setup.channel = 1;          // timer channel
   timer_setup.int_priority = DMA_TIMER1_INTERRUPT_PRIORITY;
   timer_setup.int_handler = G2TimerProcedure;                // enter timer call-back
   timer_setup.mode = (DMA_TIMER_INTERNAL_CLOCK | DMA_TIMER_SINGLE_SHOT_INTERRUPT);
   if(IsMS)
    timer_setup.count_delay = DMA_TIMER_MS_DELAY(1,1,Tme);   
   else
    timer_setup.count_delay = DMA_TIMER_US_DELAY(1,1,Tme);   
   
   fnConfigureInterrupt((void *)&timer_setup);    
}
« Last Edit: October 09, 2017, 04:09:14 PM by neil »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Adding a delay without using a task
« Reply #1 on: October 09, 2017, 04:53:13 PM »
Hi Neil

If TEST_DMA_TIMER is not enabled in ADC_Timers.h there are no DMA timers being used by uTasker. The Tick comes from PIT0 and the performance monitor (MONITOR_PERFORMANCE) used PIT1, if enabled.

Beware that if you have a long delay the watchdog may fire since no (other) tasks will be scheduled. Interrupts will still be serviced during the wait.

For long waits you can start the timer and return from the task. When the interrupt fires, send an event (usually INTERRUPT_EVENT type) to the task so that it can pick up from where it left off.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Adding a delay without using a task
« Reply #2 on: October 09, 2017, 04:59:37 PM »
Hi Mark
  Thanks for the reply.

I will use the event to fire when the interrupt fires in long delays. I use an external watchdog with a 3 second timeout, which is fired if there are any lock ups.  This gives me plenty of breathing space for SD card read/writes.

Thanks
Neil

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Adding a delay without using a task
« Reply #3 on: October 13, 2017, 03:10:45 PM »
Hi Mark,
  The delay above works well until one point where the interrupt never gets called. I have an interrupt that is captured on the rising edge. And within this interrupt I send an I2C command and have a 10ms delay, but the timer interrupt never gets called.  Here is the code for capturing the rising edge.

GPTIMER_SETUP gptimer_setup; 
 
  gptimer_setup.int_type = GPT_TIMER_INTERRUPT;
    gptimer_setup.int_handler = DCDPulse_int;
    gptimer_setup.channel = 1;                                           // general purpose timer channel 1
    gptimer_setup.int_priority = GPTIMER0_INTERRUPT_PRIORITY;            // define interrupt priority
    gptimer_setup.mode = GPT_CAPTURE_RISING_EDGE; // set up capture mode and define the timer clock
    gptimer_setup.usCaptureCount = 0;                         // request this many capture values to be recorded before calling our interrupt
    gptimer_setup.capture_list = 0;                          // the capture list for saving to

   fnConfigureInterrupt((void *)&gptimer_setup);                       

I am using GPT0 , and GPT1 (MCF52559) as input captures.  I assume the above doesnt use any DMA timers?

Would I be correct in saying that a DMA timer , as above, cant be called withing a timer interrupt as above?

I have checked TEST_DMA_TIMER and its not enabled, but I couldnt find MONITOR_PERFORMANCE.

How many DMA timers can I use , and is not used by the system?


Many Thanks
Neil
« Last Edit: October 13, 2017, 03:15:26 PM by neil »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Adding a delay without using a task
« Reply #4 on: October 13, 2017, 09:40:57 PM »
Neil

All DMA timers should be available to you.
I am not aware of a restriction to using these from within interrupt routines.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Adding a delay without using a task
« Reply #5 on: October 14, 2017, 07:06:19 AM »
Hi Mark
  I just checked and and can confirm that within a pulse input routine (DCDPulse_int above) I called the delay function, and the timeout routine never gets called.

Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Adding a delay without using a task
« Reply #6 on: October 14, 2017, 02:22:59 PM »
Neil

If the DMA timeout interrupt never gets called can you identify one of the following possible explanations?
1. The DMA timer never runs?
2. The DMA timer times out but its interrupt doesn't fire?
3. The DMA tiers' interrupt fires but the callback never gets called?

Also, do you leave the DCDPulse_int() interrupt or do you wait in it for the DMA timer to fire? If you wait, beware that interrupts will be globally disabled until it returns and so wouldn't let the DMA interrupt be executed (although it will be pending). To overcome this you could poll the DMA interrupt flag instead. Or you can enable interrupts explicitly while in the first IRQ so that t can be interrupted by another.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Adding a delay without using a task
« Reply #7 on: October 14, 2017, 03:16:14 PM »
Hi Mark
  Thanks for the reply. I don’t exit the interupt while in the DCD_int(). I think I will poll the register . When setting up the interupt I set the callback , do I simply put NULL, or an empty callback function? What register do I poll ?

Regards
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Adding a delay without using a task
« Reply #8 on: October 16, 2017, 11:21:14 AM »
Hi Neil

When the timer fires you should see the DMA_TIM_EVENT_REF flag being set in DTERn.

I checked the DMA timer driver and it requires a user interrupt handler to be set - if it is NULL it will return without starting the timer.

In case you prefer to not have to add a handler you could this code:

                        if (ptrDMA_timer_settings->int_handler == 0) {   // a handler must be supplied
                            return;
                        }



Also change
        iInterruptLevel = 1;
        dma_timer_handler[1]();
        iInterruptLevel = 0;


to

    if (dma_timer_handler[1] != 0) {
        iInterruptLevel = 1;
            dma_timer_handler[1]();
        iInterruptLevel = 0;
    }


in each interrupt handler.
Note that the interrupt is still handled by the driver in order to set the DMA timer back low power mode but no user callback is needed once the interrupt could be taken.

Since the flag will be lost once the interrupt has been taken it may be best to keep a handler so that it can still be used in the other case (the handler will however be called after interrupt have been enabled again).

Regards

Mark


Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: Adding a delay without using a task
« Reply #9 on: October 20, 2017, 09:13:45 AM »
Hi Mark

  Thanks for that.

Best Regards
Neil