• 0

Chipkit Max32 Delay Functions


EigenFunctions

Question

I did a great deal of web searching to find a decent delay function for timing and found a few (though I don't understand why it's not provided in a standard library). It was also important to me to understand how it works. So the following is what I came up with.

 

The PIC32mx795F512L uC (on the ChipKit Max32 Arduino board) has a core timer feature. The timer is clocked every two system clocks (SYSCLK) and has two associated 32-bit registers (Count and Compare). This discussion is limited to simple uses of the core timer, so I won't cover the Compare register or interrupts. Given a clock speed of 80MHz, the timing resolution is 10^9/((80*10^6)/2) = 25nS/count. Notice that the core timer feature has nothing to do with the peripheral clock. When the count gets to the maximum (i.e., 0xFFFF_FFFF), the register simply rolls over to zero and starts counting again. At a 25nS clock rate (80MHz clock frequency), the register rolls over every 107 seconds (25nS*[2^32-1] = 107 seconds or 1 minute, 47 seconds). There is a function that reads the core timer count register  - ReadCoreTimer(). This function returns the instantaneous value of the counter when called. There are other associated core timer routines that are not discussed here.

 

Given all that, here are two functions, one to delay in milliseconds and another to delay in microseconds:

 

First a few header definitions:

:
:

#define                         SYS_FREQ (80000000L)


//              Note- the CPU Core timer is always half the processor clock rate
#define             COUNTS_PER_MICRO_SEC ((SYS_FREQ/2L)/1000000L)
#define             COUNTS_PER_MILLI_SEC ((SYS_FREQ/2L)/1000L)

// --------------------------------------------------------- Function prototypes
void Delay_uS(unsigned int ReqDelay);
void Delay_mS(unsigned int ReqDelay);


:
:

The actual functions:

#include <plib.h>

:
:

// _____________________________________________________________________________
void Delay_uS(unsigned int ReqDelay) {
  unsigned int Finish;
  unsigned int EntryCount = ReadCoreTimer();


  ReqDelay *= COUNTS_PER_MICRO_SEC;
  Finish    = EntryCount + ReqDelay;
  if (Finish >= EntryCount) {                      // Normal Case
      while (ReadCoreTimer() < Finish);
      }
    else {                                         //  Roll-over will happen
      while (ReadCoreTimer() > EntryCount);        //   Wait for roll-over
      while (ReadCoreTimer() > Finish);            //    Remainder of wait
      }


 }


// _____________________________________________________________________________
void Delay_mS(unsigned int ReqDelay) {
  unsigned int Finish;
  unsigned int EntryCount = ReadCoreTimer();


  ReqDelay *= COUNTS_PER_MILLI_SEC;
  Finish    = EntryCount + ReqDelay;
  if (Finish >= EntryCount) {                      // Normal Case
      while (ReadCoreTimer() < Finish);
      }
    else {                                         //  Roll-over will happen
      while (ReadCoreTimer() > EntryCount);        //   Wait for roll-over
      while (ReadCoreTimer() < Finish);            //    Remainder of wait
      }


 }

:
:

A few comments:

  • The two routines use the function ReadCoreTimer() from the plib library. There is a companion WriteCoreTimer() function, but it is not needed in this case and best not used.
  • In all the XC32 documentation, they say plib.h will go away, but it is not at all clear what will replace it or what to use in the mean time. So I will use it until I find a replacement.
  • Notice that the function parameter is modified within the routine. The functions are NOT portable to other uC, so for the PIC32 parameter passing scheme, this will not cause a problem.
  • If the parameter passed is zero (it is unsigned, so it can't be negative), the result will be the shortest possible delay.
  • The routines take into account the case when the timer register rolls-over which gives better timing over all. I did not yet get a chance to look at it with a scope, but I believe it should be correct.

I struggled to find these routines, so I hope they are useful to others.

 

Thanks,

  EigenFunctions

 

 

Link to comment
Share on other sites

1 answer to this question

Recommended Posts

Archived

This topic is now archived and is closed to further replies.