What value is the PIN toggle?

Go To Last Post
40 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I was thinking that the PIN toggle was a temporary toggle, but apparently that was incorrect.  Given that it toggles the PORT pin permanently, what purpose does it have:

 

        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR
 202:    7c 9a           sbi    0x0f, 4    ; 15
        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR
 204:    7c 9a           sbi    0x0f, 4    ; 15

 

-or-

 

        PORTF&=~_BV(PORTF_WR_PIN_AL); //take wr low
 206:    8c 98           cbi    0x11, 4    ; 17
        PORTF|=_BV(PORTF_WR_PIN_AL);  //take rd back high
 208:    8c 9a           sbi    0x11, 4    ; 17

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Toggle in 1 cycle instead of a RMW?

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Given that it toggles the PORT pin permanently, what purpose does it have

How about to toggle the output pin?  You know, like, when you want toggle it, maybe flash an led

 

If it toggling not available & you had to code it yourself (as on some other micros), would you be happier?

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, given that I can set or clear a bit already using cbi/sbi on the port, the only thing pin toggle gets me is that I don't need to know the initial state.  I know, I know, I shouldn't complain about a feature.  I was hoping it would do a pulse on the pin and return to its original state.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Think of Pin Toggle like a toggle switch....its always going to be sent to the opposite state when activated, and stay there until activated again, rinse repeat.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the only thing pin toggle gets me is that I don't need to know the initial state.

 That can be a pretty significant advantage, since otherwise you're looking at four(ish) instructions instead of just one...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To use single cycle instructions sbi/cbi, as you not, you have to know the initial state.

 

But, stop for a moment and think of what that implies.

 

To know the initial state, you have to read the port.

 

That is not enough, though. You have to test the appropriate bit from that port (often involves a mask), then make a decision based on that masked port value.

 

So, now, there are 4 clock cycles, more or less.

 

Toggle goes in 1 cycle. If you only have a few instances, that does not buy you much. But, if you have several or execute a toggle in a many-pass loop, it can add up quickly. 

 

Now, we do know that you are a bit miffed that it does not do what you want. We are all faced with that little problem at some time, maybe several some times. It happens. And, its neither the first time nor the last. To make a short pulse, just toggle, then immediately toggle again. 

 

Frankly, I hardly ever use toggle, because I want those port pins to be in a totally known state, not just the opposite of what ever it happens to be at this instant. For me, that is one of the aspects of "defensive programming": rather than relying on some initial condition that might or might actually be the case, do something that results in a known state, no matter what the initial state. 

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

test the appropriate bit from that port (often involves a mask), then make a decision based on that masked port value

 

What about a XOR boy? You don't have to go steaming into the Mask/Test/Modify like a bull in a china shop.

 

(waits to see differences in cultures)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What about a XOR

But there's no XORI instruction, so you end up with
 

  ldi t1, BITMASK
  in t2, PORT
  xor t2, t1
  out PORT, T2

If you're lucky, you can use t1 more than once...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR
 202:    7c 9a           sbi    0x0f, 4    ; 15
        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR
 204:    7c 9a           sbi    0x0f, 4    ; 15

Your syntax is surely wrong?. You don't want to use OR do you ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:

I was hoping it would do a pulse on the pin and return to its original state.

 

But how would you set the pulse's width? Would you want a 1 clock-cycle width pulse? Or a 2, or a 3....

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not that this really matter for this thread but:

sbi and cbi take 2 clk  out (and in) only take 1 clk.

 

Just have that in mind if we talk about speed. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

Now, we do know that you are a bit miffed that it does not do what you want. We are all faced with that little problem at some time, maybe several some times. It happens. And, its neither the first time nor the last. To make a short pulse, just toggle, then immediately toggle again.

 

You are so right!

ka7ehk wrote:
Frankly, I hardly ever use toggle, because I want those port pins to be in a totally known state, not just the opposite of what ever it happens to be at this instant. For me, that is one of the aspects of "defensive programming": rather than relying on some initial condition that might or might actually be the case, do something that results in a known state, no matter what the initial state.

 

Exactly my point; if you are doing this anyway, then PIN toggle has no benefit as you already know its state and can SBI or CBI it in a single instruction to the opposite state.

 

clawson wrote:

        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR
 202:    7c 9a           sbi    0x0f, 4    ; 15
        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR
 204:    7c 9a           sbi    0x0f, 4    ; 15

Your syntax is surely wrong?. You don't want to use OR do you ?

 

You bring up a good point clawson, I had the OR in their by mistake.  In C this would mean take the existing value, OR this value into it, then store it, but it is optimized into a bit operation sbi instead.  When I remove the OR and do an assignment, it takes two instructions instead:

 

 112:    80 e1           ldi    r24, 0x10    ; 16
 114:    8f b9           out    0x0f, r24    ; 15

 

Brian Fairchild wrote:

But how would you set the pulse's width? Would you want a 1 clock-cycle width pulse? Or a 2, or a 3....

 

I was thinking as short as possible, something on the order of twice as fast as what sbi cbi could do would have made it interesting.

Last Edited: Tue. Mar 12, 2019 - 12:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I was thinking as short as possible, something on the order of twice as fast as what sbi cbi could do would have made it interesting.

 

Then you problem is already solved, by using = instead of |=.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I was thinking as short as possible, something on the order of twice as fast as what sbi cbi could do would have made it interesting.

Tell how that would be "interesting".  What are you doing, tickling some high-speed logic?  What kind?  If you do an SBI-CBI pair, then you get a pulse of two AVR clock cycles.  As you are on an apparent quest for speed, one would surmise that you are running at a fast AVR speed.  At 8MHz, that would be 250ns.  At 16MHz, that would be 125ns.  What is the need for something that short?

 

Using the toggle feature, the pulse width can be no shorter on an AVR8.  You tell us what the use is of the new-fangled toggle feature.  Yes, it is much less painful than the RMW sequence.

theusch wrote:

david.prentice wrote:
So why did Atmel change the SBI functionality?

???  That would seem fairly obvious to me -- to create a mechanism to modify [individual] port bit values without introducing possible RMW side effects.  Unless I'm way off.

 

It more-or-less seems to coincide with the timeline of write-to-PIN-to-toggle.  In practice that doesn't come up often, but prior it is painful to toggle an AVR8 I/O port bit.

 

theusch wrote:
[As seen, toggling an I/O port bit in classic AVR models is a painful process. With any of the IN/OUT methods there is a RMW situation where one must be aware of if working with the same poirt in an ISR. Thus, Atmel gave us the PINx write for toggling on new models. While I often use the construct during dev as an indication that a piece of code has been reached, and/or for timing purposes, I'm hard-pressed to think of a time I toggled a port-pin I/O bit in final production firmware.] Lee

 

I don't know of a way on AVR8 to create a pulse narrower than one AVR cycle.  For a single pulse, consecutive OUTs to the associated PORT with prepared registers containing the desired values for all bits in the port.  For repetitive operation or rat-a-tat-tat a few times, timer in CTC mode and a compare of 0.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
At 8MHz, that would be 250ns.  At 16MHz, that would be 125ns.  What is the need for something that short?
'E' for an LCD has min 220ns time, wonder if it's an attempt to drive that as fast as possible?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

Then you problem is already solved, by using = instead of |=.

 

I am not following what you mean.

 

theusch wrote:

Tell how that would be "interesting".  What are you doing, tickling some high-speed logic?  What kind?  If you do an SBI-CBI pair, then you get a pulse of two AVR clock cycles.  As you are on an apparent quest for speed, one would surmise that you are running at a fast AVR speed.  At 8MHz, that would be 250ns.  At 16MHz, that would be 125ns.  What is the need for something that short?

 

Interesting as in something that was better than what you can already do with PORT.  If with PORT you can SBI/CBI in two clock cycles, it would have been interesting to write a bit to PIN and do it in one clock cycle!  I am working on an AVR to Z80 project so part of it is a response to to the Z80 doing an IN our OUT instruction.  Every cycle it waits is every cycle it is doing nothing.  So, my hope was a single SBI would toggle a pin in 1 cycle.  Not a huge deal, I just really thought the toggle a pin PIN=_BV(x) was something cooler than it is.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lol -- alank2 investigated this "pin toggle" in 2017...

https://www.avrfreaks.net/commen...

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote :

 

I don't know of a way on AVR8 to create a pulse narrower than one AVR cycle

just as side info, chips with a PLL like tiny85 can make shorter pulses using the timer.

 

Back to OP's quistion, the place I have used it is in a ISR to make interrupt taken, a 5 uS pulse is harder to see, and rare interrupts can be marked with just a LED on the port.

 

other side info the first AVR's like the 8515 didn't have this function.    

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PINx assignment can also be useful when one port is shared

among multiple modules, each of which uses a different interrupt.

If all the modules stay in their lanes, one can get the effect of

atomic assignment under mask.

 

Note that there is disagreement about what a compiler

is allowed to do which constructs like "PINx |= 4".

There is also disagreement about what a compiler ought to do.

My though is that a compiler ought to reject them altogether.

Instead there should be a macro or other construct

that becomes a singe sbi instruction.

At one time avr-gcc has such a macro,

but it was removed in favor of letting the

compiler proper handle the optimization.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I am not following what you mean.

 

What I mean is that this code

 

#include <avr/io.h>

#define PORTF_WR_PIN_AL 4

int main () {
        PINF =_BV(PORTF_WR_PIN_AL); //toggle WR
        PINF =_BV(PORTF_WR_PIN_AL); //toggle WR
}

 

Compiles to:

 

000000fa <main>:
  fa:	80 e1       	ldi	r24, 0x10	; 16
  fc:	8f b9       	out	0x0f, r24	; 15
  fe:	8f b9       	out	0x0f, r24	; 15

 

Since out takes 1 cycle to execute, unlike sbi which takes 2 cycles, this will give a 1 cycle pulse.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
just as side info, chips with a PLL like tiny85 can make shorter pulses using the timer.

lol -- indeed.  IIRC some/few/one model(s) have a burst feature so the number of pulses can be controlled. 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

lol -- alank2 investigated this "pin toggle" in 2017...

https://www.avrfreaks.net/commen...

 

I knew I had seen/talked about this before, but couldn't find it easily.

 

El Tangas wrote:

What I mean is that this code

Since out takes 1 cycle to execute, unlike sbi which takes 2 cycles, this will give a 1 cycle pulse.

 

I always forget how fast OUT is.  Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what about

 

  uint8_t a,b;
  a = PINB;
  b = a & ~_BV(PINB6);
  a = a | _BV(PINB6);
  PINB = a;
  PINB = b;

 

which generates

 

    in r24,0x3
    mov r25,r24
    andi r25,lo8(-65)
    ori r24,lo8(64)
    out 0x3,r24
    out 0x3,r25

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MattRW wrote:
what about

No.  With your code every 1 that you write to PINx toggles that bit in PORTx.  Close, if you [perhaps] do the last two lines to PORTB.  Yet, it still is fraught with peril ["Here there be dragons"] in the unexplored territory, as a change in one of the PORTB bits in the meantime would be lost.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

        PINF|=_BV(PORTF_WR_PIN_AL); //toggle WR

 202:    7c 9a           sbi    0x0f, 4    ; 15

Your syntax is surely wrong?. You don't want to use OR do you ?

 

I believe this is a bug in avr-gcc which is seen as

a feature (I've used it myself).

 

The compiler knows that the PINF register is located

in the register map at a low address which supports

SBI and CBI instructions, and since you are only

setting a single bit, an SBI instruction is generated.

 

For a normal register like PORTF or DDRF there is

no issue, but PINF is special.  What the |= should

do if taken literally is output a 1 to every bit position

which reads as one, in addition to setting the specific

bit provided.

 

The effect would be to toggle the requested pin (if it

is an output) and also turn off every other output in

PORTF, and maybe disable some of the input pull-ups.

This does not happen, though, since the SBI affects

only the one bit/pin.

 

The problem arises if you try to use the same |= code

on a PINx register which is not located within reach

of the SBI instruction. The compiler has no choice

but to read PINx, OR in the requested bit, and then

write this value back to PINx. If any other bits in

PORTx are outputs, they will be reset to zero.

 

I think it's safer to always use = with PINx registers

when writing C or C++. The generated code will be

correct for all PINx registers, and there's no speed

penalty. Wastes two bytes of flash, if you're really

tight on program memory, but then you're probably

going to have to write parts in ASM anyway!  ;-)

 

--Mike

 

EDIT: mentioned pull-up resistors

 

Last Edited: Tue. Mar 12, 2019 - 07:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I ought to stay out of this...

 

I find it interesting the concern about knowing the initial state of the pin, before one uses the Pin Toggle capability.

 

When I've written a bit-banged an SPI,  I2C, USART or LCD interface, etc., and I am about to blast a bunch of data out a pin, (or pins), I have also "wasted" a couple of clock cycles to pre-set the interface signals to their desired condition.

If they were already pre-set correctly, (as is the expected status of the pins), then it wasted a couple clock cycles.

It they, somehow mysteriously, were not how I expected them to be, then they are correctly set up before the data gets sent.

My bit-bang routines then end with the interface signals back in a known and desired state, awaiting their next usage.

I am comfortable using a pin toggle, or explicitly setting and clear the pins in this case.

 

I would think that if I wanted to generate a single pulse, (LCD driver, laser driver, etc.), I would once again be starting with a known condition for the hardware interface.

If I absolutely wanted to set and clear pins, then I'd take the clock cycle hit and set and clear them, without the toggle.

 

It kind of reminds me of the days of programming a PC in DOS vs in Windows today.

In the days of DOS I knew exactly what the 8086 was doing, and what the various peripheral interface chips were doing.

My code told them what to do.

 

These days my PC is running 2500 - 3000 Threads in the background, with 10K handles open, and I have no clue what the processor is actually doing at any point in time.

 

Fortunately, for my little embedded micro projects, their complexity is such that I still know, or at least I think I know, what the hardware is doing.

 

JC 

 

Edit: Typo

Last Edited: Tue. Mar 12, 2019 - 08:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reviewing this, it appears that the genesis is really in understanding the word "toggle". In the logic world, it means, roughly, to change a binary value from its current state to the opposite state. You see the term particularly applied to flip-flops as a description of what the device does when a clock edge happens.

 

I have never encountered a pulse functionality of the kind that alan seems to want, especially involving intervals smaller than 1 clock cycle.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My dream of a single instruction pulse operation is dashed!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My dream of a single instruction pulse operation is dashed!!!

Ah, finally a use for the 555 chip!

 

You could use an I/O pin, (Assuming you knew its initial state was low... <smirk> ), to trigger a 555 in one-shot mode.

 

On a more serious note:

It would be interesting to see if this is doable through the XmegaE5 series' programmable logic module.

And, unfortunately, it will have to go on the list of things to investigate some day, as I can't work on it at the moment.

 

JC 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can you not make a 2/4/6/8/10/12/14/16/18 clock pulse from a USART with a single out instruction?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

andrewm1973 wrote:

can you not make a 2/4/6/8/10/12/14/16/18 clock pulse from a USART with a single out instruction?

 

Oooh, I like that!  Very cool.  It'd be an inverted pulse.

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Throw a pin high into a grounded inductor and pick off the flyback voltage, and you'll get a pulse a lot shorter than your clock.

 

Resetting is your problem.  Also not blowing up the AVR while you're at it...  wink

 

I like 'write PINx' toggle, and get annoyed when I'm using an AVR that doesn't have it.  Saving instructions while writing assembler is always a good thing.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a pretty fundamental rule that it has always taken TWO toggles to make a complete "cycle". To quote Scottie "Ye cannae change the laws of physics!".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
To quote Scottie "Ye cannae change the laws of physics!".

AVRs should be made from transparent aluminum.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
It's a pretty fundamental rule that it has always taken TWO toggles to make a complete "cycle". To quote Scottie "Ye cannae change the laws of physics!".
Tell that to Q or to the legislature at Camelot or in the Dancing Gods series (a good read).

For that matter, tell it to Scottie.  He generally got the job done anyway.

All that said, 'tain't a matter of physics, 'tis a matter of mathematics.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
'tain't a matter of physics, 'tis a matter of mathematics.
Should we just say "one of God's laws" perhaps? cheeky

 

(sorry - deliberately inflammatory comment!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

sbi and cbi take 2 clk
Not on every target e.g. t4/5/9/10 and other reduced core tinies it is 1cycle.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just took a look at the datasheet for tiny214 etc. and that also only say 1 clk

 

and xmega E manual also say 1clk.

 

I think it was something they had to fix when there was chips made for USB and probably also other devices, that if status changed (in HW) while you made a SBI (CBI) there could be a error.

  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

skeeve wrote:
'tain't a matter of physics, 'tis a matter of mathematics.
Should we just say "one of God's laws" perhaps? cheeky

 

(sorry - deliberately inflammatory comment!)

Not even Odin can square the circle.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods