chipKIT® Development Platform

Inspired by Arduino™

Strange behaviour while bit flipping I/O pin

Created Fri, 27 Apr 2012 09:49:46 +0000 by Materie62


Materie62

Fri, 27 Apr 2012 09:49:46 +0000

I recently bought a UNO32 because I found out that the Arduino UNO board was too slow for my application. Trying to find out what the maximum I/O flipping speed is I stumbled on an artifact that I can’t explain. The program I wrote is very simple,

void setup() { } void loop() { while(true) } Measuring on pin 13 (RG6, J5 pin 11) I see on an oscilloscope the picture http://www.alyda.nl/Download/UNO32/1.JPG With the above program I would expect an almost 50% duty cycle, with the low period somewhat longer because of the while loop. But not the pattern given in picture 1.JPG. I also noticed some oscilloscope trigger problems. On a longer time scale I found out why (see http://www.alyda.nl/Download/UNO32/2.JPG). I appears that pin 13 becomes low for 1.7 us every 1 ms. The strange pattern given in picture 1.JPG disappears when including an extra LATGSET line.

void setup() { } void loop() { while(true) }

Then on the oscilloscope the signal given in http://www.alyda.nl/Download/UNO32/3.JPG can be measured. Which looks ok, 25ns high and 37ns low. However also with this code the 1 ms repetition appears. Could someone confirm and explain what I’m seeing here? The measured patterns do not change if the UNO32 is connected or disconnected to a USB port. The UNO32 is powered by an external power supply. Suggestions are welcome.


Ryan K

Fri, 27 Apr 2012 11:46:32 +0000

Hello,

Wanna try this?

void setup(){
TRISGCLR = (1 << 6);
}

void loop(){
while(1){
LATGINV = (1 << 6);
}
}

Let me know if you get anything different.

Best Regards, Ryan K Digilent


Materie62

Fri, 27 Apr 2012 12:29:14 +0000

Hi Ryan,

have a look at http://www.alyda.nl/Download/UNO32/4.JPG for the result. I understand your code but I can't explain why the duty cycle of your code isn't exactly 50%. Since LATGINV inverts the bit. Also the 1 ms "heartbeat" is still in there. Can you explain my previous questions and why the signal in figure 4.JPG doesn't have a duty cycle of 50%?

Regards

PS is there a possiblity to view the mnemonics code from the MPIDE compiler?


Ryan K

Sat, 28 Apr 2012 00:49:00 +0000

Hello,

If I just remove the while loop in the loop function it seems to work fine. I get a 50% duty cycle signal at 5 MHz. I'm not quite sure why that behavior occurs... As for the heartbeat you are getting I'm not sure what is causing that, I haven't been able to replicate it here. Hopefully removing the while loop also solves that problem for you. As for the MPIDE compiler, it uses the same compiler as the one for MPLAB so you will have to look that up, I'm not sure if that information is released.

Best Regards, Ryan K Digilent


Materie62

Sun, 29 Apr 2012 12:12:14 +0000

Hi,

removing the while loop around the LATGINV = (1 << 6) line indeed gives a duty cycle of more or less than 50% (90 ns high and 110 ns low, equal to a freq. of 5MHz). But using the while loop speeds up things dramatically (15 ns low and 38 ns high, equal to approx.20MHz). Also I don't have a clue why this happens and why the duty cycle is not 50% when using the while loop. The heartbeat is still there. I used an oscilloscope with a sampling speed of 400MS/s and 0.5MB of storage memory. Using these settings I could store more than 1 ms of signal and detect the heartbeat. I think the heartbeat is caused by the PIC32M USB On-The-Go interface (see register 11-2, U1OTGIE). I could check if the heartbeat disappears disabling the T1MSECIE bit but I’m afraid that I brick the UNO32. I’m not sure if the bootloader program always returns to its default settings after a reboot. If the PIC32M USB On-The-Go interface is causing this heartbeat then I think this is a hidden “feature”. Since I’m not using the PIC32M USB On-The-Go interface it should not be enabled unless you use let’s say “Serial.begin”. Also my initial question is still open (why the strange bit flipping pattern using the program given in the first post).

Regards.


WestfW

Tue, 01 May 2012 04:59:11 +0000

When I did tests with "direct port io", I recall that the compiler would partially unroll my while loop. I never did figure out exactly why.

The heartbeat is almost certainly the 1ms timer interrupt. It's not that the pin goes low, but the loop pauses with the pin in whichever state it was in.


Materie62

Tue, 01 May 2012 14:50:00 +0000

@WestfW, Yes, I agree the loop is halted/paused for 1.7us. Apperently this is the time needed to deal with the timer interrupt. Do you believe this is the USB On-To-Go timer?

Is there another compiler available then the MPIDE? Seems to me that the MPIDE is a bit too clever.....


EmbeddedMan

Tue, 01 May 2012 19:10:07 +0000

There are no interrupts used for USB OTG, I do not believe.

The 1ms 'heartbeat' is the 1ms system tick timer, implemented using the Core Timer. It has nothing to do with USB.

Unless you use a library that has a USB stack, or you build for a board that uses the USB as its Serial device (which you have to select in the boards list), the code MPIDE code does nothing with the USB hardware. Completely ignores it.

*Brian


Demolishun

Sun, 03 Jun 2012 00:37:58 +0000

Try writing your while loop in assembler.


EmbeddedMan

Mon, 04 Jun 2012 13:30:45 +0000

The reason the original code did not produce 50% duty cycle is because the processor needs to do the loop construct.

In Basic, it would look like this:

LoopCounter = 1000

LoopTop: SETBIT CLEARBIT LoopCounter = LoopCounter - 1 IF LoopCounter <> 0 THEN GOTO LoopTop

So there is 'code' that needs to run every time through the loop. That code takes time. And that's why you don't get 50% duty cycle.

If you did this

LATGSET = B01000000; LATGCLR = B01000000; LATGSET = B01000000; LATGCLR = B01000000; LATGSET = B01000000; LATGCLR = B01000000; LATGSET = B01000000; LATGCLR = B01000000;

Then you'd have 50% duty cycle for 4 cycles of the waveform. But you need to loop back around eventually if you want it to run forever, and thus there will be a 'break' in the 50% waveform as the loop construct code runs.

If you remove the while() with the bit-invert code it gives you approximately 50% duty cycle, but far slower, because the loop() function is returning, all of the core MPIDE code is running, then loop() gets called again, over and over.

Make sense?

Writing in assembler won't help - you still need to do the loop and thus can't have exactly 50% duty cycle at that speed. Now, if you go a bit slower, it's possible to get exactly 50% duty cycle . . .

*Brian