Author Topic: [ATmega 0] register confusion  (Read 10324 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #50 on: August 01, 2018, 07:14:54 am »
Even the plain old AVR had this kind of "accelerator"; the sbi and cbi instructions, which are specifically designed to do exactly this! But their use was limited to only part of the IO device mapping, so on some devices, you could use them for PORTA, but not for PORTF, for example. Which is stupid. Also, it's a bit confusing that a GPIO task has two specific instructions in the CPU instruction set. These instructions also only could set or clear only one single bit at a time. With these new register, you can, for example, set bits 0, 4 and 6 at the same time, using just one write operation, with no runtime math whatsoever.

On those "plain old" AVR bit set, clear and even toggle can be done in one single instruction, be it for one or more bits; no need to read-modify-write (except for a few cases). Again, the optimizer translates into the proper instructions. The only trick is bit(s) toggle, which is done by writing one(s) to the corresponding PINx register. Still, one instruction.

Nope, because it's not the "double" register. On old AVR what you write takes effect be it 1 or 0. Because you have to write the whole register the calculation is necessary. I know that it takes 4 clock cycles to change a pin state.

In this new implementation the 0's are ignored so you can write "gibberish" to the register by just sending 1's to the bits that you care about, you don't have to worry about accidentally setting another bit to 0 because the 0's no longer have an effect so you don't have to worry about accidentally changing them with 0's. Clever, it's gotten one step away form single bit/pin addressing without having to actually have the address space.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: [ATmega 0] register confusion
« Reply #51 on: August 01, 2018, 07:24:06 am »
On those "plain old" AVR bit set, clear and even toggle can be done in one single instruction, be it for one or more bits; no need to read-modify-write (except for a few cases). Again, the optimizer translates into the proper instructions. The only trick is bit(s) toggle, which is done by writing one(s) to the corresponding PINx register. Still, one instruction.

Maybe you could show us what these "proper" instructions are. I have never heard about them.

There was the pin toggling trick with some devices indeed, but toggling is a fairly rare use case: usually we want to deterministically set the port to '0' or '1', toggling would require us to keep state of the previous value somewhere else. Unless we, of course, just want to blink something efficienctly with no regards of the phase (whether it's '0' or '1' at a given time).

I have never found any use for toggling an IO register bit between 0 and 1 (so that I'd read out the register, toggle a bit, and write back; which this old trick would optimize). I always need to write 0 or 1 explicitly.
« Last Edit: August 01, 2018, 07:25:40 am by Siwastaja »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #52 on: August 01, 2018, 07:30:18 am »
The only use I can think of is software PWM
 

Offline hans

  • Super Contributor
  • ***
  • Posts: 1638
  • Country: nl
Re: [ATmega 0] register confusion
« Reply #53 on: August 01, 2018, 07:51:38 am »
I agree, I've only used I/O toggle in blinky programs.
All the rest can be used using pin set and clr.

For software PWM you still want an accurate start and end phase. :-//
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: [ATmega 0] register confusion
« Reply #54 on: August 01, 2018, 07:56:35 am »
For software PWM you still want an accurate start and end phase. :-//

Granted, you can do software PWM with toggling no problem - set the initial known state and then just toggle it every time start or end happens. I feel a bit uneasy doing things like this, but it shouldn't go out of sync unless an actual electronic glitch happens - in which case things could go haywire anyway.

You may need to think your logic carefully to handle 0% and 100% cases and transitions to them, so there's more to go wrong. Basically, if you skip a "start", you need to skip the next "stop" as well, and vice versa.

I have never done software PWM like this. Just feeling too uneasy about it for little performance gain.
« Last Edit: August 01, 2018, 08:50:21 am by Siwastaja »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #55 on: August 01, 2018, 08:35:06 am »
Well my explained board just arrived, complete with bodge wire 😁
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [ATmega 0] register confusion
« Reply #56 on: August 01, 2018, 10:02:56 am »
Quote
I have never found any use for toggling an IO register bit
It can speed up (and shrink) any clock signal you're outputting, say for bit-banged SPI.  Depending on whether you have those convenient "set to one" and "set to zero" instructions (or registers.)  (keep in mind that an old-style AVR did NOT have the set-bit-to-zero and set-bit-to-one capability for any registers beyond 0x1F.)

The new-style AVRs have the separate clear/set/toggle registers IN ADDITION TO the old "whole port" and SBI/CBI single-bit capabilities (via VPORTx)
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: [ATmega 0] register confusion
« Reply #57 on: August 01, 2018, 12:13:59 pm »
Quote
I have never found any use for toggling an IO register bit
Quote
It can speed up...
I think they were just referring to the INV/TGL, not SET/CLR.

On a pic32, even where you have clr/set/inv for the whole sfr space, I think the INV registers live a pretty dull life.  Probably for the same reason we don't have momentary 'invert' fuse panel circuit breakers- we typically need to know the state before or after.

Speaking of pic32, I would guess the Atmel sam designers wanted a more human friendly way to deal with the io bit access, and liked the pic32 clr/set/inv layout (changing inv to tgl for some reason, I guess they couldn't think of any substitutes for clr/set, though). It then trickles down in a very limited way to other chips. I would still chuckle if someone said the new atmegas are 'pic32 style'. (I really don't know if pic32/mips was even the first to use this layout- I would be surprised if so, as its difficult to be first at anything).
 
The following users thanked this post: Siwastaja

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11254
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #58 on: August 01, 2018, 03:01:14 pm »
Speaking of pic32, I would guess the Atmel sam designers wanted a more human friendly way to deal with the io bit access, and liked the pic32 clr/set/inv layout (changing inv to tgl for some reason, I guess they couldn't think of any substitutes for clr/set, though). It then trickles down in a very limited way to other chips. I would still chuckle if someone said the new atmegas are 'pic32 style'. (I really don't know if pic32/mips was even the first to use this layout- I would be surprised if so, as its difficult to be first at anything).
PIC32 was definitely not the first to do so. This is a very old way of dealing with I/O, appearing way before PIC32 was conceived. I think even AGC (Apollo Guidance Computer) uses it.
Alex
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: [ATmega 0] register confusion
« Reply #59 on: August 01, 2018, 06:45:09 pm »
Quote
PIC32 was definitely not the first to do so
I guess I'm talking about the specific CLR/SET/INV layout, not the fact there is such a thing as a way to do these operations on single bits. Does some other micro have this same layout- base register/clr/set/inv?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11254
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #60 on: August 01, 2018, 06:47:13 pm »
Quote
PIC32 was definitely not the first to do so
I guess I'm talking about the specific CLR/SET/INV layout, not the fact there is such a thing as a way to do these operations on single bits. Does some other micro have this same layout- base register/clr/set/inv?
I'm not sure I follow. What is the "layout"? All registers must be located in the memory somehow. Having all related registers be close to each other is an obvious solution. I don't see a way to do it otherwise.
Alex
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [ATmega 0] register confusion
« Reply #61 on: August 01, 2018, 07:55:56 pm »
Does some other micro have this same layout- base register/clr/set/inv?
Yes, eg. Freescale's K series (data, set, clear, toggle).

For something truly bizarre, NXP's LPC13xx (and maybe others) have a scheme where bits 13:2 of the address used to access the GPIO port functions as a mask for reads and writes to the port data register. So if you want to update all bits of the port, you write to address GPIO_BASE+0x3FFC. If you write to GPIO_BASE+0x4, only port bit 0 will be updated.

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: [ATmega 0] register confusion
« Reply #62 on: August 01, 2018, 08:01:13 pm »
Quote
Having all related registers be close to each other is an obvious solution. I don't see a way to do it otherwise
'Close' to each other, sure, but how about in that particular order with the 3 bit manipulation registers. I guess I'm familiar with a lpc1114 in the arm world, so in that case for port io bit manipulation you have a 14 bit address space with 12 bits usable (12 io pins per 'port'), so to set bit0 you end up with something like- *(volatile uint32_t*)(base_reg + (1<<2) ) = 1  (this may not be right, but its close).

I don't know, but have most arm micros used this sort of big address space for bit manipulation? From my limited knowledge, it would seem most arm bit manipulation has been done like this previously.

This is where I take another guess- Atmel designers (newer sam series) wanted a better way to deal with this io port bit manipulation- using 3 register offsets instead. So it ends up similar to pic32-
*(volatile uint32_t)(base_reg + SET) = 0x0001
in the end it really doesn't matter- the bit gets set either way, but the latter is easier to deal with on the user end (I'm sure could also be argued, but there must be a reason they changed to this style)

So if this is obvious, why don't all arm micros use the base/clr/set/inv 'layout' instead of the bit-banding(?)/big memory space? With the atmega it IS an obvious solution as they simply do not have the address space to do that.

I'm just trying to make the connection from pic32 base/clr/set/inv to newer atmel arm base/clr/set/tgl (for port io) to atmega base/clr/set/tgl. The last connection is a little thin on my part as its obvious as stated, but they did happen to get the order the same as the others.

This post probably makes no sense.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11254
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #63 on: August 01, 2018, 08:31:23 pm »
All Atmel ARM processors had this. SAM7x are ARM7TDMI-based processors were introduced in early 2000s and had this system already.

8- and 16-bit processors typically don't have enough memory map do do a lot of registers, but also the penalty for a read-modify-write operation is not that high there. On ARM it stresses the bus more than you want.
Alex
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: [ATmega 0] register confusion
« Reply #64 on: August 01, 2018, 09:09:00 pm »
Quote
All Atmel ARM processors had this.
I'm looking at an AT91SAM7S32 (was first on the arm7tdmi device search list)-
they have a PIO_SODR at offset 0x30, and PIO_CCDR at offset 0x34, but I see no invert register, and this doesn't look anything like base/clr/set/inv which I'm referring to.

in contrast, something like a newer atmel arm- ATSAMD09C13, they have listed in table 22-2 the base/clr/set/tgl layout for the dir and out


 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11254
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #65 on: August 01, 2018, 09:13:23 pm »
I think you are giving too much value to the actual register location and grouping. It is not meaningful or important. On 32-bit systems you have plenty of address space to put things however you want.
Alex
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [ATmega 0] register confusion
« Reply #66 on: August 01, 2018, 09:26:33 pm »
Quote
definitely not the first to do so
Indeed.  It is not at all a new concept.  The venerable 82C55 had bitset/reset modes.  Before that, it was a common option on flip-flops.  (7474: "dual D flipflop with preset and clear.")

It "caught on" in microcontrollers with the wave of 32bit RISC processors.  RISC (generally) meant doing away with the special purpose io register bit manipulation instructions (even IN and OUT) and going to a strict load/store memory architecture.  If they were going to replace 8bit microcontrollers, they had to figure out some way to to have the bit-banging that uC engineers were so fond of doing not end up 4 to 5x slower at the same clock rate.  Fortunately, there was all this address space in which to add extra "registers" to get extra functions from "store."  In fact, there was so much address space that they could throw "questionable" functions (like toggle) in there too...
Essentially, it's all a matter of moving complexity OUT of the CPU and into the peripheral.  I can envision a GPIO peripheral with the bitset and bitclear operations more easily than I can see how to implement it in the CPU.(similarly, bit-banding moved complexity from CPU to memory bus.  It's a bit of a shame that it didn't catch on; it would have been interesting to have true one-bit variables sneak into programs.   bit-banding was PROBABLY the core-designer's idea of how to handle bit-banging, whereas the users and peripheral designers found the set/clear "registers" more understandable.)
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: [ATmega 0] register confusion
« Reply #67 on: August 01, 2018, 10:46:01 pm »
Quote
On 32-bit systems you have plenty of address space to put things however you want.
Which is why I am/was making the connection to pic32. Of all the various ways they can could/can come up with to do this, it matches the pic32 (or whatever else does the same)-
base_reg
base_reg + 4 = CLR register
base_reg + 8 = SET register
base_reg + 12 = INV (TGL) register

None of this is important, and I have beaten the dead horse long enough, so will stop :)
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #68 on: August 02, 2018, 11:43:42 am »
I see the 32 pin version has a slightly easier pin pitch of 0.8mm with the 48 pin version being exactly the same size but more dense at 0.5mm. Right that's a start from scratch with a new symbol and footprint, for my small stuff 32 pins is ample and I'd rather not stuff up my first customer prototypes over a solder bridge.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #69 on: August 02, 2018, 07:13:08 pm »
Right, having been confused enough by the "atmel start" online crashware I have decided to start writing my own code base. Can someone translate the following into english.

Quote

Virtual Ports
The Virtual PORT registers map the most frequently used regular PORT registers into the bit-accessible
I/O space. Writing to the Virtual PORT registers has the same effect as writing to the regular registers, but
allows for memory-specific instructions, such as bit-manipulation instructions, which are not valid for the
extended I/O memory space where the regular PORT registers reside.

 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11254
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #70 on: August 02, 2018, 08:06:24 pm »
AVR has two "address spaces". In the lower one all bits are accessible through special bit-manipulation instructions (sbi/cbi). The higher one is only byte-accessible.

Originally all the peripherals fit into the lowest space, but then devices grew in size and certain peripherals had to be prioritized. Ports were selected to be mapped into the lower space, since it makes sense.

But with the new port features (SET/CLR/TGL) it really does not make that much of a difference.

Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #71 on: August 02, 2018, 08:27:05 pm »
So why have we been doing read-modify-write if the pins were individually addressable? I still don't see a name for any bit on any register, they all need register wide addressing, it's just that now they have made it faster. The VPORT is just a duplication of PORT, I don't see how they have helped or is this more unclear documentation aimed at those working with raw address numbers rather than the standard register definitions.

My pin manipulation code is now:

Code: [Select]
// PortF setup and manipulation

#define PF0_input PORTF.DIRCLR = 0x01
#define PF1_input PORTF.DIRCLR = 0x02
#define PF2_input PORTF.DIRCLR = 0x04
#define PF3_input PORTF.DIRCLR = 0x08
#define PF4_input PORTF.DIRCLR = 0x10
#define PF5_input PORTF.DIRCLR = 0x20
#define PF6_input PORTF.DIRCLR = 0x40
#define PF7_input PORTF.DIRCLR = 0x80

#define is_PF0_low !bit_get(PORTF.IN, 0)
#define is_PF1_low !bit_get(PORTF.IN, 1)
#define is_PF2_low !bit_get(PORTF.IN, 2)
#define is_PF3_low !bit_get(PORTF.IN, 3)
#define is_PF4_low !bit_get(PORTF.IN, 4)
#define is_PF5_low !bit_get(PORTF.IN, 5)
#define is_PF6_low !bit_get(PORTF.IN, 6)
#define is_PF7_low !bit_get(PORTF.IN, 7)

#define is_PF0_hi bit_get(PORTF.IN, 0)
#define is_PF1_hi bit_get(PORTF.IN, 1)
#define is_PF2_hi bit_get(PORTF.IN, 2)
#define is_PF3_hi bit_get(PORTF.IN, 3)
#define is_PF4_hi bit_get(PORTF.IN, 4)
#define is_PF5_hi bit_get(PORTF.IN, 5)
#define is_PF6_hi bit_get(PORTF.IN, 6)
#define is_PF7_hi bit_get(PORTF.IN, 7)

#define PF0_output PORTF.DIRSET = 0x01
#define PF1_output PORTF.DIRSET = 0x02
#define PF2_output PORTF.DIRSET = 0x04
#define PF3_output PORTF.DIRSET = 0x08
#define PF4_output PORTF.DIRSET = 0x10
#define PF5_output PORTF.DIRSET = 0x20
#define PF6_output PORTF.DIRSET = 0x40
#define PF7_output PORTF.DIRSET = 0x80

#define PF0_hi PORTF.OUTSET = 0x01
#define PF1_hi PORTF.OUTSET = 0x02
#define PF2_hi PORTF.OUTSET = 0x04
#define PF3_hi PORTF.OUTSET = 0x08
#define PF4_hi PORTF.OUTSET = 0x10
#define PF5_hi PORTF.OUTSET = 0x20
#define PF6_hi PORTF.OUTSET = 0x40
#define PF7_hi PORTF.OUTSET = 0x80

#define PF0_low PORTF.OUTCLR = 0x01
#define PF1_low PORTF.OUTCLR = 0x02
#define PF2_low PORTF.OUTCLR = 0x04
#define PF3_low PORTF.OUTCLR = 0x08
#define PF4_low PORTF.OUTCLR = 0x10
#define PF5_low PORTF.OUTCLR = 0x20
#define PF6_low PORTF.OUTCLR = 0x40
#define PF7_low PORTF.OUTCLR = 0x80
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11254
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #72 on: August 02, 2018, 08:35:35 pm »
So why have we been doing read-modify-write if the pins were individually addressable?
I don't know. And on bigger devices not all ports are accessible individually. You only have lower 32 locations in the memory accessible like this and some of them are reserved for the core. So typically ports A, B and C were accessible like that, but not D and above.

And normally compilers themselves insert cbi/sbi if they infer that this operation is possible.

I still don't see a name for any bit on any register, they all need register wide addressing, it's just that now they have made it faster.
There are no specific names. Previously PORT peripherals had very few registers, so they were directly located in the I/O space. Now PORT registers have a lot of registers, and placing all of them in the I/O space is wasteful. So they took a subset of the registers that need to be fast and grouped them into VPORT, which resides in the I/O region.

The VPORT is just a duplication of PORT
It is duplication of only a few registers.

I don't see how they have helped or is this more unclear documentation aimed at those working with raw address numbers rather than the standard register definitions.
There is a lot of effort went into designing all of this, and if something does not make sense, you can pretty much assume that you are missing something until proven otherwise. Life is easier this way.

Again, your frustration comes from the fast that you are working with AVR, which is full of legacy stuff like this.

You can look at the Table 6-1. "Peripheral Module Address Map" and all peripherals that have address below 32 (0x1f) are bit-accessible though cbi/sbi instructions. Which in this case are only VPORTs, GPIO and CPU. That's all.
« Last Edit: August 02, 2018, 08:39:00 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #73 on: August 02, 2018, 08:48:38 pm »
Presumably there is no way to selectively write a series of 0's and 1's to a register in one go leaving the other non intended bits alone?
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #74 on: August 02, 2018, 08:55:37 pm »
There is a lot of effort went into designing all of this, and if something does not make sense, you can pretty much assume that you are missing something until proven otherwise. Life is easier this way.

Again, your frustration comes from the fast that you are working with AVR, which is full of legacy stuff like this.

You can look at the Table 6-1. "Peripheral Module Address Map" and all peripherals that have address below 32 (0x1f) are bit-accessible though cbi/sbi instructions. Which in this case are only VPORTs, GPIO and CPU. That's all.

Sure which is why i ask, all i can see is name duplication with a "V" in front. I don't see anything that describes access to the bits, there are no names to use which in compiling would get translated to addresses. If bit wise access is possible it would have to be done by using a number to address the pin rather than a name.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf