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

0 Members and 1 Guest are viewing this topic.

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #75 on: August 02, 2018, 09:02:29 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?
Not for most registers, no. Only bit by bit into registers, which addresses are below 32.
Alex
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #76 on: August 02, 2018, 09:04:12 pm »
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.

Section "5.10 I/O Memory":
Quote
I/O Registers within the address range 0x00 - 0x1F are directly bit-accessible using the SBI and CBI
instructions. In these registers, the value of single bits can be checked by using the SBIS and SBIC
instructions. Refer to the Instruction Set section for more details.

If bit wise access is possible it would have to be done by using a number to address the pin rather than a name.
You still can.
Alex
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21686
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: [ATmega 0] register confusion
« Reply #77 on: August 02, 2018, 09:26:31 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?

How would you indicate intent?

Does the computer just know what you want to do? ;D

You would need another sequence of bits to say which ones to write, and which ones to leave.  In other words, a bit mask.  You need exactly one extra bit for each bit written, i.e. double the data.

This requires a R-M-W operation, or two 8-bit writes to send the data (however it's coded) to a suitable peripheral.

In this case, the desired operation would be:
PORTn.OUTSET = BitStates & BitMask;
PORTn.OUTCLR = ~BitStates & BitMask;

Which can indeed be done in just two instructions (assuming constant operands). :)

Regarding VPORTs, you won't normally need that, unless you are doing very time critical IO, or supporting legacy ASM/BIN that assumes those addresses are the ATmega ports.

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #78 on: August 03, 2018, 07:36:11 am »
OK so for registers that do'n have SET and CLR I still need to write one bit at a time with a mask. Basically if I want to send 101 to the last 3 bits of a register I can't use a read-modify-write as I see from my own macros that bit_set and bit_clr use different math operands and 101 needs to do both at once which is impossible.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #79 on: August 03, 2018, 07:38:05 am »
OK so for registers that do'n have SET and CLR I still need to write one bit at a time with a mask. Basically if I want to send 101 to the last 3 bits of a register I can't use a read-modify-write as I see from my own macros that bit_set and bit_clr use different math operands and 101 needs to do both at once which is impossible.
You can do this. REG = (REG & 0xf8) | 0b101;  your macros are just not universal enough.

You can invent macros to automatically calculate masks, of course. But it is a real overkill. Those situations don't happen that often in real life, it is easier to just write it in the code or make a dedicated function.
« Last Edit: August 03, 2018, 07:39:52 am by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #80 on: August 03, 2018, 08:56:32 am »
Well my macro's are universally for any register and bit. But if i need to write several bits to a register to set one thing up like the pin mode I am doing multiple read-write-modifies for what is one operation. This is usually just a setup operation and not main run code so it's not a real problem. Obviously I could restrict this to 2 operations, maybe the compiler optimises it anyway.
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21686
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: [ATmega 0] register confusion
« Reply #81 on: August 04, 2018, 12:05:48 pm »
Initialization is almost always writing a whole register at a time.

There is absolutely nothing wrong with writing the default value (on AVR, almost always 0) to bits that you aren't using.

Bit instructions are just doing the same thing anyway.  The registers don't care, they're none the wiser!

Only when a register is designed so that any write operation causes a state change, do you need to worry about things -- and in that case, you can't use the bit instructions anyway, or anything else.  You have to handle that state change in your program, period.

A typical example of this is an interrupt status register, which resets on read or write.  In that case, if you must perform an operation on this register without upsetting the peripheral's state, you must record that state somewhere else.  Say, read the register into a temp variable, which is later read by the code responsible for that peripheral.  Better yet, add a getter and setter function (in the code for that peripheral), so that all read and write operations are handled by the driver code, and your extra operation can be handled at the right time without upsetting things. :)

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #82 on: August 04, 2018, 12:27:18 pm »
Yes I can write a 0 to an unused bit (which at some point on future point might be used on new devices) but I can't just go writing 0's to bits without certainty they will be 0 in all circumstances. So in writing generic setup code I have to do it one bit at a time unless the register is of the set/clr type.
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21686
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: [ATmega 0] register confusion
« Reply #83 on: August 04, 2018, 12:57:34 pm »
Ah yes, the unlimited code portability trap...

1. Write for the platform you're using.  No one cares.  Why should you?

If you (or someone else) later finds a platform with broken compatibility, make it obvious to look for making changes in, say, main.c:init().  That's where I put it, that's where the appnotes put it, that's where everyone else puts it.  It works because it works. :)

2. Assume that the bits will default to zero in future versions.  This is pretty safe to assume.  It would be terribly shitty of them to say "write zero to this bit" in literally every datasheet ever, then break that later.  (Well.  I wouldn't put it past them now that they're Microchip.  But, if that happens, then it happens.)

3. Be a dick about it, and put in autodetects and init tables and header files or config settings and everything.  Don't be surprised if you find you end up spending three times longer on the project just doing this, and it's still not done... :-DD  (Not to mention it doesn't even /fit/ on the smallest flash/RAM parts you had initially wanted to support.  Talk about breaking compatibility! ;) )

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #84 on: August 04, 2018, 01:18:33 pm »
It would appear that none of the register names has been defined
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #85 on: August 04, 2018, 02:11:16 pm »

You can do this. REG = (REG & 0xf8) | 0b101;  your macros are just not universal enough.


This is starting to look like a better plan, So presumably the AND operation sets the bits of interest to 0 while maintaining the others untouched and the the OR sets the bits that need setting in the bits of interest.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: [ATmega 0] register confusion
« Reply #86 on: August 04, 2018, 06:52:16 pm »
This is starting to look like a better plan, So presumably the AND operation sets the bits of interest to 0 while maintaining the others untouched and the the OR sets the bits that need setting in the bits of interest.
Correct. And you almost never have to actually do this in real life.

I've looked at the header files for those new AVRs and it is sad. Not as sad as plain old AVRs, but Xmega sad.

Here is how UART initialization code looks like on SAMD21:
Code: [Select]
  SERCOM3->USART.CTRLA.reg =
      SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK |
      SERCOM_USART_CTRLA_RXPO(1/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(0/*PAD0*/);

  SERCOM3->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN |
      SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);

  SERCOM3->USART.BAUD.reg = (uint16_t)br;

  SERCOM3->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;

And here is a simple interval timer:

Code: [Select]
  TC3->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |
      TC_CTRLA_PRESCALER_DIV256 | TC_CTRLA_PRESCSYNC_RESYNC;

  TC3->COUNT16.COUNT.reg = 0;
  TC3->COUNT16.CC[0].reg = (F_CPU / 1000ul / 256) * 500; // 500 ms
  TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;

  TC3->COUNT16.INTENSET.reg = TC_INTENSET_MC(1);
  NVIC_EnableIRQ(TC3_IRQn);

Notice how there are no cryptic 3 letter bit names and the code is actually readable.

And if you want to access individual bits, but without goofy macros, you can just do "TC3->COUNT16.CTRLA.bit.MODE = xxxx". And compiler will figure out how to do this in the most optimal way.

I really thought they would do the same for the new AVRs, but they decided otherwise, probably to keep the old code more portable. Although that would be the most significant step towards making them ARM-like.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #87 on: August 04, 2018, 06:58:25 pm »
Old AVR code will be completely incompatible with 0-series peripherals. yes lot's of lovely "bit names" for registers but none of those names not even the sodding pins are in a header file, I have to use numbers instead which is why i decided to just do all muti-bit mask operations in one go.
 

Online westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [ATmega 0] register confusion
« Reply #88 on: August 04, 2018, 10:22:03 pm »
Quote
It would appear that none of the register names has been defined
What are you talking about?  I see an iom4809.h file containing all the names I expect to see...
It's true that Atmel has gone to some annoying "pack-based" scheme for getting data about new chips, and you may have to go hunting to find that file, and I can't speak to Studio's abilty to autocomplete or do inline help because I don't use Studio.  But "none of the register names are defined" needs clarification!
Quote
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?
From the datasheet:
 
 
Quote
Yes I can write a 0 to an unused bit (which at some point on future point might be used on new devices) but I can't just go writing 0's to bits without certainty they will be 0 in all circumstances.
Even though the datasheet says that that is what you should do?  Might as well give up, then.
« Last Edit: August 04, 2018, 10:25:45 pm by westfw »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #89 on: August 05, 2018, 11:07:30 am »
No what I am saying is that there is no point in writing a macro that i will use for years to come relying on the current ability to write gibberish to an unused bits knowing that they are unused as in some future device my macro is also applicable to this could cause havoc. As suggested earlier for multi bit writes I will AND the bits to be left alone with 1's and the bit's of interest with 0's and then OR the bit's of no interest with 0's and the desired sequence for the bits of interest.

I did not say that the register names are undefined, they actually appear to be struct variables. But the bit names have not been defined you havo to use position numbers instead, one more reason to use a desccriptive macro instead.

In older devices somewhere there was something like:

#define PA0 0

This no longer exists and PA0 in your code will cause a compile error. You now have to use "0"
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21686
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: [ATmega 0] register confusion
« Reply #90 on: August 05, 2018, 12:08:15 pm »
No what I am saying is that there is no point in writing a macro that i will use for years to come relying on the current ability to write gibberish to an unused bits knowing that they are unused as in some future device my macro is also applicable to this could cause havoc. As suggested earlier for multi bit writes I will AND the bits to be left alone with 1's and the bit's of interest with 0's and then OR the bit's of no interest with 0's and the desired sequence for the bits of interest.

I did not say that the register names are undefined, they actually appear to be struct variables. But the bit names have not been defined you havo to use position numbers instead

They use bit masks now.  Instead of writing (1 << PB2) you use PORT_PIN2_bm or something like that.

The structs are just a different way to tell the compiler how to find the register.  This simplifies code, so a half dozen instances of a GPIO port can use the same exact register names (address offset) while referring to unique ports (base address).

Would examples not be helpful here?  Here's some init I wrote last month:

Code: [Select]
/**
 * Set up all the registers needed for operation
 */
void initialize() {

// Set default pin states
PORTA.OUT = BIT_PIN7;
PORTA.DIR = 0;
PORTB.OUT = BIT_PIN3 | BIT_PIN4 | BIT_PIN5 | BIT_PIN6 | BIT_SPI_RS;
PORTB.DIR = BIT_LED1 | BIT_LED2 | BIT_LED3 | BIT_SPI_RS;

// ...

// Initialize TCC0, 16 bits, PWM, MAX = 57600, PC4/OC1A (2048Hz)
TCC0.PER = PWM_PERIOD;
TCC0.CTRLB = TC0_CCAEN_bm | TC_WGMODE_SS_gc;
TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
TCC0.CCA = 0;
HIRESC.CTRLA = HIRES_HREN_TC0_gc;
TCC0.INTCTRLA = TC_OVFINTLVL_HI_gc;

// ...

// Enable interrupt sources
PMIC.CTRL = PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;
sei();

// Done, turn on power LED
PORT_LED1.OUTSET = BIT_LED1;

}

("..." is a bunch of stuff I cut out here for simplicity's sake; it's long enough as it is!)

Meanwhile, in pindefs.h, I have all the names used above that aren't predefined.  I generated these from a list of pin names (what the pins do in the circuit), so I don't have to maintain them by hand.  Many SDKs include this sort of functionality for init and config and abstraction, although they're often ugly as sin (ST Cube for example..).

Code: [Select]
#ifndef PINDEFS_H_INCLUDED
#define PINDEFS_H_INCLUDED

#define BIT_PIN0 PIN0_bm
#define BIT_PIN1 PIN1_bm
#define BIT_PIN2 PIN2_bm
#define BIT_PIN3 PIN3_bm
#define BIT_PIN4 PIN4_bm
#define BIT_PIN5 PIN5_bm
#define BIT_PIN6 PIN6_bm
#define BIT_PIN7 PIN7_bm

#define PIN_VREF PIN0
#define BIT_VREF (1 << PIN0)
#define PORT_VREF PORTA
#define PIN_VO PIN1
#define BIT_VO (1 << PIN1)
#define PORT_VO PORTA
#define PIN_IO PIN2
#define BIT_IO (1 << PIN2)
#define PORT_IO PORTA
// ...

I named this as PIN_, BIT_ and PORT_ for each pin, followed by the name (VREF, VO and IO above, among others).  This gives the assignment PORT_IO.OUTSET = PIN_IO, say to turn on the pin.


Quote
In older devices somewhere there was something like:

#define PA0 0

This no longer exists and PA0 in your code will cause a compile error. You now have to use "0"

If you like that convention, you can always define your own, you know.  You aren't stuck with exactly only the headers in the SDK! ;D

It took me under four hours to list all the pins I used (64 pin device), write the script to generate the code, and paste it in the header (with minor changes and additions).  That's peanuts.  If it takes someone else an hour or two to configure it for some other device or platform, that's no problem at all.

If you know it's going to save you a week of work sometime later (say, porting to other platforms is within the project scope), by all means spend the time worrying about how it's going to be set up.

But yeah, if you're just doing cutesy one-offs, like I did above, it doesn't freakin' matter, man.  Don't sweat it, just sit down and write.

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #91 on: August 05, 2018, 05:33:43 pm »
Well as they have not bothered to define each bit name I'll just use the bit number.
 

Offline VinzC

  • Regular Contributor
  • *
  • Posts: 227
  • Country: be
  • See you later, oscillator.
Re: [ATmega 0] register confusion
« Reply #92 on: August 05, 2018, 06:12:48 pm »
Quote
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, you're wrong:  Multiple-bit set/clear in IO registers never existed, single bit set/clear had an extremely limited range, and bit-toggle was a kludge tacked on to only SOME of the newer CPUs (in a manner rather like the 0-series, actually.)  Manipulating a bit of PORT L on an ATmega1280 takes 10 bytes.

and

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

Gosh, my bad again :palm:. Indeed multiple-bit change require a read-modify-write operation [EDIT: with PORT's] — a temporary register is needed to change multiple [EDIT: PORT] bits and I don't know why I insisted it was possible (too much booze maybe... other than I wasn't focusing on PORT bits anymore, which was off-topic anyway) :-// Sorry for the noise.

There was the pin toggling trick with some devices indeed, but toggling is a fairly rare use case.

Well, maybe, I don't disagree with that. Anyway should you toggle an output port bit, there's still a one-clock cycle instruction for that instead of a read-modify-write operation. That's not much of an optimization overall, I agree, compared to the overhead discussed otherwise.

EDIT: BTW I'm not referring to PWM but to controlled toggling of a pin, e.g. when timing accuracy relatively doesn't matter, like blinking an indicator or... well any other use case blind toggling is wanted.

Nothing else to add, your honour ;) .
« Last Edit: August 05, 2018, 06:34:52 pm by VinzC »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [ATmega 0] register confusion
« Reply #93 on: August 05, 2018, 06:21:29 pm »
in the past i used macro's that edited one bit at a time. I know for certain that it takes 4 clock cycles to carry out a bit change. I sent a 0/1 sequence to a pin and it took 4 clk cycles to go from 0 to 1. I have now modified all of my multibit manipulations from a list of several read-modify-write operations to a single operation so where i was using up to 16 cycles to change 4 bits I now do it in 4 cycles regardless of how many cycles.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf