Ask Larry

Practical Rabbit Timing Information

This morning I answered an email from an engineer who was puzzled by the width of a fast pulse being generated by the RCM5700. He had a very tight set of five assembly language statements which should have produced a pulse approximately 200ns wide. Here is the code:

  ld HL, PADR ; address of Port A
  Ipset 3 ; turn off interrupts
Ioi set 0, (HL) ; turn on bit 0
Ioi res 0, (HL) ; turn off bit 0
  ipres   ; back to normal processor priority

Looking up this version of the set instruction shows that it should take 10 CPU clock cycles. Here is the break-down of the set instruction timing without the loi prefix:

  • Four clocks to read the two bytes of the instruction
  • Two clocks to read the contents of the memory location (HL)
  • One clock to modify the value
  • Three clocks to write the value back to the memory location (HL)

The loi prefix takes two clock cycles to read. However, the total execution time will only be eleven clocks because the internal I/O register can be written in two clocks as opposed to the three it takes to write to memory.

Since the RCM5700 uses a 50MHz clock (a 20ns period) this set of instructions should produce a pulse width of 11*20ns, or 220ns. His measured pulse width was 460ns.

Why is there such a large difference? The reason is that the RCM5700 executes its program out of flash memory which has a 70ns access time. Looking up the contents of the appropriate Memory Bank Control Register (MB0CR) shows that it is set for four wait states. This means that EVERY byte read from the flash takes an additional four clock cycles. Since the instruction is three bytes long this is an additional twelve clocks which takes the total number of clocks to 23 which then takes the execution time to 23*20 = 460ns.

I have attached a short program which prints a number of memory parameters of any rabbit system. These values can be used to determine exactly how fast the Rabbit is actually executing its instructions.

However, this data cannot easily be used to determine how fast C statements can be executed. The easiest way to do that is to use MS_TIMER surrounding a loop as shown here to measure the time of a WrPortI instruction:

unsigned long eTime0, eTime1; // elapsed time values
long k; // loop counter
int SomeValue;  
float ExecutionTIme;  
 
eTime0 = MS_TIMER; // get start time
for (k=1; k<=100000; k++ );  
eTime0 = MS_TIMER - eTime0; // time to execute for loop
 
eTime1 = MS_TIMER; // get start time
for (k=1; k<=100000; k++ ) WrPortI ( PADR, &PADRShadow, SomeValue );
eTime1 = MS_TIMER - eTime1; // time to execute for loop + WrPortI
 
eTime1 = eTime1 - eTime0; // eTime1 = time to execute WrPortI 10000 times
ExecutionTIme = (float)eTime1/100.0; // actual WrPortI execution time in microseconds
; // for breakpoint

For an RCM5710, this came to 1.998us for this WrPortI. This time is affected slightly due to the processor being connected to the Dynamic C debugging environment but it should be very close. If you need more accurate results you could disconnect from the programming port and send the data out a serial port to another device.

Keep in mind that the time calculated is for this particular implementation of the WrPortI – a change in any of the three parameters types will cause a change in the time.

- Larry C.

Larry Cicchinelli is Rabbit’s Technical Support Manager. He has 30 years of embedded experience, and is considered one of the foremost authorities on Rabbit products. Larry and his staff offer comprehensive technical support to Rabbit customers.

Download program

Submit your questions for Larry via email at AskLarry@rabbit.com

Read more Ask Larry Answers