Assembler code

Gentlefolk,

Using winXP-SP3, Arduino 22. Aurdino Mini pro (328P) at 16MH.

I have a need for an accurate time delay, something more than a few NOPS so I have a LDI DEC BRNE loop.

Read the documents, assembler code (at the Arduino level) compiles clean.

I have the following

DigitalWrite(9, HIGH)
ASM(..Delay Code..)
DigitalWrite(9, LOW)

The code executes (I can see pin 9 go up and down).

The trouble is that the pulse I see on pin 9 is extremely short. Changing the count in the delay code has no effect.
Change the code to a sequence of NOPs, no change, pulse delay/time is the same.

Put a delayMicroSecond(?) before the second DigitalWrite and the pulse delay/time is increased.

It would appear that the ASM code is not being executed.

Any ideas, suggestions?
Can anyone tell me how I can get an assembler listing from the sketch compile so I can perhaps work out what is going on?

Thanks, Ian.

You need to post your real code, not what you remember of it.

Here is the code.....

for (ctr = 0; ctr < MaxPulse; ctr++)
{
// Assumption, PulsePin = LOW on entry
// Duration of pulse: At clock of 16MB we need 200 clocks to generate a 40K signal
// Each half cycle is 12.5 Usec, sort of......

digitalWrite(9, HIGH); // (PulsePin, HIGH);

// Debug - nops only.... or the following loop code
asm("nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
::);

asm(
"ldi r0,%0" "\n\t" // copy LoopCount to r0
"L_loop%=:" "\n\t"
"dec r0" "\n\t" // decrement
"breq L_loop%=" "\n\t"
: "+d" (LoopCount));

// delayMicroseconds(10); // For debug purposes
digitalWriteFast(9, LOW); //PulsePin, LOW);
}

Now post it properly in a code box, using the # icon on the editor's toolbar.
Post ALL of the code.

iru:
Can anyone tell me how I can get an assembler listing from the sketch compile so I can perhaps work out what is going on?

Hold Shift, click the Verify button (top left). That will give you the location of the .elf file (last few lines).

Then type:

avr-objdump -S  <that file> > foo.txt

Then edit foo.txt. You'll see what got generated.

digitalWrite(9, HIGH); // (PulsePin, HIGH);
   
    // Debug - nops only.... or the following loop code
    asm("nop" "\n\t"
           "nop" "\n\t" 
           "nop" "\n\t"
             "nop" "\n\t"
           "nop" "\n\t" 
           "nop" "\n\t"
           "nop" "\n\t"
           "nop" "\n\t" 
           "nop" "\n\t"                   
        :smiley;

    asm(
        "ldi r0,%0"    "\n\t"  // copy LoopCount to r0
        "L_loop%=:"    "\n\t"
           "dec r0"    "\n\t"  // decrement         
           "breq L_loop%=" "\n\t"   
        :  "+d" (LoopCount));

      // delayMicroseconds(10); // For debug purposes
    digitalWriteFast(9, LOW); //PulsePin, LOW);

You're using a really slow function to turn the pin of and off, and then trying to diddle for a new nanoseconds between the calls, and see a noticeable delay? On an oscilloscope, I hope. I don't think that the smiley helps...

iru:
I have a need for an accurate time delay, something more than a few NOPS so I have a LDI DEC BRNE loop.

Can you be a tiny bit more specific? What time delay, and how accurate?

The trouble is that the pulse I see on pin 9 is extremely short.

How short? In microseconds.

The delayMicroseconds code basically has a subtraction and a test in it. How is your code going to improve on that?

Gentlefolk,

Thank you for the responses.

The smiley was not my doing, it apprears to be an artifact of the code and perhaps not inputting the code as "code".

I have an old but good osciliscope with two channels. Can see things down to nanosec.

I have managed to access the assembler code. Looks ugly but hopefully it will be a learning experience and I will benefit from grinding my way through it.

I note a couple of responses while inputting this so....

I need a delay of 12.5 U-sec.
The DEC-BRNE loop is 3 instruction times.
(1+2( dec, brne))*(1000000/16000000) = 0.1875 u-sec per loop.
For 12.5 u-sec the loop count is 67 (rounded).

I see around 1.5 u-sec on the osciliscope with only the dec-brne ASM code . Same if i include all the NOPS.

I include the assembler code around that area. I have not examined it in detail, yet.

Thanks, Ian, Melbourne Australia.

[void PulseIt(int MaxPulse)
 24a:	20 e0       	ldi	r18, 0x00	; 0
 24c:	30 e0       	ldi	r19, 0x00	; 0
 24e:	03 c0       	rjmp	.+6      	; 0x256 <_Z7PulseIti+0xc>
        "L_loop%=:"  "\n\t"
           "dec r0    \n\t"  // decrement   
           "brne L_loop%=" "\n\t"   
        :  "+r" (LoopCount)); 

    digitalWriteFast(PulsePin, LOW); 
 250:	29 98       	cbi	0x05, 1	; 5
  
  int ctr;
  // Send 'MaxPulses' to the transducers.
  // Left = LOW

  for (ctr = 0; ctr < MaxPulse; ctr++)
 252:	2f 5f       	subi	r18, 0xFF	; 255
 254:	3f 4f       	sbci	r19, 0xFF	; 255
 256:	28 17       	cp	r18, r24
 258:	39 07       	cpc	r19, r25
 25a:	d4 f3       	brlt	.-12     	; 0x250 <_Z7PulseIti+0x6>
        "L_loop%=:" "\n\t"
           "dec r0    \n\t"  // increment   
           "brne L_loop%=" "\n\t"   
        :  "+r" (LoopCount)); 
  }
}/code]

Gentlefolk,

If someone can tell me how to attach a file I will upload the entire assembler code file.

A quick look at the code I uploaded appears to indicate that the ASM code was not assembled!

Ian

Maybe "asm volatile" rather than "asm" seems to be what most people do.

Thanks for the response,

You may have it!

Just added volatile and re-compiled.
Code looks different.

Unfortunately I have to work today, will check code and operation of things tonight.

Ian

@iru

I try to use in-line assembly in this tread that I posted. Check http://arduino.cc/forum/index.php/topic,72626.0.html

My example in my post is to make two pulse and a delay ( the looping delay ), it work but I did not kow how to use JMP , a Forum member help me out to use JMP. I use while (1==1) to loop faster not throught void loop(). ( take too long )

I hope it help... I am still learning

Gentlefolk,

Thank all of you for the responses and the interest.

The problem was the lack of VOLATILE on the ASM statement. It would appear that without the volatile my code was optimised out.

Add the volatile, recompile, re-load the 328. The ASM code looks good and I can control the pulse width/s by changing the value fed into the DEC-BRNE loop/s.

Looing at assembler code can sometimes be informative......

I had attempted to use the "digitalWriteFast(PulsePin, HIGH)" to set the PulsePin high and reduce overheads. This did not work, the code is

256: 85 b1 in r24, 0x05 ; 5
258: 82 60 ori r24, 0x02 ; 2

Woops, nothing set back into the port. Something else to chase....

However, I am progressing, once again thanks to all, Ian.

Just a postscript,

Chased up the bad code on the "digitalWriteFast" via a search on the forum. There is the problem and a solution.

Wonderful thing the Internet and forms......

Ian