Zhe Hu
Zhe Hu

Reputation: 4007

pic32 fastest way to toggle DIO

I have a PIC32 configured running at 80MHz clock rate. As a test, I tried to toggle a DIO pin with

while(1) {        
    LATFbits.LATF4 = !LATFbits.LATF4;
}

It's only toggling DIO at 625kHz according to the scope. Looking at the dissembled listing

9D000118  8C446160   LW A0, 24928(V0)
9D00011C  30840010   ANDI A0, A0, 16
9D000120  2C840001   SLTIU A0, A0, 1
9D000124  8C436160   LW V1, 24928(V0)
9D000128  7C832104   INS V1, A0, 4, 1
9D00012C  AC436160   SW V1, 24928(V0)
9D000130  0B400046   J 0x9D000118

It's not that many instructions. Why is it so slow?

==============

finally get 20MHz (4 instructions) with assembly

#include<p32xxx.h>

.text
.set    noreorder
.set    nomacro

.global toggle
.ent    toggle

toggle:

# void toggle(int mask)

# $a0 - mask
# performs toggles in an infinite loop (never returns)

# la $t0, 0xbf886160  # LATF base address 04:clear 08:set 12:inv

la $t0,LATF

loop:
sw  $a0,  4($t0)        # write mask to clear 
sw  $a0,  8($t0)        # write mask to set
j loop
nop

.end toggle

Upvotes: 2

Views: 2903

Answers (3)

Marco van de Voort
Marco van de Voort

Reputation: 26376

(ds)PIC's C30 compiler has _builtin_btg() to do a bit toggle in one instruction on F devices and 2 on -E devices. See if PIC32 also has it. Probably it will only get you half way there since like the E series, afaik PIC32 isn't necessarily 1 cycle/I/O instruction.

Also using modules like output compare you might be able to reach higher speeds, if the peripheral clock of the module is higher then what the CPU can toggle (e.g. due to mem latency)

Upvotes: 0

chux
chux

Reputation: 154075

These ideas present asymmetric waveforms, but increase the number of transitions per second.

I've used a similar approach when I need a burst of high speed sampling - of course reading rather than writing.

Along with other ideas already mentioned:

while(1) {        
  LATFbits.LATF4 = 0;
  LATFbits.LATF4 = 1;
}

You could also reduce the overhead of the loop

while(1) {        
  LATFbits.LATF4 = 0;
  LATFbits.LATF4 = 1;
  LATFbits.LATF4 = 0;
  LATFbits.LATF4 = 1;
  LATFbits.LATF4 = 0;
  LATFbits.LATF4 = 1;
  ...
  LATFbits.LATF4 = 0;
  LATFbits.LATF4 = 1;
}

With a PIC24, I can configure a timer output on many DIO pins and lets the hardware generate the signal. I suspect the same can be done with PIC32.

Upvotes: 0

Beryllium
Beryllium

Reputation: 12998

Have you tried to toggle the PORT using the INV register?

In addition to the TRIS, PORT, and LAT base registers, each port
module is associated with a SET, CLR and INV register which provides
atomic bit manipulations and allowing faster I/O pin operations.

Upvotes: 1

Related Questions