A bit of fun - new way to program AVRs - beta testers invited!

Go To Last Post
60 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

A couple of posts the other day made me think about something.

 

First someone posted to say that when debugging with gdb they were a bit disappointed that all the symbols in io.h don't make it through to the debugging. This is, of course, because they are preprocessor defines, not C symbols.

 

Then in another thread Morten mentioned that the XML files in AS6/7 had recently been changed from .xml to .atdf extension. Now I always knew those files existed and I always knew that (amongst other things) they define the layout of the AVR but I'd never really looked at them in any detail.

 

But recently my day job has involved me learning Python and, in particular using it to write C++ code generators taking XML as input.

 

So I threw this together...

 

#########################################################################################################
#                                          AVRRead                                                      #
# A utility to read the XML files (probably .atdf in fact) in a Studio 6/7 installation and use         #
# the data within to define one big structure to overlay the SFR area of any AVR. Just use:             #
#                                                                                                       #
# python avrread.py -i ATmgea16.atdf                                                                    #
#                                                                                                       #
# or any other .atdf to generat an ATmega16.h (or whatever) header file for use in programming the      #
# AVR. In this case don't use "#include <avr/io.h>" but instead just do something like this:            #
#                                                                                                       #
#        #include "ATmega16.h"                                                                          #
#                                                                                                       #
#        USE_SFRS(pSFR);                                                                                #
#                                                                                                       #
#        int main(void)                                                                                 #
#        {                                                                                              #
#            pSFR->DDRB.byte = 0xFF;                                                                    #
#            pSFR->UCSRB.bits.TXEN = 1;                                                                 #
#            while (1)                                                                                  #
#            {                                                                                          #
#                pSFR->PORTB.byte ^= (1 << 3);                                                          #
#            }                                                                                          #
#        }                                                                                              #
#                                                                                                       #
# Use the USE_SFR() macro to name a struct pointer variable (like "pSFR") that you then want to         #
# use to access the registers in the code.                                                              #
#                                                                                                       #
#                        by Cliff Lawson                                                                #
#                                                                                                       #
# Licence: I need beer - see what you can do!                                                           #
#########################################################################################################

# following ("from...") line is useful if you are trying to make Python 3 code run in Python 2
# (however things like "argparse" here means this program is 3.2+ anyway.
# from __future__ import print_function
import sys
import os
import argparse
import xml.etree.ElementTree as et

# found this on StackOverflow - it simply returns the lowest bit that is set in a byte
def lowestSet(int_type):
    low = (int_type & -int_type)
    lowBit = -1
    while (low):
        low >>= 1
        lowBit += 1
    return(lowBit)


# often find this useful to check the raw command line args
# for n in range(0, len(sys.argv)):
#	print(n, sys.argv[n])

# I like argparse - it makes for very clean command line interfaces
parser = argparse.ArgumentParser(description='Read Atmel XML (version 1.0)')
parser.add_argument("-i", "--input", dest='in_fname', help="name of .XML file to read as input", required=True)
parser.add_argument("-o", "--output", dest='out_name', help="Name of output file (overides default)")
parser.add_argument("-q", "--quiet", dest='quiet', action="store_true", help="Don't print to console")
parser.add_argument("-v", "--verbose", dest='verbose', action="store_true", help="Show developer info")

# my one argument with argparse is that if you run the app without args it doesn't show help info, so
# this will achieve that...
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)

# this actually runs the argument parser on sys.argv
args = parser.parse_args()

# the user has the opportunity to use -o to set an output filename but if they haven't used that this
# takes the input .atdf/.xml filename and replaces the extension with ".h" to create the output name
if args.out_name is None:
    args.out_name = os.path.splitext(args.in_fname)[0]+".h"

# The following creates an empty list. As the XML is parsed this will be appened()'d too to build a complete
# picture of the AVR layout as a list of dictionaries
mainlist = []

# Assuming the user has given a name then do our thing!
if args.in_fname is not None and os.path.isfile(args.in_fname):
    print("Creating:", args.out_name)
    # following two lines are the classic way to invoke ElementTree to read an XML then get access to the
    # root from which access to all other data then occurs
    tree = et.parse(args.in_fname)
    root = tree.getroot()
    # So the first thing I search for is the "memory-segment" entry with attribute name='MAPPED_IO'
    # this has the start/length of the SFRs (start is bound to be 0x20, it's the length I need to
    # later build the struct that covers the entire SFR region)
    io_node = root.find(".//memory-segment[@name='MAPPED_IO']")
    sfr_start = io_node.attrib['start']
    sfr_size = io_node.attrib['size']
    # The "interesting stuff" (as far as this program is concerned) is then the "modules" which are things
    # like "UART", "TIMER_COUNTER_1" and so on.
    modules = root.find("modules")
    # this then iterates over each module found...
    for mod in modules.findall("module"):
        # rather curiously there are two "modules" called "FUSE" and "LOCKBIT" - I want to ignore them...
        if mod.attrib['name'] in ['FUSE', 'LOCKBIT']:
            continue
        # To keep the user entertained with some output - print the name of each module as I find it...
        print("===============", mod.attrib['name'], "===============")
        # Now there's a load of data for each "module" that I'm not interested in. All I want are the registers
        # and bits and these appear under one or more "register-groups"
        rg = mod.find("register-group")
        # then in each register group iterate through the individual registers..
        for reg in rg.findall("register"):
            # for each register pick out the useful bits of information
            addr = int(reg.attrib['offset'], 0)
            name = reg.attrib['name']
            capt = reg.attrib['caption']
            sz = int(reg.attrib['size'])
            # use the following to add extra detail if more than one byte involved
            xtra = ""
            if sz != 1:
                xtra = str(sz) + " bytes"
            print(name, "addr=", hex(addr), xtra, "// ", capt)
            # Have a look to see if there is a "bitfield" defined for this register
            bits = reg.findall("bitfield")
            # going to create a list of tuples (eventually sorted and duplicates removed) for any groups of bits
            bitlist = []
            if len(bits) != 0:
                # if there is/are bitfields then work through each entry in turn
                for bit in bits:
                    # int(x, 0) converts "0xNN" into an integer value - unfortunately the XML only holds these
                    # as a "mask" so if it's bits 3,4,5,6 the mask will be 0x78 and so on - need to process this
                    # later to get the lowest bit (3 in this example) and the starting bit position. For the
                    # lowest bit set I found something useful on StackOverflow which is at the start of this file
                    # for the number of bits set in a mask I found a very clever technique in another answer
                    # on StackOverflow - you use bit() to convert the mask to a "10101.." string then use count('1')
                    # on this to find out how many bits there are (as it happens they're always adjacent in fact)
                    mask = int(bit.attrib['mask'], 0)
                    bitlist.append((lowestSet(mask), bin(mask).count('1'), bit.attrib['name'], bit.attrib['caption']))
                for n in sorted(bitlist):
                    print(n)
            # now we assume we are going to this register/bits as a whole new entry in mainlist[]. However it turns
            # out the XML may have several different register/bit definitions in different places for the same
            # register - but you can spot this because you have already seen the address used. (BTW this all occurs
            # with a register like TIMSK that may have some TMR_0 bits defined under the section for "TIMER 0" but
            # then has some more bits defined later under "TIMER 1" and so on)
            do_add = 1
            # so now we check to see if the address of the register we're currently looking at was already seen
            # and recorded in mainlist[]. If it has been then what we need to do is extract the existing "bitlist"
            # (which is a list of tuples), then append each new tuple we've just found to this. However that may
            # lead to duplicates.
            for n in mainlist:
                if n['addr'] == addr:
                    # so pull the "bits" from the existing entry that was found to have the same address
                    updated_bits = n['bits']
                    # then append each new bit entry tuple to this..
                    for entry in bitlist:
                        do_add = 1
                        for eb in updated_bits:
                            if entry[0] == eb[0]:
                                do_add = 0
                        if do_add:
                            updated_bits.append(entry)
                    # I'll leave this (one of my development print()s as I found it MOST useful!)
                    # print("YOIKS!", "now=", sorted(nodups))
                    # now search the entrie mainlist[] again to find the index (i) of the one where we found the
                    # existing entry for the same address
                    for i in range(0, len(mainlist)):
                        # and when we stumble upon it..
                        if mainlist[i]['addr'] == addr:
                            # replace what was there with new details including the sorted, duplicate removed list of bits
                            mainlist[i] = {'addr': addr, 'name': name, 'size': sz, 'caption': capt, 'bits': sorted(updated_bits)}
                    # as we've updated an existing entry we don't want to add the data as a new one so..
                    do_add = 0
            # if the address has not occurred before then just add the details including the sorted list of bits -
            # it sort by default on the first item in the tuple which is the bit position
            if do_add:
                mainlist.append({'addr': addr, 'name': name, 'size': sz, 'caption': capt, 'bits': sorted(bitlist)})
    # The order of the "modules" in the XML is arbitrary and does not follow address order so now we sort the mainlist
    # of dictionaries using the 'addr' field in each one. Again this clever technique came from Stack Overflow
    mainlist = sorted(mainlist, key=lambda k: k['addr'])
    # finally entertain the user with something interesting looking (good for debugging too!)
    print("\n++++++++++ All of that data from XML now stored as.... +++++++++++\n")
    for ent in mainlist:
        print(hex(ent['addr']), ent)

    # So we arrive here with mainlist[] fully populated with the complete info of all registers/bits stripped
    #  from the XMLso and the list now ordered by address. Now it's time to generate some output
    regidx = 0
    # remember the "MAPPED_IO" which was the first thing taken from the XML - this is where we use the sfr_start/size
    # we pulled from it at that time
    addr = int(sfr_start, 0)
    # this is just standard Python file IO - open xxx.h as a writable text file..
    hdr = open(args.out_name, "wt")
    # the preamble is a fixed text so write that now...
    hdr.write("#include <stdint.h>\n\ntypedef struct {\n")
    # now we build a struct that will span sfr_start to sfr_start+sfr_size (remember int(x,0) converts "0xNN" to int)
    # Oh and if you are wondering why this is a while() loop and not a for() loop it's because in Python (I found
    # out the hard way!) you cannot use "for x in range(start,end)" and the modify x within the loop to skip some values
    # the range() builds a list at the very start and x will be set to every member in that list for each iteration
    # of the loop - updates to the iteration variable are over-written!
    while addr < (int(sfr_start, 0) + int(sfr_size,0)):
        # now for each address in the SFR range we see if the next mainlist[] entry has something for it
        if mainlist[regidx]['addr'] == addr:
            # if here then this address has an entry in mainlist[] so now the question is "is it a whole register or
            # is it a group of bits?". Whole registers are things like PORTB, ADC, OCR0 and so on, while registers with
            # (named) bits are things like UCSRA, TWCR and so on. For a whole register with anonymous bits then
            # just generate something like:
            #
            # union {
            # 	uint8_t byte; // (@ 0x32) Port D Data Register
            # 	struct {
            # 		int b0:1;
            # 		int b1:1;
            # 		int b2:1;
            # 		int b3:1;
            # 		int b4:1;
            # 		int b5:1;
            # 		int b6:1;
            # 		int b7:1;
            # 	} bits;
            # } PORTD;
            #
            # while for a register with named bits generate something like:
            #
            # union {
            #     uint8_t byte; // (@ 0x2e) SPI Status Register
            #     struct {
            #         int SPI2X:1; // b0 Double SPI Speed Bit
            #         int unused:5; // b1
            #         int WCOL:1; // b6 Write Collision Flag
            #         int SPIF:1; // b7 SPI Interrupt Flag
            #     } bits;
            # } SPSR;
            #
            #
            # If it is a whole register then it might be more than one byte so need to decide to uint8_t, uint16_t
            # and so on (I'm hoping they haven't got one defined as 'size':3 because that would lead to uint24_t
            # as I just multiply by 8!!)
            hdr.write("\tunion {\n\t\tuint" + str(8 * mainlist[regidx]['size']) + "_t byte; // (@ " + str(hex(addr)) + ") " + mainlist[regidx]['caption'] + "\n\t\tstruct {\n")
            # now for a whole register just write bN fields for the number of bits there are
            if len(mainlist[regidx]['bits']) == 0:
                for b in range(0, 8 * mainlist[regidx]['size']):
                    hdr.write("\t\t\tint b" + str(b) + ":1;\n")
            else:
                # So this is the complicated bit when there are named bits defined
                bitpos = 0;
                for b in mainlist[regidx]['bits']:
                    # We have tuples like (2, 5, 'FOO') which means FOO is at bit position 2 and spans 5 bits but
                    # some of the structs have "gaps" that are unused and we need to fill these with a padding
                    # entry to define "unusedN", the gap is padded using the following...
                    if b[0] > bitpos:
                        hdr.write("\t\t\tint unused"+ str(bitpos) + ":" + str(b[0] - bitpos) + "; // b" + str(bitpos) + "\n")
                        # and step bitpos on to the bit position of the enrty we're about to write
                        bitpos = b[0]
                    # then the actual named "FOO:5" entry is created by this...
                    hdr.write("\t\t\tint " + b[2] + ":" + str(b[1]) + "; // b" + str(b[0]) + " " + b[3] + "\n")
                    bitpos += b[1]
            hdr.write("\t\t} bits;\n\t} " + mainlist[regidx]['name'] + ";\n")
            # following adds 0 for size:1 entries but is mainly here for multi-byte entries so that addr can be
            # stepped on for uint16_t registers and so on
            addr += int(mainlist[regidx]['size']) - 1
            # now step the mainlist[] index on to the next entry
            regidx += 1
            # this may look "odd" but it prevents regidx trying to index beyond the end of mainlist and setting it
            # to 1 is benign as "addr" has already moved on so there's no chance of it matching as it's now "behind"
            # (hope that makes sense!)
            if regidx >= len(mainlist):
                regidx = 1
        else:
            # this just writes an unused0xNN entry for each byte that has nothing in mainlist[]
            hdr.write("\tuint8_t unused" + str(hex(addr)) + ";\n")
        addr += 1
    # then just finish with the closing part of the struct{} definition and we're all done! :-)
    hdr.write("} SFRS_t;\n\n#define USE_SFRS(x) volatile SFRS_t * x = (SFRS_t *)" + sfr_start + ";")
    # BTW I wanted to call the whole thing "AVR" not "SFRS" but the compiler alredy defines "AVR"
    hdr.close()
else:
    print("No valid input file")

If you dabble in Python then you should be able to write this to a .py file (mine is called avrread.py) and then simply run it with:

python avrread.py

If you do that it will say something like:

usage: avrread.py [-h] -i IN_FNAME [-o OUT_NAME] [-q] [-v]

Read Atmel XML (version 1.0)

optional arguments:
  -h, --help            show this help message and exit
  -i IN_FNAME, --input IN_FNAME
                        name of .XML file to read as input
  -o OUT_NAME, --output OUT_NAME
                        Name of output file (overides default)
  -q, --quiet           Don't print to console
  -v, --verbose         Show developer info

The non-optional parameter there is -i so you actually run it with something like:

python avrread.py -i ATmega16.atdf

Where ATmega16.atdf is one of the XML files taken from the "packs" installation in your AS7 - pick anything you like the look of. When run it will produce output something like:

Creating: ATmega16.h
=============== TIMER_COUNTER_0 ===============
TCCR0 addr= 0x53  //  Timer/Counter Control Register
(0, 3, 'CS0', 'Clock Selects')
(3, 1, 'WGM01', 'Waveform Generation Mode 1')
(4, 2, 'COM0', 'Compare Match Output Modes')
(6, 1, 'WGM00', 'Waveform Generation Mode 0')
(7, 1, 'FOC0', 'Force Output Compare')
TCNT0 addr= 0x52  //  Timer/Counter Register
OCR0 addr= 0x5c  //  Output Compare Register
TIMSK addr= 0x59  //  Timer/Counter Interrupt Mask Register
(0, 1, 'TOIE0', 'Timer/Counter0 Overflow Interrupt Enable')
(1, 1, 'OCIE0', 'Timer/Counter0 Output Compare Match Interrupt register')
TIFR addr= 0x58  //  Timer/Counter Interrupt Flag register
(0, 1, 'TOV0', 'Timer/Counter0 Overflow Flag')
(1, 1, 'OCF0', 'Output Compare Flag 0')
SFIOR addr= 0x50  //  Special Function IO Register
(0, 1, 'PSR10', 'Prescaler Reset Timer/Counter1 and Timer/Counter0')
=============== TIMER_COUNTER_1 ===============
TIMSK addr= 0x59  //  Timer/Counter Interrupt Mask Register
(2, 1, 'TOIE1', 'Timer/Counter1 Overflow Interrupt Enable')
(3, 1, 'OCIE1B', 'Timer/Counter1 Output CompareB Match Interrupt Enable')
(4, 1, 'OCIE1A', 'Timer/Counter1 Output CompareA Match Interrupt Enable')
(5, 1, 'TICIE1', 'Timer/Counter1 Input Capture Interrupt Enable')
TIFR addr= 0x58  //  Timer/Counter Interrupt Flag register
(2, 1, 'TOV1', 'Timer/Counter1 Overflow Flag')
(3, 1, 'OCF1B', 'Output Compare Flag 1B')
(4, 1, 'OCF1A', 'Output Compare Flag 1A')
(5, 1, 'ICF1', 'Input Capture Flag 1')
TCCR1A addr= 0x4f  //  Timer/Counter1 Control Register A
(0, 2, 'WGM1', 'Waveform Generation Mode')
(2, 1, 'FOC1B', 'Force Output Compare 1B')
(3, 1, 'FOC1A', 'Force Output Compare 1A')
(4, 2, 'COM1B', 'Compare Output Mode 1B, bits')
(6, 2, 'COM1A', 'Compare Output Mode 1A, bits')
TCCR1B addr= 0x4e  //  Timer/Counter1 Control Register B
(0, 3, 'CS1', 'Prescaler source of Timer/Counter 1')
(3, 2, 'WGM1', 'Waveform Generation Mode')
(6, 1, 'ICES1', 'Input Capture 1 Edge Select')
(7, 1, 'ICNC1', 'Input Capture 1 Noise Canceler')
TCNT1 addr= 0x4c 2 bytes //  Timer/Counter1  Bytes
OCR1A addr= 0x4a 2 bytes //  Timer/Counter1 Output Compare Register  Bytes
OCR1B addr= 0x48 2 bytes //  Timer/Counter1 Output Compare Register  Bytes
ICR1 addr= 0x46 2 bytes //  Timer/Counter1 Input Capture Register  Bytes
=============== EXTERNAL_INTERRUPT ===============
GICR addr= 0x5b  //  General Interrupt Control Register
(0, 1, 'IVCE', 'Interrupt Vector Change Enable')
(1, 1, 'IVSEL', 'Interrupt Vector Select')
(5, 1, 'INT2', 'External Interrupt Request 2 Enable')
(6, 2, 'INT', 'External Interrupt Request 1 Enable') 
       etc.

that just shows it is reading the XML OK and picking the "interesting bits" from it (have a look at the Python if you want to know how). It then outputs a more "internal" representation of the data it has culled from the XML:

++++++++++ All of that data from XML now stored as.... +++++++++++

0x20 {'name': 'TWBR', 'caption': 'TWI Bit Rate register', 'bits': [], 'size': 1, 'addr': 32}
0x21 {'name': 'TWSR', 'caption': 'TWI Status Register', 'bits': [(0, 2, 'TWPS', 'TWI Prescaler'), (3, 5, 'TWS', 'TWI Status')], 'size': 1, 'addr': 33}
0x22 {'name': 'TWAR', 'caption': 'TWI (Slave) Address register', 'bits': [(0, 1, 'TWGCE', 'TWI General Call Recognition Enable Bit'), (1, 7, 'TWA', 'TWI (Slave) Address register Bits')], 'size': 1, 'addr': 34}
0x23 {'name': 'TWDR', 'caption': 'TWI Data register', 'bits': [], 'size': 1, 'addr': 35}
0x24 {'name': 'ADC', 'caption': 'ADC Data Register  Bytes', 'bits': [], 'size': 2, 'addr': 36}
0x26 {'name': 'ADCSRA', 'caption': 'The ADC Control and Status register', 'bits': [(0, 3, 'ADPS', 'ADC  Prescaler Select Bits'), (3, 1, 'ADIE', 'ADC Interrupt Enable'), (4, 1, 'ADIF', 'ADC Interrupt Flag'), (5, 1, 'ADATE', 'When this bit is written to one,the Timer/Counter2 prescaler will be reset.The bit will be cleared by hardware after the operation is performed.Writing a zero to this bit will have no effect.This bit will always be read as zero if Timer/Counter2 is clocked by the internal CPU clock.If this bit is written when Timer/Counter2 is operating in asynchronous mode,the bit will remain one until the prescaler has been reset.'), (6, 1, 'ADSC', 'ADC Start Conversion'), (7, 1, 'ADEN', 'ADC Enable')], 'size': 1, 'addr': 38}
   etc.

and finally it does what it's supposed to and creates a .h file with the same name as the .atdf you used as input:

#include <stdint.h>

typedef struct {
	union {
		uint8_t byte; // (@ 0x20) TWI Bit Rate register
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
		} bits;
	} TWBR;
	union {
		uint8_t byte; // (@ 0x21) TWI Status Register
		struct {
			int TWPS:2; // b0 TWI Prescaler
			int unused2:1; // b2
			int TWS:5; // b3 TWI Status
		} bits;
	} TWSR;
	union {
		uint8_t byte; // (@ 0x22) TWI (Slave) Address register
		struct {
			int TWGCE:1; // b0 TWI General Call Recognition Enable Bit
			int TWA:7; // b1 TWI (Slave) Address register Bits
		} bits;
	} TWAR;
	union {
		uint8_t byte; // (@ 0x23) TWI Data register
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
		} bits;
	} TWDR;

and that's kind of the point. It has scoured the XML and produce a structure definition of the entire SFR are of the chosen AVR.

 

As the comment in the Python notes you can then use it like this...

#include "ATmega16.h"

USE_SFRS(pSFR);

int main(void)
{
    pSFR->DDRB.byte = 0xFF;
    pSFR->UCSRB.bits.TXEN = 1;
    while (1) 
    {
	pSFR->PORTB.byte ^= (1 << 3);
    }
}

The key thing here being that you just #include the generated header and then invoke USE_SFR() and give the name for a structure pointer you would like to use.

 

Now when you type in Studio you will find things like this happening...

 

 

 

 

I am being pestered by cats as I type this but after I've been out for a walk I'll post some generated .h files for some popular AVRs.

 

Have fun and let me know what works/doesn't work or how you think it could be improved.

Last Edited: Tue. Apr 5, 2016 - 10:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PS forgot the two I've been using to test this...

 

 

Attachment(s): 

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

clawson wrote:
pSFR->UCSRB.bits.TXEN = 1;

If you make the bits structure anonymous, can you then use pSFR->UCSRB.TXEN ?

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

Love it!!!

 

theusch wrote:
If you make the bits structure anonymous, can you then use pSFR->UCSRB.TXEN ?

+1

ɴᴇᴛɪᴢᴇᴎ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
# AVR. In this case don't use "#include <avr/io.h>" but instead just do something like this:            #

What's the problem with using such header file in conjunction with avr/io.h?

Or did you mean to say it's not necessary to include it if one is going to entirely abide by this new way of addressing hardware?

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Sat. Apr 2, 2016 - 05:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or did you mean to say it's not necessary

Yup I meant "not necessary".

 

As for simplifying the syntax, I tried to make this as generic as possible so it will work with any C compiler, not just avr-gcc. AFAIK it is completely standard/generic and should work with all.

 

However I did consider invoking a GCC extension so that instead of:

typedef struct {
	union {
		uint8_t byte; // (@ 0x20) TWI Bit Rate register
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
		} bits;
	} TWBR;
	union {
		uint8_t byte; // (@ 0x21) TWI Status Register
		struct {
			int TWPS:2; // b0 TWI Prescaler
			int unused2:1; // b2
			int TWS:5; // b3 TWI Status
		} bits;
	} TWSR;

it would generate:

typedef struct {
	union {
		uint8_t byte; // (@ 0x20) TWI Bit Rate register
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
		}; // anonymous
	} TWBR;
	union {
		uint8_t byte; // (@ 0x21) TWI Status Register
		struct {
			int TWPS:2; // b0 TWI Prescaler
			int unused2:1; // b2
			int TWS:5; // b3 TWI Status
		}; // anonymous
	} TWSR;

where the struct in the union had no name. Then you could use this in the C:

    pSFR->UCSRB.TXEN = 1;
    while (1) 
    {
	pSFR->PORTB.b3 = pSFR->PINC.b2;
    }

so I will add a command line option "-a, --anonymous - generate anonymous structs (GCC only)" then the user can choose to exercise this GCC only feature.

 

I also thought about a version which drops the unions. So you either have a "full" register and it's just uint8_t/uint16_t with no bitfields or you have the registers with named bit and nothing but the named bits:

typedef struct {
	uint8_t TWBR; // (@ 0x20) TWI Bit Rate register
	struct { // (@ 0x21) TWI Status Register
		int TWPS:2; // b0 TWI Prescaler
		int unused2:1; // b2
		int TWS:5; // b3 TWI Status
	} TWSR;

Actually when I was developing it this is what my first version did. But then I thought about people wanting to do something like:

#define RED_LED pSFR->PORTB.bits.b3;

..

   RED_LED = 1;

where they might want to access the individual bits in a "whole register" and equally those who might want to:

pSFR->UCSRB.byte = (1 << TXEN) | (1 << RXEN);

// instead of

pSFR->UCSRB.TXEN = 1;
pSFR->UCSRB.RXEN = 1;

and set multiple bits in a "named bits register" all in one go. So I switched to making a union of byte/bitfields for every entry instead. But as I say I might add "-n, --no_union - only one entry per register"

 

Last Edited: Sat. Apr 2, 2016 - 06:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so here's a .zip file with 124 generated headers in it for every ATDF file in "\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATmega_DFP\1.0.90\atdf\". That's all the mega AVRs supported by AS7

Attachment(s): 

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

OK so the following is V1.1 code. The changes are:

 

1) --quiet and --verbose now wired up

2) New -a/--anonymous option that generates anonymous structs in unions for use with GCC

3) New -n/--no_union option that only generates either a single byte/word for "whole" registers or a single struct when there are named bits.

 

#########################################################################################################
#                                          AVRRead                                                      #
# A utility to read the XML files (probably .atdf in fact) in a Studio 6/7 installation and use         #
# the data within to define one big structure to overlay the SFR area of any AVR. Just use:             #
#                                                                                                       #
# python avrread.py -i ATmgea16.atdf                                                                    #
#                                                                                                       #
# or any other .atdf to generat an ATmega16.h (or whatever) header file for use in programming the      #
# AVR. In this case don't use "#include <avr/io.h>" but instead just do something like this:            #
#                                                                                                       #
#        #include "ATmega16.h"                                                                          #
#                                                                                                       #
#        USE_SFRS(pSFR);                                                                                #
#                                                                                                       #
#        int main(void)                                                                                 #
#        {                                                                                              #
#            pSFR->DDRB.byte = 0xFF;                                                                    #
#            pSFR->UCSRB.bits.TXEN = 1;                                                                 #
#            while (1)                                                                                  #
#            {                                                                                          #
#                pSFR->PORTB.byte ^= (1 << 3);                                                          #
#            }                                                                                          #
#        }                                                                                              #
#                                                                                                       #
# Use the USE_SFR() macro to name a struct pointer variable (like "pSFR") that you then want to         #
# use to access the registers in the code.                                                              #
#                                                                                                       #
#                        by Cliff Lawson                                                                #
#                                                                                                       #
# Licence: I need beer - see what you can do!                                                           #
#########################################################################################################

# following ("from...") line is useful if you are trying to make Python 3 code run in Python 2
# (however things like "argparse" here means this program is 3.2+ anyway.
# from __future__ import print_function
import sys
import os
import argparse
import xml.etree.ElementTree as et

# found this on StackOverflow - it simply returns the lowest bit that is set in a byte
def lowestSet(int_type):
    low = (int_type & -int_type)
    lowBit = -1
    while (low):
        low >>= 1
        lowBit += 1
    return(lowBit)


# often find this useful to check the raw command line args
# for n in range(0, len(sys.argv)):
#	print(n, sys.argv[n])

# I like argparse - it makes for very clean command line interfaces
parser = argparse.ArgumentParser(description='Read Atmel XML (version 1.1)')
parser.add_argument("-i", "--input", dest='in_fname', help="name of .XML file to read as input", required=True)
parser.add_argument("-o", "--output", dest='out_name', help="Name of output file (overides default)")
parser.add_argument("-q", "--quiet", dest='quiet', action="store_true", help="Don't print to console")
parser.add_argument("-v", "--verbose", dest='verbose', action="store_true", help="Show developer info")
parser.add_argument("-a", "--anonymous", dest='anon', action="store_true", help="Use anonymous structs (GCC only)")
parser.add_argument("-n", "--no_union", dest='nounion', action="store_true", help="No unions - just one entry per register")

# my one argument with argparse is that if you run the app without args it doesn't show help info, so
# this will achieve that...
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit(1)

# this actually runs the argument parser on sys.argv
args = parser.parse_args()

# the user has the opportunity to use -o to set an output filename but if they haven't used that this
# takes the input .atdf/.xml filename and replaces the extension with ".h" to create the output name
if args.out_name is None:
    args.out_name = os.path.splitext(args.in_fname)[0]+".h"

# The following creates an empty list. As the XML is parsed this will be appened()'d too to build a complete
# picture of the AVR layout as a list of dictionaries
mainlist = []

# Assuming the user has given a name then do our thing!
if args.in_fname is not None and os.path.isfile(args.in_fname):
    if not args.quiet:
        print("Creating:", args.out_name)
    # ===================================== PART 1 (process the XML) ======================================
    # following two lines are the classic way to invoke ElementTree to read an XML then get access to the
    # root from which access to all other data then occurs
    tree = et.parse(args.in_fname)
    root = tree.getroot()
    # So the first thing I search for is the "memory-segment" entry with attribute name='MAPPED_IO'
    # this has the start/length of the SFRs (start is bound to be 0x20, it's the length I need to
    # later build the struct that covers the entire SFR region)
    io_node = root.find(".//memory-segment[@name='MAPPED_IO']")
    sfr_start = io_node.attrib['start']
    sfr_size = io_node.attrib['size']
    # The "interesting stuff" (as far as this program is concerned) is then the "modules" which are things
    # like "UART", "TIMER_COUNTER_1" and so on.
    modules = root.find("modules")
    # this then iterates over each module found...
    for mod in modules.findall("module"):
        # rather curiously there are two "modules" called "FUSE" and "LOCKBIT" - I want to ignore them...
        if mod.attrib['name'] in ['FUSE', 'LOCKBIT']:
            continue
        # To keep the user entertained with some output - print the name of each module as I find it...
        if not args.quiet:
            print("===============", mod.attrib['name'], "===============")
        # Now there's a load of data for each "module" that I'm not interested in. All I want are the registers
        # and bits and these appear under one or more "register-groups"
        rg = mod.find("register-group")
        # then in each register group iterate through the individual registers..
        for reg in rg.findall("register"):
            # for each register pick out the useful bits of information
            addr = int(reg.attrib['offset'], 0)
            name = reg.attrib['name']
            capt = reg.attrib['caption']
            sz = int(reg.attrib['size'])
            # use the following to add extra detail if more than one byte involved
            xtra = ""
            if sz != 1:
                xtra = str(sz) + " bytes"
            if not args.quiet:
                print(name, "addr=", hex(addr), xtra, "// ", capt)
            # Have a look to see if there is a "bitfield" defined for this register
            bits = reg.findall("bitfield")
            # going to create a list of tuples (eventually sorted and duplicates removed) for any groups of bits
            bitlist = []
            if len(bits) != 0:
                # if there is/are bitfields then work through each entry in turn
                for bit in bits:
                    # int(x, 0) converts "0xNN" into an integer value - unfortunately the XML only holds these
                    # as a "mask" so if it's bits 3,4,5,6 the mask will be 0x78 and so on - need to process this
                    # later to get the lowest bit (3 in this example) and the starting bit position. For the
                    # lowest bit set I found something useful on StackOverflow which is at the start of this file
                    # for the number of bits set in a mask I found a very clever technique in another answer
                    # on StackOverflow - you use bit() to convert the mask to a "10101.." string then use count('1')
                    # on this to find out how many bits there are (as it happens they're always adjacent in fact)
                    mask = int(bit.attrib['mask'], 0)
                    bitlist.append((lowestSet(mask), bin(mask).count('1'), bit.attrib['name'], bit.attrib['caption']))
                if not args.quiet:
                    for n in sorted(bitlist):
                        print(n)
            # now we assume we are going to this register/bits as a whole new entry in mainlist[]. However it turns
            # out the XML may have several different register/bit definitions in different places for the same
            # register - but you can spot this because you have already seen the address used. (BTW this all occurs
            # with a register like TIMSK that may have some TMR_0 bits defined under the section for "TIMER 0" but
            # then has some more bits defined later under "TIMER 1" and so on)
            do_add = 1
            # so now we check to see if the address of the register we're currently looking at was already seen
            # and recorded in mainlist[]. If it has been then what we need to do is extract the existing "bitlist"
            # (which is a list of tuples), then append each new tuple we've just found to this. However that may
            # lead to duplicates.
            for n in mainlist:
                if n['addr'] == addr:
                    # so pull the "bits" from the existing entry that was found to have the same address
                    updated_bits = n['bits']
                    # then append each new bit entry tuple to this..
                    for entry in bitlist:
                        do_add = 1
                        for eb in updated_bits:
                            if entry[0] == eb[0]:
                                do_add = 0
                        if do_add:
                            updated_bits.append(entry)
                    # I'll leave this (one of my development print()s as I found it MOST useful!)
                    # print("YOIKS!", "now=", sorted(nodups))
                    # now search the entrie mainlist[] again to find the index (i) of the one where we found the
                    # existing entry for the same address
                    for i in range(0, len(mainlist)):
                        # and when we stumble upon it..
                        if mainlist[i]['addr'] == addr:
                            # replace what was there with new details including the sorted, duplicate removed list of bits
                            mainlist[i] = {'addr': addr, 'name': name, 'size': sz, 'caption': capt, 'bits': sorted(updated_bits)}
                    # as we've updated an existing entry we don't want to add the data as a new one so..
                    do_add = 0
            # if the address has not occurred before then just add the details including the sorted list of bits -
            # it sort by default on the first item in the tuple which is the bit position
            if do_add:
                mainlist.append({'addr': addr, 'name': name, 'size': sz, 'caption': capt, 'bits': sorted(bitlist)})
    # The order of the "modules" in the XML is arbitrary and does not follow address order so now we sort the mainlist
    # of dictionaries using the 'addr' field in each one. Again this clever technique came from Stack Overflow
    mainlist = sorted(mainlist, key=lambda k: k['addr'])
    # finally entertain the user with something interesting looking (good for debugging too!)
    if args.verbose:
        print("\n++++++++++ All of that data from XML now stored as.... +++++++++++\n")
        for ent in mainlist:
            print(hex(ent['addr']), ent)

    # ===================================== PART 2 (generate the output) ======================================
    # So we arrive here with mainlist[] fully populated with the complete info of all registers/bits stripped
    #  from the XMLso and the list now ordered by address. Now it's time to generate some output
    regidx = 0
    # remember the "MAPPED_IO" which was the first thing taken from the XML - this is where we use the sfr_start/size
    # we pulled from it at that time
    addr = int(sfr_start, 0)
    # this is just standard Python file IO - open xxx.h as a writable text file..
    hdr = open(args.out_name, "wt")
    # the preamble is a fixed text so write that now...
    hdr.write("#include <stdint.h>\n\ntypedef struct {\n")
    # now we build a struct that will span sfr_start to sfr_start+sfr_size (remember int(x,0) converts "0xNN" to int)
    # Oh and if you are wondering why this is a while() loop and not a for() loop it's because in Python (I found
    # out the hard way!) you cannot use "for x in range(start,end)" and the modify x within the loop to skip some values
    # the range() builds a list at the very start and x will be set to every member in that list for each iteration
    # of the loop - updates to the iteration variable are over-written!
    while addr < (int(sfr_start, 0) + int(sfr_size,0)):
        # now for each address in the SFR range we see if the next mainlist[] entry has something for it
        if mainlist[regidx]['addr'] == addr:
            # if here then this address has an entry in mainlist[] so now the question is "is it a whole register or
            # is it a group of bits?". Whole registers are things like PORTB, ADC, OCR0 and so on, while registers with
            # (named) bits are things like UCSRA, TWCR and so on. For a whole register with anonymous bits then
            # just generate something like:
            #
            # union {
            # 	uint8_t byte; // (@ 0x32) Port D Data Register
            # 	struct {
            # 		int b0:1;
            # 		int b1:1;
            # 		int b2:1;
            # 		int b3:1;
            # 		int b4:1;
            # 		int b5:1;
            # 		int b6:1;
            # 		int b7:1;
            # 	} bits;
            # } PORTD;
            #
            # while for a register with named bits generate something like:
            #
            # union {
            #     uint8_t byte; // (@ 0x2e) SPI Status Register
            #     struct {
            #         int SPI2X:1; // b0 Double SPI Speed Bit
            #         int unused:5; // b1
            #         int WCOL:1; // b6 Write Collision Flag
            #         int SPIF:1; // b7 SPI Interrupt Flag
            #     } bits;
            # } SPSR;
            #
            #
            # If it is a whole register then it might be more than one byte so need to decide to uint8_t, uint16_t
            # and so on (I'm hoping they haven't got one defined as 'size':3 because that would lead to uint24_t
            # as I just multiply by 8!!)
            whole_reg = len(mainlist[regidx]['bits']) == 0
            if args.nounion:
                if whole_reg:
                    hdr.write("\tuint" + str(8 * mainlist[regidx]['size']) + "_t " + mainlist[regidx]['name'] + "; // (@ " + str(hex(addr)) + ") " + mainlist[regidx]['caption'])
                else:
                    hdr.write("\tstruct { // (@ " + str(hex(addr)) + ") " + mainlist[regidx]['caption'] + "\n")
            else:
                hdr.write("\tunion {\n\t\tuint" + str(8 * mainlist[regidx]['size']) + "_t byte; // (@ " + str(hex(addr)) + ") " + mainlist[regidx]['caption'] + "\n\t\tstruct {\n")
            # now for a whole register just write bN fields for the number of bits there are
            if whole_reg and not args.nounion:
                for b in range(0, 8 * mainlist[regidx]['size']):
                    hdr.write("\t\t\tint b" + str(b) + ":1;\n")
            else:
                # So this is the complicated bit when there are named bits defined
                bitpos = 0;
                for b in mainlist[regidx]['bits']:
                    # We have tuples like (2, 5, 'FOO') which means FOO is at bit position 2 and spans 5 bits but
                    # some of the structs have "gaps" that are unused and we need to fill these with a padding
                    # entry to define "unusedN", the gap is padded using the following...
                    if b[0] > bitpos:
                        hdr.write("\t\t\tint unused"+ str(bitpos) + ":" + str(b[0] - bitpos) + "; // b" + str(bitpos) + "\n")
                        # and step bitpos on to the bit position of the enrty we're about to write
                        bitpos = b[0]
                    # then the actual named "FOO:5" entry is created by this...
                    hdr.write("\t\t\tint " + b[2] + ":" + str(b[1]) + "; // b" + str(b[0]) + " " + b[3] + "\n")
                    bitpos += b[1]
            if args.nounion:
                if not whole_reg:
                    hdr.write("\t} " + mainlist[regidx]['name'] + ";\n")
                else:
                    hdr.write("\n")
            else:
                if args.anon:
                    hdr.write("\t\t};\n\t} " + mainlist[regidx]['name'] + ";\n")
                else:
                    hdr.write("\t\t} bits;\n\t} " + mainlist[regidx]['name'] + ";\n")
            # following adds 0 for size:1 entries but is mainly here for multi-byte entries so that addr can be
            # stepped on for uint16_t registers and so on
            addr += int(mainlist[regidx]['size']) - 1
            # now step the mainlist[] index on to the next entry
            regidx += 1
            # this may look "odd" but it prevents regidx trying to index beyond the end of mainlist and setting it
            # to 1 is benign as "addr" has already moved on so there's no chance of it matching as it's now "behind"
            # (hope that makes sense!)
            if regidx >= len(mainlist):
                regidx = 1
        else:
            # this just writes an unused0xNN entry for each byte that has nothing in mainlist[]
            hdr.write("\tuint8_t unused" + str(hex(addr)) + ";\n")
        addr += 1
    # then just finish with the closing part of the struct{} definition and we're all done! :-)
    hdr.write("} SFRS_t;\n\n#define USE_SFRS(x) volatile SFRS_t * x = (SFRS_t *)" + sfr_start + ";")
    # BTW I wanted to call the whole thing "AVR" not "SFRS" but the compiler alredy defines "AVR"
    hdr.close()
else:
    print("No valid input file")

An "anonymous" file looks like this:

	union {
		uint16_t byte; // (@ 0x24) ADC Data Register  Bytes
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
			int b8:1;
			int b9:1;
			int b10:1;
			int b11:1;
			int b12:1;
			int b13:1;
			int b14:1;
			int b15:1;
		};
	} ADC;
	union {
		uint8_t byte; // (@ 0x26) The ADC Control and Status register
		struct {
			int ADPS:3; // b0 ADC  Prescaler Select Bits
			int ADIE:1; // b3 ADC Interrupt Enable
			int ADIF:1; // b4 ADC Interrupt Flag
			int ADATE:1; // b5 When this bit is written to one,the Timer/Counter2 prescaler will be reset.(stupidly long comment removed)
			int ADSC:1; // b6 ADC Start Conversion
			int ADEN:1; // b7 ADC Enable
		};
	} ADCSRA;
	union {
		uint8_t byte; // (@ 0x27) The ADC multiplexer Selection Register
		struct {
			int MUX:5; // b0 Analog Channel and Gain Selection Bits
			int ADLAR:1; // b5 Left Adjust Result
			int REFS:2; // b6 Reference Selection Bits
		};
	} ADMUX;

A "no union" file looks like this:

	uint16_t ADC; // (@ 0x24) ADC Data Register  Bytes
	struct { // (@ 0x26) The ADC Control and Status register
			int ADPS:3; // b0 ADC  Prescaler Select Bits
			int ADIE:1; // b3 ADC Interrupt Enable
			int ADIF:1; // b4 ADC Interrupt Flag
			int ADATE:1; // b5 When this bit is written to one,the Timer/Counter2 prescaler will be reset.(...stupidly long text removed!)
			int ADSC:1; // b6 ADC Start Conversion
			int ADEN:1; // b7 ADC Enable
	} ADCSRA;
	struct { // (@ 0x27) The ADC multiplexer Selection Register
			int MUX:5; // b0 Analog Channel and Gain Selection Bits
			int ADLAR:1; // b5 Left Adjust Result
			int REFS:2; // b6 Reference Selection Bits
	} ADMUX;

 

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

Cliff,

 

I tried a simple program in AS7 b790.

/*
 * cliff_header.c
 *
 * Created: 03/04/2016 10:14:55
 * Author : David Prentice
 */

//#include <avr/io.h>
#include "cliff_ATmega328P.h"

USE_SFRS(pSFR);

int main(void)
{
    /* Replace with your application code */
    pSFR->DDRB.bits.b5 = 1;
    while (1) {
        pSFR->PORTB.bits.b5 ^= 1;
    }
}

and started the Simulator.     For some reason,  pSFR appears in the Autos Window.

If you click on the DDRB member,   it shows the bits member.

If you click on the bits member,  the Simulator crashes.    (local backend agent disconnects)

 

I suppose that I could try it with real hardware.    Yes,  local backend agent disconnects with ATMEL-ICE too.

 

I can see how "ToolTips" might be useful in the Editor.    But I can't see any advantage in trying to look in a Watch window (or Autos window).    You have to open up too many nodes.

 

It is a lot easier watching the SFR in the I/O window.    Providing I do not delve into pSFR too deeply,   the debugger does not crash.   i.e. the byte view is safe.

 

Writing header files that describe the SFR structures is infinitely better from a HLL point of view.   The Compiler can see whether you are using a field from the wrong SFR.    On the other hand,   the source code needs to be attractive to read.

 

David.

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

clawson wrote:
netizen wrote:
Or did you mean to say it's not necessary

Yup I meant "not necessary".

I've got a problem with that, actually. Suppose I have something like:

#include "ATmegaXX.h"
#include <avr/io.h>

USE_SFRS(hw);
…
    hw->ADCSRA.byte = 0;

It yields:

error: expected identifier before ‘(’ token
  hw->ADCSRA.byte = 0;
      ^

It's a pity, cause I'd like to be able to do something like what you've mentioned above:

hw->ADCSRA.byte = 1<<ADEN | 1<<ADSC;

 

I like the "anonymous" option. I suppose that would become a default for GCC users.

I would suggest finding another name for accessing the full register (all? full?), because the following seems confusing:

	union {
		uint16_t byte; // (@ 0x24) ADC Data Register  Bytes
		struct {
			int b0:1;
			int b1:1;
			…
			int b15:1;
		};
	} ADC;

In fact, ideally I'd like to access whole registers without named fields directly (like with --no_union), and whole registers with named fields indirectly (so the field access is direct). For example:

hw->ADCSRA.byte = 1<<ADEN | 1<<ADSC;
while(hw->ADCSRA.ADSC);
uint16_t result = hw->ADC;

So, sort of a mix between --no_union and --anonymous, with an emphasis on "usage flow".

 

EDIT: Might not be a good example actually, because of ADCL/ADCH… :-/

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Sun. Apr 3, 2016 - 10:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

netizen wrote:
I would suggest finding another name for accessing the full register (all? full?), because the following seems confusing

Very good point! I'd forgotten it would be applying this name to some uint16_t's.

netizen wrote:
So, sort of a mix between --no_union and --anonymous, with an emphasis on "usage flow".

Yeah I see what you mean. Will have a think about that.

david.prentice wrote:
I can see how "ToolTips" might be useful in the Editor.    But I can't see any advantage in trying to look in a Watch window (or Autos window).    You have to open up too many nodes.

That wasn't quite the design goal here - the fact you get sort of useful tooltips (as I showed above) as you edit is just serendipitous. What I was aiming for was symbolic debugging in avr-gdb in fact. The fact is that because io.h uses #define's they don't make it to the DWARF2. The way AS6/AS7 overcomes this in that debugger is to use some XML files (these ones in fact!) to put names to faces in the debugger to those anonymously defined locations. But in avr-gdb you are just left with "PORTB" being some anonymous looking 0x800017 value or whatever. If you define C symbols and -g then the plan is that those symbols make it to the DWARF2. If you use ddd (don't know about anything else!) you can use "display" (rather than "print") to put a watch on a struct and you should then be able to see the AVR register map updated at each BREAK.

 

Or so the theory goes anyway! 

 

I would like to make it "easy to use" on the authoring side too though so I totally agree with:

david.prentice wrote:
On the other hand,   the source code needs to be attractive to read.

smiley

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

 What I was aiming for was symbolic debugging in avr-gdb in fact. The fact is that because io.h uses #define's they don't make it to the DWARF2. The way AS6/AS7 overcomes this in that debugger is to use some XML files (these ones in fact!) to put names to faces in the debugger to those anonymously defined locations.

Actually, not completely true. DWARF2 contains macro information (using -g3 at least), but it is really badly encoded (which as far as I remember was the major point of DWARF4). The built-in debugger in Atmel Studio doesn't even try to read the macro information from the DWARF info (if some of you remember atbackend.exe crashing with out of resource errors in studio 5 and it growing well into 2gig memory, this was one of the reasons).

 

If you enable GDB on avr, in Atmel Studio, you will get the macro information if you evaluate it in the Watch window etc. gcc also has a feature with debug information compression that causes unused macros to not be available in the debug info. This is the case on ARM in Atmel Studio, but it seems that on AVR all the macros I tried just now comes through. 

 

The atdf in Atmel Studio is used a a device descriptor file (similar to svd etc). It is used in the device system internally in Atmel Studio (showing the IO view, memory layout, registers, access register etc etc etc). The atdf is not used directly in symbol evaluation. 

 

The header files that you shown above looks a lot like a mix of our generated xmega headers and the ARM headers... 

 

 

And, a final plug; if you are playing with Python, did you know that Atmel Studio exports a Python "runtime environment" during debug? See here for some of the hooks that you can add (I've updated the examples to something more useful which I hope will be online in the not too far future).

:: 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

To avoid the name pollution I have various options:

 

1) Switch to capitalised names using Python's .title()

2) Switch to lower case name using Python's .lower()

3) Prefix the names with something like "_"

 

Any preferences?

 

1)

	union {
		uint8_t all; // (@ 0x54) MCU Control And Status Register
		struct {
			int Porf:1; // b0 Power-on reset flag
			int Extrf:1; // b1 External Reset Flag
			int Borf:1; // b2 Brown-out Reset Flag
			int Wdrf:1; // b3 Watchdog Reset Flag
			int Jtrf:1; // b4 JTAG Reset Flag
			int unused5:1; // b5
			int Isc2:1; // b6 Interrupt Sense Control 2
			int Jtd:1; // b7 JTAG Interface Disable
		} bits;
	} Mcucsr;

2) 

	union {
		uint8_t all; // (@ 0x54) MCU Control And Status Register
		struct {
			int porf:1; // b0 Power-on reset flag
			int extrf:1; // b1 External Reset Flag
			int borf:1; // b2 Brown-out Reset Flag
			int wdrf:1; // b3 Watchdog Reset Flag
			int jtrf:1; // b4 JTAG Reset Flag
			int unused5:1; // b5
			int isc2:1; // b6 Interrupt Sense Control 2
			int jtd:1; // b7 JTAG Interface Disable
		} bits;
	} mcucsr;

3)

	union {
		uint8_t all; // (@ 0x54) MCU Control And Status Register
		struct {
			int _PORF:1; // b0 Power-on reset flag
			int _EXTRF:1; // b1 External Reset Flag
			int _BORF:1; // b2 Brown-out Reset Flag
			int _WDRF:1; // b3 Watchdog Reset Flag
			int _JTRF:1; // b4 JTAG Reset Flag
			int unused5:1; // b5
			int _ISC2:1; // b6 Interrupt Sense Control 2
			int _JTD:1; // b7 JTAG Interface Disable
		} bits;
	} _MCUCSR;

I think I might possibly favour (2) in fact.

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

Just found what I think is a fault in the XML. The ATmega16.atdf file has this:

    <module caption="" name="EXTERNAL_INTERRUPT">
      <register-group caption="" name="EXTERNAL_INTERRUPT">
        <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
          <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>              <<<<<<<< Error on this line
          <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
          <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
          <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>
        </register>

The "INT" for "Request 1 Enable" is surely called "INT1" not "INT" ? (this causes problems if is makes it all the way through to the generated C as a symbol name called "int")

 

When debugging in AS7 and looking at the Atmel I/O view that uses these XML files the error is evident...

 

 

looks like I need to check all symbol names against C reserved keywords and make sure I don't generate a symbol that is a reserved word.

 

EDIT: actually when I think about it there is a more serious error here:

caption="External Interrupt Request 1 Enable" mask="0xC0"

C0? How can it be C0 ? The datasheet says this:

 

 

so the XML is supposed to say:

        <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
          <bitfield caption="External Interrupt Request 1 Enable" mask="0x80" name="INT1"/>
          <bitfield caption="External Interrupt Request 1 Enable" mask="0x40" name="INT0"/>
          <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
          <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
          <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>
        </register>

They've somehow combined INT1/INT0 into just "INT".

Last Edited: Sun. Apr 3, 2016 - 02:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I came of this post recently: http://a3f.at/articles/register-syntax-sugar that goes through a couple of other structures... The last one using linker sections looked cool (and somewhat scary).

:: 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

Sigh... 0xC0 means that INT here spans INT0 and INT1 in the datasheet. I'll fix it in the next mega pack release :) 

:: 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

Hi Morten,

 

BTW See the edit I just made above - there's definitely a fault in your XML for the mega16. EDIT: Oh I see you did as I typed this :)

 

As to that link: Funny you should mention it but the way I originally did this was to actually instantiate a struct:

struct {
    uint8_t PORTB;
    struct {
        int TXEN:1;
        int RXEN:1;
    } UCSRB;
    etc.
} SFRS __attribute__((section(".SFRS")));

then used a linker option:

-Wl,-section-start=.SFRS=0x800020

which worked and I was surprised the linker didn't moan about me "inserting" something into the RAM layout before .data. But I didn't like it as an option as it involved the user having to make this -section-start separately from the simple #include. Before I left this idea I had a thought about a rather mad extension of the idea:

    uint8_t PORTB __attribute__((section(".PORTB")));
    struct {
        int TXEN:1;
        int RXEN:1;
    } UCSRB __attribute__((section(".UCSRB")));
    etc.

and also auto-generating:

-Wl,-section-start=.PORTB=0x800020 -Wl,-section-start=.PORTB=0x800021 etc.

which would give the user loads of individual (watchable) variables, rather than one big/complicated struct, but that -Wl,-section-start line could have 64..200 odd entries and might be a bit "unmanageable" (to put it mildly). I also toyed with the idea of putting all that in an auto-generated linker script.

 

But I wanted to keep this simple(ish!) and, if possible, standard C for all compilers and hence I decided on one all encompassing stuct{} with one pointer to it with a single, fixed base address (which is why I also went for all the "unused" padding entries).

 

I can't say I particularly like:

#define USE_SFRS(x) volatile SFRS_t * x = (SFRS_t *)0x0020;

and then:

#include ...

USE_SFRS(foo);

int main(void) {
    foo->whatever = nn;
}

but right now I cannot think of a way to do this and keep it as C variables that pass all the way through to the debugger.

 

In your link there I like the look/simplicity of "Approach VI":

struct SysTick_ __packed {
  u32 ctrl;
  u32 load;
  u32 curr;
  u32 cal;
};
#define SysTick (*(struct SysTick_ volatile *)0xE000E010)

but as he even notes himself:

A more pressing issue is that, unlike the prior approach, you can’t just write print *SysTick when it’s in scope to read out the registers in GDB.

because "SysTick" is not a C symbol but a pre-pro macro that GDB won't get to hear about.

 

I suppose that I could #define something to somehow mask "foo->" to make the code authoring more readable (even just replacing it with "bar." perhaps simply because '.' is easier to type/read than "->"?) but I cannot immediately think of something to make the authoring syntax cleaner.

Last Edited: Sun. Apr 3, 2016 - 02:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is a bit like Jame's Joyce stream of consciousness but I just had a further thought:

typedef struct {
    uint8_t _PORTB;
    struct {
        int Txen:1;
        int Rxen:1;
    } _UCSRB;
    etc.
} SFRS_t;

volatile SFRS_t * pSF = (SFRS_t *)0x0020;

#define Portb pSf->_PORTB
#define Ucsrb pSf->_UCSRB
etc.

Then the user just uses:

#include ...

int main(void) {
    Portb = 0x5A;
    Ucsrb.Rxen = 1;
}

Umm .. will have to think about this some more...

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

clawson wrote:
To avoid the name pollution I have various options:

  1. Switch to capitalised names using Python's .title()
  2. Switch to lower case name using Python's .lower()
  3. Prefix the names with something like "_"

Any preferences?

I personally prefer 2. It might not be the best choice wrt name collision though.

 

meolsen wrote:
I came of this post recently: http://a3f.at/articles/register-... that goes through a couple of other structures... The last one using linker sections looked cool (and somewhat scary).

Nice link! Approach VII definitely is the nicest from a pure code attractiveness perspective.

 

clawson wrote:
This is a bit like Jame's Joyce stream of consciousness but

I like this last idea: just as attractive to read/type as the above…

Would that make it all the way to an objdump output?

ɴᴇᴛɪᴢᴇᴎ

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

OK so I have this:

#include <avr/io.h> // just to prove there's no name pollution
#include "../../../../avrread/ATmega16.h"

USE_SFRS();

#define RED_LED portb_b5

int main(void)
{
    ddrb = 0xFF;
    ucsrb_txen = 1;
    RED_LED = 1;
    while (1)
    {
        portb ^= (1 << 3);
        ucsrb_rxen = 1;
    }
}

which is fairly easy to read. It generates this:

	ddrb = 0xFF;
  7c:	8f ef       	ldi	r24, 0xFF	; 255
  7e:	87 bb       	out	0x17, r24	; 23
	ucsrb_txen = 1;
  80:	53 9a       	sbi	0x0a, 3	; 10
	RED_LED = 1;
  82:	c5 9a       	sbi	0x18, 5	; 24
etc.

but the problem is that behind the scenes this is using:

#define USE_SFRS() SFRS_t volatile * const pSFR = (SFRS_t *)0x0020

and the AS7 debugger in the simulator cannot "see" the target of this pointer - no  idea why. If I remove "const" I can inspect the pointer target but the code generated is atrocious:

	ddrb = 0xFF;
  7c:	e0 91 60 00 	lds	r30, 0x0060
  80:	f0 91 61 00 	lds	r31, 0x0061
  84:	8f ef       	ldi	r24, 0xFF	; 255
  86:	87 8b       	std	Z+23, r24	; 0x17
	ucsrb_txen = 1;
  88:	82 85       	ldd	r24, Z+10	; 0x0a
  8a:	88 60       	ori	r24, 0x08	; 8
  8c:	82 87       	std	Z+10, r24	; 0x0a
	RED_LED = 1;
  8e:	80 8d       	ldd	r24, Z+24	; 0x18
  90:	80 62       	ori	r24, 0x20	; 32
  92:	80 8f       	std	Z+24, r24	; 0x18

as it has insisted on instantiating the pointer at 0x0060/0x0061 (and because it is "runtime variable" it cannot optimise to IN/OUT/SBI/CBI) so I have to use "const" but then the AS7 debugger gets a bit hopeless.

 

I suppose that doesn't matter because in AS7 you'd use the XML annotating debugger anyway.

 

The way all this works "behind the scenes" is:

	union {
		uint8_t all; // (@ 0x38) Port B Data Register
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
		} bits;
	} _portb;
...
	union {
		uint8_t all; // (@ 0x2a) USART Control and Status Register B
		struct {
			int txb8:1; // b0 Transmit Data Bit 8
			int rxb8:1; // b1 Receive Data Bit 8
			int ucsz2:1; // b2 Character Size
			int txen:1; // b3 Transmitter Enable
			int rxen:1; // b4 Receiver Enable
			int udrie:1; // b5 USART Data register Empty Interrupt Enable
			int txcie:1; // b6 TX Complete Interrupt Enable
			int rxcie:1; // b7 RX Complete Interrupt Enable
		} bits;
	} _ucsrb;

then..

#define portb pSFR->_portb.all
#define portb_b0 pSFR->_portb.bits.b0
#define portb_b1 pSFR->_portb.bits.b1
#define portb_b2 pSFR->_portb.bits.b2
#define portb_b3 pSFR->_portb.bits.b3
#define portb_b4 pSFR->_portb.bits.b4
#define portb_b5 pSFR->_portb.bits.b5
#define portb_b6 pSFR->_portb.bits.b6
#define portb_b7 pSFR->_portb.bits.b7

...

#define ucsrb pSFR->_ucsrb.all
#define ucsrb_txb8 pSFR->_ucsrb.bits.txb8
#define ucsrb_rxb8 pSFR->_ucsrb.bits.rxb8
#define ucsrb_ucsz2 pSFR->_ucsrb.bits.ucsz2
#define ucsrb_txen pSFR->_ucsrb.bits.txen
#define ucsrb_rxen pSFR->_ucsrb.bits.rxen
#define ucsrb_udrie pSFR->_ucsrb.bits.udrie
#define ucsrb_txcie pSFR->_ucsrb.bits.txcie
#define ucsrb_rxcie pSFR->_ucsrb.bits.rxcie

The ATmega16.h is attached...

 

BTW the USE_SFRS() is now just there to instantiate the pointer "pSFR". You don't get a choice about the name - but as it's all buried in #defines this does not matter. The only time you use pSFR is when you ask the debugger to show you everything at "*pSFR" (beneath which the symbols have vaguely sensible names even is some have a "_" prefix).

 

PS I found that if I just manually type a watch on "*(SFRS_t *)0x20" it does the trick anyway... :)

Attachment(s): 

Last Edited: Sun. Apr 3, 2016 - 04:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One random thought and one question.

 

It's a pity none of the above approaches allow access to the "full register" without a specific field (like .all). It would be really nice to write stuff like:

ADCSRA = 1<<ADEN | 1<<ADSC;
while (ADCSRA.ADSC);

 

Also, I don't understand why io.h register fields are defined as bit position instead of bit value? Why can't we just have:

#define ADEN  (1<<7)   // instead of 7
#define ADSC  (1<<6)   // instead of 6
// so we could simply write:
ADCSRA = ADEN | ADSC;
while (ADCSRA & ADSC);

In all the code I read I see left shits all over the place, but I can't remember a single time where bit position was taken advantage of.

Why pick bit position then?

ɴᴇᴛɪᴢᴇᴎ

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

It's a pity none of the above approaches allow access to the "full register" without a specific field (like .all). It would be really nice to write stuff like:

My most recent version does allow this:

int main(void)
{
    ddrb = 0xFF;
    while (1)  {
	admux_adlar = 1;
	adcsra = (1 << ADEN) | (1 << ADSC);
	while (adcsra_adsc);
	portb = *(uint8_t *)(&adc + 1);
    }
}

(and yes I just realised why I need to create L/H splits of a uint16_t member!). The generated code here is:

	ddrb = 0xFF;
  7c:	8f ef       	ldi	r24, 0xFF	; 255
  7e:	87 bb       	out	0x17, r24	; 23
    while (1)  {
		admux_adlar = 1;
		adcsra = (1 << ADEN) | (1 << ADSC);
  80:	90 ec       	ldi	r25, 0xC0	; 192

int main(void)
{
	ddrb = 0xFF;
    while (1)  {
		admux_adlar = 1;
  82:	3d 9a       	sbi	0x07, 5	; 7
		adcsra = (1 << ADEN) | (1 << ADSC);
  84:	96 b9       	out	0x06, r25	; 6
		while (adcsra_adsc);
  86:	36 99       	sbic	0x06, 6	; 6
  88:	fe cf       	rjmp	.-4      	; 0x86 <main+0xa>
		portb = *(uint8_t *)(&adc + 1);
  8a:	86 b1       	in	r24, 0x06	; 6
  8c:	88 bb       	out	0x18, r24	; 24

 Also, I don't understand why io.h register fields are defined as bit position instead of bit value? 

Blame the AVR designers who gave us the SBI and CBI opcodes. They take a bit number not a bit mask. It's fairly easy to convert a bit number into a mask but (as doing this Python just proved!) converting masks back to bit positions is more convoluted.

 

When Atmel got to the Xmega they defined the headers to have BITNAME_bm and BITNAME_bp where one is a bit mask (_bm) and one is a bit position (_bp) so you have the choice of:

REG = BINTNAME_bm;

or

REG = (1 << BITNAME_bp);

I guess that because I am inventing new headers here I could auto generate lists of _bm's so you have something like:

	adcsra = aden_bm | adsc_bm;

instead of:

	adcsra = (1 << ADEN) | (1 << ADSC);

or similar?

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

OK, So I made it do this:

#define adcsra pSFR->_adcsra.all
#define adcsra_adps pSFR->_adcsra.bits.adps
#define adps_bm (1 << 0)
#define adcsra_adie pSFR->_adcsra.bits.adie
#define adie_bm (1 << 3)
#define adcsra_adif pSFR->_adcsra.bits.adif
#define adif_bm (1 << 4)
#define adcsra_adate pSFR->_adcsra.bits.adate
#define adate_bm (1 << 5)
#define adcsra_adsc pSFR->_adcsra.bits.adsc
#define adsc_bm (1 << 6)
#define adcsra_aden pSFR->_adcsra.bits.aden
#define aden_bm (1 << 7)

but then I got errors about this:

#define tccr1b_wgm1 pSFR->_tccr1b.bits.wgm1
#define wgm1_bm (1 << 3)
#define tccr1b_ices1 pSFR->_tccr1b.bits.ices1
#define ices1_bm (1 << 6)
#define tccr1b_icnc1 pSFR->_tccr1b.bits.icnc1
#define icnc1_bm (1 << 7)

#define tccr1a pSFR->_tccr1a.all
#define tccr1a_wgm1 pSFR->_tccr1a.bits.wgm1
#define wgm1_bm (1 << 0)
C:\Users\Cliff\OneDrive\Documents\avrread\ATmega16.h(1217,0): warning: "wgm1_bm" redefined
		 #define wgm1_bm (1 << 0)
		 ^
C:\Users\Cliff\OneDrive\Documents\avrread\ATmega16.h(1209,0): info: this is the location of the previous definition
		 #define wgm1_bm (1 << 3)
		 ^

I now understand why they call these things WGM01 and WGM11. Sadly the XML itself just defines a bit called WGM1 for both TMR_0 and TMR_1. I need to think about a way to automate the resolution of this.

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

clawson wrote:

It's a pity none of the above approaches allow access to the "full register" without a specific field (like .all). It would be really nice to write stuff like:

My most recent version does allow this

Sure, but at the cost of using '_' instead of the more syntactically significant '.'.

 

clawson wrote:

 Also, I don't understand why io.h register fields are defined as bit position instead of bit value? 

Blame the AVR designers who gave us the SBI and CBI opcodes. They take a bit number not a bit mask.

But in C we're not using these opcodes, and I believe the compiler knows how to work out what the bit number is on its own. Like, if I wrote:

PORTB |= 0x80;

…the compiler would translate that to the right SBI instruction, right?

 

clawson wrote:

When Atmel got to the Xmega they defined the headers to have BITNAME_bm and BITNAME_bp where one is a bit mask (_bm) and one is a bit position (_bp) so you have the choice of:

REG = BINTNAME_bm;

or

REG = (1 << BITNAME_bp);

Oh, I see…

Well, in this case I'd rather have:

REG = BINTNAME;
REG = (1 << BITNAME_bp);

…in the interest of keeping things short and sweet: give the most used (by far) define the best/shortest name.

Or in our case, what about:

	adcsra = aden | adsc;
	adcsra = 1<<ADEN | 1<<ADSC;

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Sun. Apr 3, 2016 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I now understand why they call these things WGM01 and WGM11. Sadly the XML itself just defines a bit called WGM1 for both TMR_0 and TMR_1. I need to think about a way to automate the resolution of this.

Damn… Devil is in the details! :-p

ɴᴇᴛɪᴢᴇᴎ

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

netizen wrote:
But in C we're not using these opcodes

The same defining headers are shared between compiler and assembler. I can just as easily do this:

#define __SFR_OFFSET 0
#include <avr/io.h>

somefunc:
    sbi UCSRA, TXEN
    ret

as I can:

#include <avr/io.h>

int main(void) {
    UCSRA |= (1 << TXEN);
}

It's the same TXEN (5) being used in both cases.

netizen wrote:
…the compiler would translate that to the right SBI instruction, right?
Of course, what do you think:

PORTB |= (1 << 7);

is anyway if not just:

PORTB |= 0x80;

and both would generate:

SBI PORTB, 7

netizen wrote:
Or in our case, what about:

Yup, I was just walking my cats and thinking about this and I know how some folks hate having to use the [Shift] key so anything like "txen_bm" or "txenB" or "ucsraTxen" all involve having to press [Shift] so I guess trying to avoid "_" or any form of capitalization should be a goal.

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

clawson wrote:

netizen wrote:

…the compiler would translate that to the right SBI instruction, right?

 

Of course, what do you think

Exactly the same. So, to sum it up, when programming in C we're not directly using SBI/CBI, and all the left shifting we have to write have to be translated back into bit positions by the compiler anyway. That's exactly where I wanted to get to: what's the point of having the assembler and the compiler including the same version of register defines?

Don't get me wrong, I like the elegance of having a single file serving both purposes as much as the next guy. Yet, please don't tell me thousands of programmers have to read and write hundreds of thousands of (useless) left shifts for this reason alone?

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Sun. Apr 3, 2016 - 08:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

netizen wrote:
what's the point of having the assembler and the compiler including the same version of register defines?

So they only need to be created once by a single process. It's too susceptible to possible errors though it's true that the starting version (as well as the def.inc files for the Atmel assembler) are created using an Atmel utility a bit like what I'm working on here that reads the Atmel XML files.

 

Again in the case of Xmega Atmel sort of learned from what have occurred in the previous 7..8 years so they are effectively in two parts - one part that does not appear "#ifdef __ASSEMBLER__"

 

I agree with you that it's a shame that they didn't see the potential in that original tool to at least generate both bit positions and bit masks. But they didn't and there's no going back now. This is, of course why people have things like (AVR-Libc sfr_defs.h):

#define _BV(pos) (1 << pos)

but I personally don't know whether it's easier to type/read:

UCSRA |= _BV(TXEN);

or

UCSRA |= (1 << TXEN);

I actually favour the latter for 2 reasons:

 

1) in 30+ years of this it's more familiar to me

2) the second will work in any AVR compiler because it's standard C - they don't all have sfr_defs.h / _BV()

 

I guess in part this toy I'm playing with could right such wrongs so I'll #define the bit masks in auto-generated code. (and for completeness sym_bp for the bit positions too).

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

clawson wrote:
I guess in part this toy I'm playing with could right such wrongs so I'll #define the bit masks in auto-generated code. (and for completeness sym_bp for the bit positions too).

+1  :-)

 

clawson wrote:
but I personally don't know whether it's easier to type/read:

UCSRA |= _BV(TXEN);

or

UCSRA |= 1<<TXEN;

NB: last code modified by me.

I'm not a big fan of _BV() either. First it has more chars than the left shift equivalent. Second: where did this name come from? I could live with it if it was at least coherent with other related str_defs.h macros like bit_is_set() and bit_is_clear(), but in the current state of things it just screams "half-baked". ^^

Like many, I resorted to using my own flavor of macros, of which the only bit of originality is perhaps that they're variadic. More readable, yet to be fair: they only make the code smaller when several bits need to be masked:

bit(ADEN, ADSC)
// vs:
1<<ADEN | 1<<ADSC

Or:

set(ADCSRA, ADEN, ADSC)
// vs:
ADCSRA |= 1<<ADEN | 1<<ADSC
ADCSRA |= _BV(ADEN) | _BV(ADSC)

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Mon. Apr 4, 2016 - 11:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK so here's selected excerpts of what it's currently generating (I think I'm abandoning the idea of "no union" and "anonymous" as these are hidden by the #defines anyway)..

	union {
		uint16_t all; // (@ 0x24) ADC Data Register  Bytes
		struct {
			int b0:1;
			int b1:1;
			int b2:1;
			int b3:1;
			int b4:1;
			int b5:1;
			int b6:1;
			int b7:1;
			int b8:1;
			int b9:1;
			int b10:1;
			int b11:1;
			int b12:1;
			int b13:1;
			int b14:1;
			int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _ADC;

this has added another ("halves") member to the union so I can deliver adcl/adch later with:

#define adc pSFR->_ADC.all
#define adc_b0 pSFR->_ADC.bits.b0
#define adc_b1 pSFR->_ADC.bits.b1
#define adc_b2 pSFR->_ADC.bits.b2
#define adc_b3 pSFR->_ADC.bits.b3
#define adc_b4 pSFR->_ADC.bits.b4
#define adc_b5 pSFR->_ADC.bits.b5
#define adc_b6 pSFR->_ADC.bits.b6
#define adc_b7 pSFR->_ADC.bits.b7
#define adc_b8 pSFR->_ADC.bits.b8
#define adc_b9 pSFR->_ADC.bits.b9
#define adc_b10 pSFR->_ADC.bits.b10
#define adc_b11 pSFR->_ADC.bits.b11
#define adc_b12 pSFR->_ADC.bits.b12
#define adc_b13 pSFR->_ADC.bits.b13
#define adc_b14 pSFR->_ADC.bits.b14
#define adc_b15 pSFR->_ADC.bits.b15
#define adcl pSFR->_ADC.halves.low
#define adch pSFR->_ADC.halves.high

For a register that has individual bits it now generates something like:

	union {
		uint8_t all; // (@ 0x2a) USART Control and Status Register B
		struct {
			int _TXB8:1; // b0 Transmit Data Bit 8
			int _RXB8:1; // b1 Receive Data Bit 8
			int _UCSZ2:1; // b2 Character Size
			int _TXEN:1; // b3 Transmitter Enable
			int _RXEN:1; // b4 Receiver Enable
			int _UDRIE:1; // b5 USART Data register Empty Interrupt Enable
			int _TXCIE:1; // b6 TX Complete Interrupt Enable
			int _RXCIE:1; // b7 RX Complete Interrupt Enable
		} bits;
	} _UCSRB;

and then:

#define ucsrb pSFR->_UCSRB.all
#define ucsrb_txb8 pSFR->_UCSRB.bits._TXB8
#define txb8 (1 << 0)
#define txb8_bp 0
#define ucsrb_rxb8 pSFR->_UCSRB.bits._RXB8
#define rxb8 (1 << 1)
#define rxb8_bp 1
#define ucsrb_ucsz2 pSFR->_UCSRB.bits._UCSZ2
#define ucsz2 (1 << 2)
#define ucsz2_bp 2
#define ucsrb_txen pSFR->_UCSRB.bits._TXEN
#define txen (1 << 3)
#define txen_bp 3
#define ucsrb_rxen pSFR->_UCSRB.bits._RXEN
#define rxen (1 << 4)
#define rxen_bp 4
#define ucsrb_udrie pSFR->_UCSRB.bits._UDRIE
#define udrie (1 << 5)
#define udrie_bp 5
#define ucsrb_txcie pSFR->_UCSRB.bits._TXCIE
#define txcie (1 << 6)
#define txcie_bp 6
#define ucsrb_rxcie pSFR->_UCSRB.bits._RXCIE
#define rxcie (1 << 7)
#define rxcie_bp 7

but a tricky one is this:

	union {
		uint8_t all; // (@ 0x5f) Status Register
		struct {
			int _C:1; // b0 Carry Flag
			int _Z:1; // b1 Zero Flag
			int _N:1; // b2 Negative Flag
			int _V:1; // b3 Two's Complement Overflow Flag
			int _S:1; // b4 Sign Bit
			int _H:1; // b5 Half Carry Flag
			int _T:1; // b6 Bit Copy Storage
			int _I:1; // b7 Global Interrupt Enable
		} bits;
	} _SREG;

which leads to some rather dangerous looking defines...

#define sreg pSFR->_SREG.all
#define sreg_c pSFR->_SREG.bits._C
#define c (1 << 0)
#define c_bp 0
#define sreg_z pSFR->_SREG.bits._Z
#define z (1 << 1)
#define z_bp 1
#define sreg_n pSFR->_SREG.bits._N
#define n (1 << 2)
#define n_bp 2
#define sreg_v pSFR->_SREG.bits._V
#define v (1 << 3)
#define v_bp 3
#define sreg_s pSFR->_SREG.bits._S
#define s (1 << 4)
#define s_bp 4
#define sreg_h pSFR->_SREG.bits._H
#define h (1 << 5)
#define h_bp 5
#define sreg_t pSFR->_SREG.bits._T
#define t (1 << 6)
#define t_bp 6
#define sreg_i pSFR->_SREG.bits._I
#define i (1 << 7)
#define i_bp 7

Not everyone will welcome the strange side effects of using i, c, z, s etc as variable names! Need to think about this one - perhaps simply impose a rule that if a symbol name is 1 character it's either not generated as a #define or it has a prefix/suffix of some sort.

Last Edited: Mon. Apr 4, 2016 - 12:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Love the bit mask default.

 

clawson wrote:
Not everyone will welcome the strange side effects of using i, c, z, s etc as variable names! Need to think about this one - perhaps simply impose a rule that if a symbol name is 1 character it's either not generated as a #define or it has a prefix/suffix of some sort.

Indeed. Isn't it just a SREG exception? If so, shouldn't the rule be about SREG rather than single char names?

 

EDIT: fixed typo.

ɴᴇᴛɪᴢᴇᴎ

Last Edited: Mon. Apr 4, 2016 - 01:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, you are right, it's only about SREG so I'll add a rule to watch out for that and do something special.

 

@Morten, are you still with us? You know that thing I said about one of the XML files using the symbol name "INT" in error. It's a bit more widespread than I first thought...

E:\avrread>for %a in (*.atdf) do python avrread.py -i %a -q

E:\avrread>python avrread.py -i ATmega164A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega644RFR2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega256RFR2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega168A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega16U4.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega644A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega165P.atdf -q

E:\avrread>python avrread.py -i ATmega328P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega88.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega328.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega325PA.atdf -q

E:\avrread>python avrread.py -i ATmega6450A.atdf -q

E:\avrread>python avrread.py -i ATmega169PA.atdf -q

E:\avrread>python avrread.py -i ATmega1284P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i AT90USB1286.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega1284.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega325.atdf -q

E:\avrread>python avrread.py -i ATmega88PA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega6490.atdf -q

E:\avrread>python avrread.py -i ATmega64A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega64RFR2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega324P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega6490A.atdf -q

E:\avrread>python avrread.py -i ATmega32C1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i AT90PWM81.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega8HVA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega329PA.atdf -q

E:\avrread>python avrread.py -i ATmega406.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega649P.atdf -q

E:\avrread>python avrread.py -i ATmega128RFA1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega16U2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega640.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega645A.atdf -q

E:\avrread>python avrread.py -i ATmega16A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega128.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega3250A.atdf -q

E:\avrread>python avrread.py -i AT90USB646.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega8A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega32U2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega48A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega3290.atdf -q

E:\avrread>python avrread.py -i ATmega6450P.atdf -q

E:\avrread>python avrread.py -i ATmega168PA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega165A.atdf -q

E:\avrread>python avrread.py -i ATmega16.atdf -q

E:\avrread>python avrread.py -i AT90USB162.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega645P.atdf -q

E:\avrread>python avrread.py -i ATmega324PB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega325P.atdf -q

E:\avrread>python avrread.py -i ATmega168PB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega64.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i AT90USB1287.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega2561.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i AT90PWM216.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Mask

E:\avrread>python avrread.py -i ATmega48P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega6490P.atdf -q

E:\avrread>python avrread.py -i ATmega64HVE2.atdf -q

E:\avrread>python avrread.py -i ATmega162.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega3290A.atdf -q

E:\avrread>python avrread.py -i ATmega16HVBrevB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega165PA.atdf -q

E:\avrread>python avrread.py -i AT90CAN64.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega644.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega8535.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega16M1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega164PA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega168P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega329A.atdf -q

E:\avrread>python avrread.py -i ATmega3250PA.atdf -q

E:\avrread>python avrread.py -i AT90CAN128.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega1281.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega16HVB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega324PA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega2564RFR2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega16HVA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega324A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega32U4.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega328PB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega32M1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega88A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i AT90PWM2B.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega48.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega88P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega64C1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega64M1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega329P.atdf -q

E:\avrread>python avrread.py -i AT90PWM3B.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i ATmega48PB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega32.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega3250.atdf -q

E:\avrread>python avrread.py -i ATmega128RFR2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i AT90PWM161.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega8515.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega1284RFR2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request Enable

E:\avrread>python avrread.py -i AT90PWM1.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Mask

E:\avrread>python avrread.py -i ATmega169P.atdf -q

E:\avrread>python avrread.py -i ATmega6450.atdf -q

E:\avrread>python avrread.py -i ATmega32A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i AT90USB647.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega645.atdf -q

E:\avrread>python avrread.py -i AT90PWM316.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega88PB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega3250P.atdf -q

E:\avrread>python avrread.py -i ATmega32HVBrevB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega325A.atdf -q

E:\avrread>python avrread.py -i ATmega32HVB.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 3 Enable

E:\avrread>python avrread.py -i ATmega48PA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega1280.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega644PA.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega8U2.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega8.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega164P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega3290PA.atdf -q

E:\avrread>python avrread.py -i ATmega649.atdf -q

E:\avrread>python avrread.py -i AT90CAN32.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega649A.atdf -q

E:\avrread>python avrread.py -i AT90USB82.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega3290P.atdf -q

E:\avrread>python avrread.py -i ATmega644P.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 2 Enable

E:\avrread>python avrread.py -i ATmega169A.atdf -q

E:\avrread>python avrread.py -i ATmega128A.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>python avrread.py -i ATmega168.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 1 Enable

E:\avrread>python avrread.py -i ATmega329.atdf -q

E:\avrread>python avrread.py -i ATmega2560.atdf -q
WOOP, WOOP, WOOP - C reserved word used as symbol name - probably XML error sym= INT group= EXTERNAL_INTERRUPT caption =
 External Interrupt Request 7 Enable

E:\avrread>

There's more there that have the error than don't (and remember this is just the "mega" XML's  - haven't looked at the "Tiny" ones yet). I added some code to check for any symbol you are using in this list:

# following list from "GNU programming tutorial"
reserved_words = ['auto', 'if', 'break', 'int', 'case', 'long', 'char', 'register', 'continue', 'return'
                  'default','short', 'do', 'sizeof', 'double', 'static', 'else', 'struct', 'entry',
                  'switch', 'extern', 'typedef', 'float', 'union', 'for', 'unsigned', 'goto', 'while',
                  'enum', 'void', 'const', 'signed', 'volatile']

so at least it just seems to be "INT"/"int" that causes the problem. You probably want to check the "External Interrupt Request" fields in ALL your XML files.

 

(and yes I know that "INT" is an acceptable symbol name in C but it's not something I would advise!!)

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

Oh and I just took this picture which was kind of the whole point of the exercise:

 

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

I'll have a look (DEVXML-908)

:: 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

Cliff, I think this is mixing two things here. The GICR register where we have unordered (due to legacy reasons?) bits for INT0, INT1 and INT2 and the "normal" ones where the bits are in EIMSK and in proper order (INT0 for LSB to INT7 for MSB). Our generator automatically generates suffixed defines for bitfields spanning more than one bit, so "INT" does not surface in our headers. Whether or not we should have separate entries for correctly ordered bits can be argued but I don't see any benefit in doing so and it's not consistent with what we do for other bits. So, I guess the 8 devices below will be fixed but for the others the INT will remain in the atdf, so you'd need to change your generator.


Searching 217 files for "name="INT"/>\n.*INT2" (regex)

C:\git\devices\source\tinymega\devices\ATmega16.atdf:
533 <register-group caption="" name="EXTERNAL_INTERRUPT">
534 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
535: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
536: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
537 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
538 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

C:\git\devices\source\tinymega\devices\ATmega162.atdf:
978 </register>
979 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
980: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
981: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
982 <bitfield caption="Pin Change Interrupt Enables" mask="0x18" name="PCIE"/>
983 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>

C:\git\devices\source\tinymega\devices\ATmega16A.atdf:
545 <register-group caption="" name="EXTERNAL_INTERRUPT">
546 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
547: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
548: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
549 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
550 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

C:\git\devices\source\tinymega\devices\ATmega32.atdf:
476 <register-group caption="" name="EXTERNAL_INTERRUPT">
477 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
478: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
479: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
480 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
481 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

C:\git\devices\source\tinymega\devices\ATmega323.atdf:
619 <register-group caption="" name="EXTERNAL_INTERRUPT">
620 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
621: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
622: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
623 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
624 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

C:\git\devices\source\tinymega\devices\ATmega32A.atdf:
476 <register-group caption="" name="EXTERNAL_INTERRUPT">
477 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
478: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
479: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
480 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
481 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

C:\git\devices\source\tinymega\devices\ATmega8515.atdf:
578 <register-group caption="" name="EXTERNAL_INTERRUPT">
579 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
580: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
581: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
582 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
583 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

C:\git\devices\source\tinymega\devices\ATmega8535.atdf:
740 <register-group caption="" name="EXTERNAL_INTERRUPT">
741 <register caption="General Interrupt Control Register" name="GICR" offset="0x5B" size="1">
742: <bitfield caption="External Interrupt Request 1 Enable" mask="0xC0" name="INT"/>
743: <bitfield caption="External Interrupt Request 2 Enable" mask="0x20" name="INT2"/>
744 <bitfield caption="Interrupt Vector Select" mask="0x02" name="IVSEL"/>
745 <bitfield caption="Interrupt Vector Change Enable" mask="0x01" name="IVCE"/>

8 matches across 8 files

 

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

MannImMond wrote:
Our generator automatically generates suffixed defines for bitfields spanning more than one bit

Ah, interesting - in which case I need to do the same I guess. Something like:

        union {
                uint8_t all; // (@ 0x2d) SPI Control Register
                struct {
                        int _SPR:2; // b0 SPI Clock Rate Selects
                        int _CPHA:1; // b2 Clock Phase
                        int _CPOL:1; // b3 Clock polarity
                        int _MSTR:1; // b4 Master/Slave Select
                        int _DORD:1; // b5 Data Order
                        int _SPE:1; // b6 SPI Enable
                        int _SPIE:1; // b7 SPI Interrupt Enable
                } bits;
        } _SPCR;

would then be:

        union {
                uint8_t all; // (@ 0x2d) SPI Control Register
                struct {
                        int _SPR0:1; // b0 SPI Clock Rate Selects
                        int _SPR1:1; // b1 SPI Clock Rate Selects
                        int _CPHA:1; // b2 Clock Phase
                        int _CPOL:1; // b3 Clock polarity
                        int _MSTR:1; // b4 Master/Slave Select
                        int _DORD:1; // b5 Data Order
                        int _SPE:1; // b6 SPI Enable
                        int _SPIE:1; // b7 SPI Interrupt Enable
                } bits;
        } _SPCR;

 

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

Just a note: bit fields have implementation-defined signedness if you don't specify "signed" or "unsigned". AVR-GCC defaults to signed bit fields, I believe, which may give unexpected results when reading the value of a bit field; for example, a signed one-bit field can be either 0 or -1. Other compilers may default to unsigned. For the sake of portability, you should define each field explicitly as unsigned (except where it makes sense to have negative values, though I can't imagine any such case).

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

Interesting. I was tempted to use "uint8_t" in fact (well for the 8 bit ones anyway) but I know from past experience that while GCC will accept that some compilers won't. So I deliberately went with "int" as I thought it was generic. Presumably signedness in AVR ints only comes into play when bit15 is set? So I guess I was probably going to be OK for the 8 bit registers anyway but I'll modify it to use "unsigned int" just to be safe.

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

uint8_t is defined as unsigned char.  It's the 'char' which goes against the standard, not the 'unsigned'.  Valid types for bit-fields are _Bool, int, signed int, and unsigned int.
 

"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: 1

cheeky

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

OK so I finally understood the lsb=n thing in a line such as:

        <register caption="TWI Status Register" name="TWSR" offset="0x21" size="1">
          <bitfield caption="TWI Status" mask="0xF8" name="TWS" lsb="3"/>
          <bitfield caption="TWI Prescaler" mask="0x03" name="TWPS" values="COMM_TWI_PRESACLE"/>
        </register>

which leads to:

	union {
		uint8_t all; // (@ 0x21) TWI Status Register
		struct {
			unsigned int _TWPS0:1; // b0 TWI Prescaler
			unsigned int _TWPS1:1; // b1 TWI Prescaler
			unsigned int unused2:1; // b2
			unsigned int _TWS3:1; // b3 TWI Status
			unsigned int _TWS4:1; // b4 TWI Status
			unsigned int _TWS5:1; // b5 TWI Status
			unsigned int _TWS6:1; // b6 TWI Status
			unsigned int _TWS7:1; // b7 TWI Status
		} bits;
	} _TWSR;

so I think I've cracked it. Here''s a complete ATmega16.h that takes on board all previous comments:

#include <stdint.h>

typedef struct {
	union {
		uint8_t all; // (@ 0x20) TWI Bit Rate register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _TWBR;
	union {
		uint8_t all; // (@ 0x21) TWI Status Register
		struct {
			unsigned int _TWPS0:1; // b0 TWI Prescaler
			unsigned int _TWPS1:1; // b1 TWI Prescaler
			unsigned int unused2:1; // b2
			unsigned int _TWS3:1; // b3 TWI Status
			unsigned int _TWS4:1; // b4 TWI Status
			unsigned int _TWS5:1; // b5 TWI Status
			unsigned int _TWS6:1; // b6 TWI Status
			unsigned int _TWS7:1; // b7 TWI Status
		} bits;
	} _TWSR;
	union {
		uint8_t all; // (@ 0x22) TWI (Slave) Address register
		struct {
			unsigned int _TWGCE:1; // b0 TWI General Call Recognition Enable Bit
			unsigned int _TWA0:1; // b1 TWI (Slave) Address register Bits
			unsigned int _TWA1:1; // b2 TWI (Slave) Address register Bits
			unsigned int _TWA2:1; // b3 TWI (Slave) Address register Bits
			unsigned int _TWA3:1; // b4 TWI (Slave) Address register Bits
			unsigned int _TWA4:1; // b5 TWI (Slave) Address register Bits
			unsigned int _TWA5:1; // b6 TWI (Slave) Address register Bits
			unsigned int _TWA6:1; // b7 TWI (Slave) Address register Bits
		} bits;
	} _TWAR;
	union {
		uint8_t all; // (@ 0x23) TWI Data register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _TWDR;
	union {
		uint16_t all; // (@ 0x24) ADC Data Register  Bytes
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _ADC;
	union {
		uint8_t all; // (@ 0x26) The ADC Control and Status register
		struct {
			unsigned int _ADPS0:1; // b0 ADC  Prescaler Select Bits
			unsigned int _ADPS1:1; // b1 ADC  Prescaler Select Bits
			unsigned int _ADPS2:1; // b2 ADC  Prescaler Select Bits
			unsigned int _ADIE:1; // b3 ADC Interrupt Enable
			unsigned int _ADIF:1; // b4 ADC Interrupt Flag
			unsigned int _ADATE:1; // b5 When this bit is written to one,the Timer/Counter2 prescaler will be reset.The bit will be cleared by hardware after the operation is performed.Writing a zero to this bit will have no effect.This bit will always be read as zero if Timer/Counter2 is clocked by the internal CPU clock.If this bit is written when Timer/Counter2 is operating in asynchronous mode,the bit will remain one until the prescaler has been reset.
			unsigned int _ADSC:1; // b6 ADC Start Conversion
			unsigned int _ADEN:1; // b7 ADC Enable
		} bits;
	} _ADCSRA;
	union {
		uint8_t all; // (@ 0x27) The ADC multiplexer Selection Register
		struct {
			unsigned int _MUX0:1; // b0 Analog Channel and Gain Selection Bits
			unsigned int _MUX1:1; // b1 Analog Channel and Gain Selection Bits
			unsigned int _MUX2:1; // b2 Analog Channel and Gain Selection Bits
			unsigned int _MUX3:1; // b3 Analog Channel and Gain Selection Bits
			unsigned int _MUX4:1; // b4 Analog Channel and Gain Selection Bits
			unsigned int _ADLAR:1; // b5 Left Adjust Result
			unsigned int _REFS0:1; // b6 Reference Selection Bits
			unsigned int _REFS1:1; // b7 Reference Selection Bits
		} bits;
	} _ADMUX;
	union {
		uint8_t all; // (@ 0x28) Analog Comparator Control And Status Register
		struct {
			unsigned int _ACIS0:1; // b0 Analog Comparator Interrupt Mode Select bits
			unsigned int _ACIS1:1; // b1 Analog Comparator Interrupt Mode Select bits
			unsigned int _ACIC:1; // b2 Analog Comparator Input Capture Enable
			unsigned int _ACIE:1; // b3 Analog Comparator Interrupt Enable
			unsigned int _ACI:1; // b4 Analog Comparator Interrupt Flag
			unsigned int _ACO:1; // b5 Analog Compare Output
			unsigned int _ACBG:1; // b6 Analog Comparator Bandgap Select
			unsigned int _ACD:1; // b7 Analog Comparator Disable
		} bits;
	} _ACSR;
	union {
		uint8_t all; // (@ 0x29) USART Baud Rate Register Low Byte
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _UBRRL;
	union {
		uint8_t all; // (@ 0x2a) USART Control and Status Register B
		struct {
			unsigned int _TXB8:1; // b0 Transmit Data Bit 8
			unsigned int _RXB8:1; // b1 Receive Data Bit 8
			unsigned int _UCSZ2:1; // b2 Character Size
			unsigned int _TXEN:1; // b3 Transmitter Enable
			unsigned int _RXEN:1; // b4 Receiver Enable
			unsigned int _UDRIE:1; // b5 USART Data register Empty Interrupt Enable
			unsigned int _TXCIE:1; // b6 TX Complete Interrupt Enable
			unsigned int _RXCIE:1; // b7 RX Complete Interrupt Enable
		} bits;
	} _UCSRB;
	union {
		uint8_t all; // (@ 0x2b) USART Control and Status Register A
		struct {
			unsigned int _MPCM:1; // b0 Multi-processor Communication Mode
			unsigned int _U2X:1; // b1 Double the USART transmission speed
			unsigned int _UPE:1; // b2 Parity Error
			unsigned int _DOR:1; // b3 Data overRun
			unsigned int _FE:1; // b4 Framing Error
			unsigned int _UDRE:1; // b5 USART Data Register Empty
			unsigned int _TXC:1; // b6 USART Transmitt Complete
			unsigned int _RXC:1; // b7 USART Receive Complete
		} bits;
	} _UCSRA;
	union {
		uint8_t all; // (@ 0x2c) USART I/O Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _UDR;
	union {
		uint8_t all; // (@ 0x2d) SPI Control Register
		struct {
			unsigned int _SPR0:1; // b0 SPI Clock Rate Selects
			unsigned int _SPR1:1; // b1 SPI Clock Rate Selects
			unsigned int _CPHA:1; // b2 Clock Phase
			unsigned int _CPOL:1; // b3 Clock polarity
			unsigned int _MSTR:1; // b4 Master/Slave Select
			unsigned int _DORD:1; // b5 Data Order
			unsigned int _SPE:1; // b6 SPI Enable
			unsigned int _SPIE:1; // b7 SPI Interrupt Enable
		} bits;
	} _SPCR;
	union {
		uint8_t all; // (@ 0x2e) SPI Status Register
		struct {
			unsigned int _SPI2X:1; // b0 Double SPI Speed Bit
			unsigned int unused1:5; // b1...b5
			unsigned int _WCOL:1; // b6 Write Collision Flag
			unsigned int _SPIF:1; // b7 SPI Interrupt Flag
		} bits;
	} _SPSR;
	union {
		uint8_t all; // (@ 0x2f) SPI Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _SPDR;
	union {
		uint8_t all; // (@ 0x30) Port D Input Pins
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PIND;
	union {
		uint8_t all; // (@ 0x31) Port D Data Direction Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _DDRD;
	union {
		uint8_t all; // (@ 0x32) Port D Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PORTD;
	union {
		uint8_t all; // (@ 0x33) Port C Input Pins
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PINC;
	union {
		uint8_t all; // (@ 0x34) Port C Data Direction Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _DDRC;
	union {
		uint8_t all; // (@ 0x35) Port C Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PORTC;
	union {
		uint8_t all; // (@ 0x36) Port B Input Pins
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PINB;
	union {
		uint8_t all; // (@ 0x37) Port B Data Direction Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _DDRB;
	union {
		uint8_t all; // (@ 0x38) Port B Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PORTB;
	union {
		uint8_t all; // (@ 0x39) Port A Input Pins
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PINA;
	union {
		uint8_t all; // (@ 0x3a) Port A Data Direction Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _DDRA;
	union {
		uint8_t all; // (@ 0x3b) Port A Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _PORTA;
	union {
		uint8_t all; // (@ 0x3c) EEPROM Control Register
		struct {
			unsigned int _EERE:1; // b0 EEPROM Read Enable
			unsigned int _EEWE:1; // b1 EEPROM Write Enable
			unsigned int _EEMWE:1; // b2 EEPROM Master Write Enable
			unsigned int _EERIE:1; // b3 EEPROM Ready Interrupt Enable
		} bits;
	} _EECR;
	union {
		uint8_t all; // (@ 0x3d) EEPROM Data Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _EEDR;
	union {
		uint16_t all; // (@ 0x3e) EEPROM Address Register  Bytes
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _EEAR;
	union {
		uint8_t all; // (@ 0x40) USART Baud Rate Register Hight Byte
		struct {
			unsigned int _UCPOL:1; // b0 Clock Polarity
			unsigned int _UCSZ0:1; // b1 Character Size
			unsigned int _UCSZ1:1; // b2 Character Size
			unsigned int _USBS:1; // b3 Stop Bit Select
			unsigned int _UPM0:1; // b4 Parity Mode Bits
			unsigned int _UPM1:1; // b5 Parity Mode Bits
			unsigned int _UMSEL:1; // b6 USART Mode Select
			unsigned int _URSEL:1; // b7 Register Select
		} bits;
	} _UBRRH;
	union {
		uint8_t all; // (@ 0x41) Watchdog Timer Control Register
		struct {
			unsigned int _WDP0:1; // b0 Watch Dog Timer Prescaler bits
			unsigned int _WDP1:1; // b1 Watch Dog Timer Prescaler bits
			unsigned int _WDP2:1; // b2 Watch Dog Timer Prescaler bits
			unsigned int _WDE:1; // b3 Watch Dog Enable
			unsigned int _WDTOE:1; // b4 RW
		} bits;
	} _WDTCR;
	union {
		uint8_t all; // (@ 0x42) Asynchronous Status Register
		struct {
			unsigned int _TCR2UB:1; // b0 Timer/counter Control Register2 Update Busy
			unsigned int _OCR2UB:1; // b1 Output Compare Register2 Update Busy
			unsigned int _TCN2UB:1; // b2 Timer/Counter2 Update Busy
			unsigned int _AS2:1; // b3 Asynchronous Timer/counter2
		} bits;
	} _ASSR;
	union {
		uint8_t all; // (@ 0x43) Timer/Counter2 Output Compare Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _OCR2;
	union {
		uint8_t all; // (@ 0x44) Timer/Counter2
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _TCNT2;
	union {
		uint8_t all; // (@ 0x45) Timer/Counter2 Control Register
		struct {
			unsigned int _CS20:1; // b0 Clock Select bits
			unsigned int _CS21:1; // b1 Clock Select bits
			unsigned int _CS22:1; // b2 Clock Select bits
			unsigned int _WGM21:1; // b3 Waveform Generation Mode
			unsigned int _COM20:1; // b4 Compare Output Mode bits
			unsigned int _COM21:1; // b5 Compare Output Mode bits
			unsigned int _WGM20:1; // b6 Waveform Genration Mode
			unsigned int _FOC2:1; // b7 Force Output Compare
		} bits;
	} _TCCR2;
	union {
		uint16_t all; // (@ 0x46) Timer/Counter1 Input Capture Register  Bytes
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _ICR1;
	union {
		uint16_t all; // (@ 0x48) Timer/Counter1 Output Compare Register  Bytes
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _OCR1B;
	union {
		uint16_t all; // (@ 0x4a) Timer/Counter1 Output Compare Register  Bytes
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _OCR1A;
	union {
		uint16_t all; // (@ 0x4c) Timer/Counter1  Bytes
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _TCNT1;
	union {
		uint8_t all; // (@ 0x4e) Timer/Counter1 Control Register B
		struct {
			unsigned int _CS10:1; // b0 Prescaler source of Timer/Counter 1
			unsigned int _CS11:1; // b1 Prescaler source of Timer/Counter 1
			unsigned int _CS12:1; // b2 Prescaler source of Timer/Counter 1
			unsigned int _WGM12:1; // b3 Waveform Generation Mode
			unsigned int _WGM13:1; // b4 Waveform Generation Mode
			unsigned int unused5:1; // b5
			unsigned int _ICES1:1; // b6 Input Capture 1 Edge Select
			unsigned int _ICNC1:1; // b7 Input Capture 1 Noise Canceler
		} bits;
	} _TCCR1B;
	union {
		uint8_t all; // (@ 0x4f) Timer/Counter1 Control Register A
		struct {
			unsigned int _WGM10:1; // b0 Waveform Generation Mode
			unsigned int _WGM11:1; // b1 Waveform Generation Mode
			unsigned int _FOC1B:1; // b2 Force Output Compare 1B
			unsigned int _FOC1A:1; // b3 Force Output Compare 1A
			unsigned int _COM1B0:1; // b4 Compare Output Mode 1B, bits
			unsigned int _COM1B1:1; // b5 Compare Output Mode 1B, bits
			unsigned int _COM1A0:1; // b6 Compare Output Mode 1A, bits
			unsigned int _COM1A1:1; // b7 Compare Output Mode 1A, bits
		} bits;
	} _TCCR1A;
	union {
		uint8_t all; // (@ 0x50) Special Function IO Register
		struct {
			unsigned int _PSR10:1; // b0 Prescaler Reset Timer/Counter1 and Timer/Counter0
			unsigned int _PSR2:1; // b1 Prescaler reset
			unsigned int _PUD:1; // b2 Pull-up Disable
			unsigned int _ACME:1; // b3 Analog Comparator Multiplexer Enable
			unsigned int unused4:1; // b4
			unsigned int _ADTS0:1; // b5 ADC Auto Trigger Sources
			unsigned int _ADTS1:1; // b6 ADC Auto Trigger Sources
			unsigned int _ADTS2:1; // b7 ADC Auto Trigger Sources
		} bits;
	} _SFIOR;
	union {
		uint8_t all; // (@ 0x51) On-Chip Debug Related Register in I/O Memory
		struct {
			unsigned int _OSCCAL0:1; // b0 Oscillator Calibration 
			unsigned int _OSCCAL1:1; // b1 Oscillator Calibration 
			unsigned int _OSCCAL2:1; // b2 Oscillator Calibration 
			unsigned int _OSCCAL3:1; // b3 Oscillator Calibration 
			unsigned int _OSCCAL4:1; // b4 Oscillator Calibration 
			unsigned int _OSCCAL5:1; // b5 Oscillator Calibration 
			unsigned int _OSCCAL6:1; // b6 Oscillator Calibration 
			unsigned int _OSCCAL7:1; // b7 Oscillator Calibration 
		} bits;
	} _OCDR;
	union {
		uint8_t all; // (@ 0x52) Timer/Counter Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _TCNT0;
	union {
		uint8_t all; // (@ 0x53) Timer/Counter Control Register
		struct {
			unsigned int _CS00:1; // b0 Clock Selects
			unsigned int _CS01:1; // b1 Clock Selects
			unsigned int _CS02:1; // b2 Clock Selects
			unsigned int _WGM01:1; // b3 Waveform Generation Mode 1
			unsigned int _COM00:1; // b4 Compare Match Output Modes
			unsigned int _COM01:1; // b5 Compare Match Output Modes
			unsigned int _WGM00:1; // b6 Waveform Generation Mode 0
			unsigned int _FOC0:1; // b7 Force Output Compare
		} bits;
	} _TCCR0;
	union {
		uint8_t all; // (@ 0x54) MCU Control And Status Register
		struct {
			unsigned int _PORF:1; // b0 Power-on reset flag
			unsigned int _EXTRF:1; // b1 External Reset Flag
			unsigned int _BORF:1; // b2 Brown-out Reset Flag
			unsigned int _WDRF:1; // b3 Watchdog Reset Flag
			unsigned int _JTRF:1; // b4 JTAG Reset Flag
			unsigned int unused5:1; // b5
			unsigned int _ISC2:1; // b6 Interrupt Sense Control 2
			unsigned int _JTD:1; // b7 JTAG Interface Disable
		} bits;
	} _MCUCSR;
	union {
		uint8_t all; // (@ 0x55) MCU Control Register
		struct {
			unsigned int _ISC00:1; // b0 Interrupt Sense Control 0 Bits
			unsigned int _ISC01:1; // b1 Interrupt Sense Control 0 Bits
			unsigned int _ISC10:1; // b2 Interrupt Sense Control 1 Bits
			unsigned int _ISC11:1; // b3 Interrupt Sense Control 1 Bits
			unsigned int _SM0:1; // b4 Sleep Mode Select
			unsigned int _SM1:1; // b5 Sleep Mode Select
			unsigned int _SM2:1; // b6 Sleep Mode Select
			unsigned int _SE:1; // b6 Sleep Enable
		} bits;
	} _MCUCR;
	union {
		uint8_t all; // (@ 0x56) TWI Control Register
		struct {
			unsigned int _TWIE:1; // b0 TWI Interrupt Enable
			unsigned int unused1:1; // b1
			unsigned int _TWEN:1; // b2 TWI Enable Bit
			unsigned int _TWWC:1; // b3 TWI Write Collition Flag
			unsigned int _TWSTO:1; // b4 TWI Stop Condition Bit
			unsigned int _TWSTA:1; // b5 TWI Start Condition Bit
			unsigned int _TWEA:1; // b6 TWI Enable Acknowledge Bit
			unsigned int _TWINT:1; // b7 TWI Interrupt Flag
		} bits;
	} _TWCR;
	union {
		uint8_t all; // (@ 0x57) Store Program Memory Control Register
		struct {
			unsigned int _SPMEN:1; // b0 Store Program Memory Enable
			unsigned int _PGERS:1; // b1 Page Erase
			unsigned int _PGWRT:1; // b2 Page Write
			unsigned int _BLBSET:1; // b3 Boot Lock Bit Set
			unsigned int _RWWSRE:1; // b4 Read While Write section read enable
			unsigned int unused5:1; // b5
			unsigned int _RWWSB:1; // b6 Read While Write Section Busy
			unsigned int _SPMIE:1; // b7 SPM Interrupt Enable
		} bits;
	} _SPMCSR;
	union {
		uint8_t all; // (@ 0x58) Timer/Counter Interrupt Flag Register
		struct {
			unsigned int _TOV0:1; // b0 Timer/Counter0 Overflow Flag
			unsigned int _OCF0:1; // b1 Output Compare Flag 0
			unsigned int _TOV1:1; // b2 Timer/Counter1 Overflow Flag
			unsigned int _OCF1B:1; // b3 Output Compare Flag 1B
			unsigned int _OCF1A:1; // b4 Output Compare Flag 1A
			unsigned int _ICF1:1; // b5 Input Capture Flag 1
			unsigned int _TOV2:1; // b6 Timer/Counter2 Overflow Flag
			unsigned int _OCF2:1; // b7 Output Compare Flag 2
		} bits;
	} _TIFR;
	union {
		uint8_t all; // (@ 0x59) Timer/Counter Interrupt Mask register
		struct {
			unsigned int _TOIE0:1; // b0 Timer/Counter0 Overflow Interrupt Enable
			unsigned int _OCIE0:1; // b1 Timer/Counter0 Output Compare Match Interrupt register
			unsigned int _TOIE1:1; // b2 Timer/Counter1 Overflow Interrupt Enable
			unsigned int _OCIE1B:1; // b3 Timer/Counter1 Output CompareB Match Interrupt Enable
			unsigned int _OCIE1A:1; // b4 Timer/Counter1 Output CompareA Match Interrupt Enable
			unsigned int _TICIE1:1; // b5 Timer/Counter1 Input Capture Interrupt Enable
			unsigned int _TOIE2:1; // b6 Timer/Counter2 Overflow Interrupt Enable
			unsigned int _OCIE2:1; // b7 Timer/Counter2 Output Compare Match Interrupt Enable
		} bits;
	} _TIMSK;
	union {
		uint8_t all; // (@ 0x5a) General Interrupt Flag Register
		struct {
			unsigned int unused0:5; // b0...b4
			unsigned int _INTF2:1; // b5 External Interrupt Flag 2
			unsigned int _INTF0:1; // b6 External Interrupt Flags
			unsigned int _INTF1:1; // b7 External Interrupt Flags
		} bits;
	} _GIFR;
	union {
		uint8_t all; // (@ 0x5b) General Interrupt Control Register
		struct {
			unsigned int _IVCE:1; // b0 Interrupt Vector Change Enable
			unsigned int _IVSEL:1; // b1 Interrupt Vector Select
			unsigned int unused2:3; // b2...b4
			unsigned int _INT2:1; // b5 External Interrupt Request 2 Enable
			unsigned int _INT0:1; // b6 External Interrupt Request 1 Enable
			unsigned int _INT1:1; // b7 External Interrupt Request 1 Enable
		} bits;
	} _GICR;
	union {
		uint8_t all; // (@ 0x5c) Output Compare Register
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
		} bits;
	} _OCR0;
	union {
		uint16_t all; // (@ 0x5d) Stack Pointer 
		struct {
			unsigned int b0:1;
			unsigned int b1:1;
			unsigned int b2:1;
			unsigned int b3:1;
			unsigned int b4:1;
			unsigned int b5:1;
			unsigned int b6:1;
			unsigned int b7:1;
			unsigned int b8:1;
			unsigned int b9:1;
			unsigned int b10:1;
			unsigned int b11:1;
			unsigned int b12:1;
			unsigned int b13:1;
			unsigned int b14:1;
			unsigned int b15:1;
		} bits;
		struct {
			uint8_t low;
			uint8_t high;
		} halves;
	} _SP;
	union {
		uint8_t all; // (@ 0x5f) Status Register
		struct {
			unsigned int _C:1; // b0 Carry Flag
			unsigned int _Z:1; // b1 Zero Flag
			unsigned int _N:1; // b2 Negative Flag
			unsigned int _V:1; // b3 Two's Complement Overflow Flag
			unsigned int _S:1; // b4 Sign Bit
			unsigned int _H:1; // b5 Half Carry Flag
			unsigned int _T:1; // b6 Bit Copy Storage
			unsigned int _I:1; // b7 Global Interrupt Enable
		} bits;
	} _SREG;
} SFRS_t;

#define USE_SFRS() volatile SFRS_t * const pSFR = (SFRS_t *)0x0020

#define twbr pSFR->_TWBR.all
#define twbr_b0 pSFR->_TWBR.bits.b0
#define twbr_b1 pSFR->_TWBR.bits.b1
#define twbr_b2 pSFR->_TWBR.bits.b2
#define twbr_b3 pSFR->_TWBR.bits.b3
#define twbr_b4 pSFR->_TWBR.bits.b4
#define twbr_b5 pSFR->_TWBR.bits.b5
#define twbr_b6 pSFR->_TWBR.bits.b6
#define twbr_b7 pSFR->_TWBR.bits.b7

#define twsr pSFR->_TWSR.all
#define twsr_twps0 pSFR->_TWSR.bits._TWPS0
#define twps0 (1 << 0)
#define twps0_bp 0
#define twsr_twps1 pSFR->_TWSR.bits._TWPS1
#define twps1 (1 << 1)
#define twps1_bp 1
#define twsr_tws3 pSFR->_TWSR.bits._TWS3
#define tws3 (1 << 3)
#define tws3_bp 3
#define twsr_tws4 pSFR->_TWSR.bits._TWS4
#define tws4 (1 << 4)
#define tws4_bp 4
#define twsr_tws5 pSFR->_TWSR.bits._TWS5
#define tws5 (1 << 5)
#define tws5_bp 5
#define twsr_tws6 pSFR->_TWSR.bits._TWS6
#define tws6 (1 << 6)
#define tws6_bp 6
#define twsr_tws7 pSFR->_TWSR.bits._TWS7
#define tws7 (1 << 7)
#define tws7_bp 7

#define twar pSFR->_TWAR.all
#define twar_twgce pSFR->_TWAR.bits._TWGCE
#define twgce (1 << 0)
#define twgce_bp 0
#define twar_twa0 pSFR->_TWAR.bits._TWA0
#define twa0 (1 << 1)
#define twa0_bp 1
#define twar_twa1 pSFR->_TWAR.bits._TWA1
#define twa1 (1 << 2)
#define twa1_bp 2
#define twar_twa2 pSFR->_TWAR.bits._TWA2
#define twa2 (1 << 3)
#define twa2_bp 3
#define twar_twa3 pSFR->_TWAR.bits._TWA3
#define twa3 (1 << 4)
#define twa3_bp 4
#define twar_twa4 pSFR->_TWAR.bits._TWA4
#define twa4 (1 << 5)
#define twa4_bp 5
#define twar_twa5 pSFR->_TWAR.bits._TWA5
#define twa5 (1 << 6)
#define twa5_bp 6
#define twar_twa6 pSFR->_TWAR.bits._TWA6
#define twa6 (1 << 7)
#define twa6_bp 7

#define twdr pSFR->_TWDR.all
#define twdr_b0 pSFR->_TWDR.bits.b0
#define twdr_b1 pSFR->_TWDR.bits.b1
#define twdr_b2 pSFR->_TWDR.bits.b2
#define twdr_b3 pSFR->_TWDR.bits.b3
#define twdr_b4 pSFR->_TWDR.bits.b4
#define twdr_b5 pSFR->_TWDR.bits.b5
#define twdr_b6 pSFR->_TWDR.bits.b6
#define twdr_b7 pSFR->_TWDR.bits.b7

#define adc pSFR->_ADC.all
#define adc_b0 pSFR->_ADC.bits.b0
#define adc_b1 pSFR->_ADC.bits.b1
#define adc_b2 pSFR->_ADC.bits.b2
#define adc_b3 pSFR->_ADC.bits.b3
#define adc_b4 pSFR->_ADC.bits.b4
#define adc_b5 pSFR->_ADC.bits.b5
#define adc_b6 pSFR->_ADC.bits.b6
#define adc_b7 pSFR->_ADC.bits.b7
#define adc_b8 pSFR->_ADC.bits.b8
#define adc_b9 pSFR->_ADC.bits.b9
#define adc_b10 pSFR->_ADC.bits.b10
#define adc_b11 pSFR->_ADC.bits.b11
#define adc_b12 pSFR->_ADC.bits.b12
#define adc_b13 pSFR->_ADC.bits.b13
#define adc_b14 pSFR->_ADC.bits.b14
#define adc_b15 pSFR->_ADC.bits.b15
#define adcl pSFR->_ADC.halves.low
#define adch pSFR->_ADC.halves.high

#define adcsra pSFR->_ADCSRA.all
#define adcsra_adps0 pSFR->_ADCSRA.bits._ADPS0
#define adps0 (1 << 0)
#define adps0_bp 0
#define adcsra_adps1 pSFR->_ADCSRA.bits._ADPS1
#define adps1 (1 << 1)
#define adps1_bp 1
#define adcsra_adps2 pSFR->_ADCSRA.bits._ADPS2
#define adps2 (1 << 2)
#define adps2_bp 2
#define adcsra_adie pSFR->_ADCSRA.bits._ADIE
#define adie (1 << 3)
#define adie_bp 3
#define adcsra_adif pSFR->_ADCSRA.bits._ADIF
#define adif (1 << 4)
#define adif_bp 4
#define adcsra_adate pSFR->_ADCSRA.bits._ADATE
#define adate (1 << 5)
#define adate_bp 5
#define adcsra_adsc pSFR->_ADCSRA.bits._ADSC
#define adsc (1 << 6)
#define adsc_bp 6
#define adcsra_aden pSFR->_ADCSRA.bits._ADEN
#define aden (1 << 7)
#define aden_bp 7

#define admux pSFR->_ADMUX.all
#define admux_mux0 pSFR->_ADMUX.bits._MUX0
#define mux0 (1 << 0)
#define mux0_bp 0
#define admux_mux1 pSFR->_ADMUX.bits._MUX1
#define mux1 (1 << 1)
#define mux1_bp 1
#define admux_mux2 pSFR->_ADMUX.bits._MUX2
#define mux2 (1 << 2)
#define mux2_bp 2
#define admux_mux3 pSFR->_ADMUX.bits._MUX3
#define mux3 (1 << 3)
#define mux3_bp 3
#define admux_mux4 pSFR->_ADMUX.bits._MUX4
#define mux4 (1 << 4)
#define mux4_bp 4
#define admux_adlar pSFR->_ADMUX.bits._ADLAR
#define adlar (1 << 5)
#define adlar_bp 5
#define admux_refs0 pSFR->_ADMUX.bits._REFS0
#define refs0 (1 << 6)
#define refs0_bp 6
#define admux_refs1 pSFR->_ADMUX.bits._REFS1
#define refs1 (1 << 7)
#define refs1_bp 7

#define acsr pSFR->_ACSR.all
#define acsr_acis0 pSFR->_ACSR.bits._ACIS0
#define acis0 (1 << 0)
#define acis0_bp 0
#define acsr_acis1 pSFR->_ACSR.bits._ACIS1
#define acis1 (1 << 1)
#define acis1_bp 1
#define acsr_acic pSFR->_ACSR.bits._ACIC
#define acic (1 << 2)
#define acic_bp 2
#define acsr_acie pSFR->_ACSR.bits._ACIE
#define acie (1 << 3)
#define acie_bp 3
#define acsr_aci pSFR->_ACSR.bits._ACI
#define aci (1 << 4)
#define aci_bp 4
#define acsr_aco pSFR->_ACSR.bits._ACO
#define aco (1 << 5)
#define aco_bp 5
#define acsr_acbg pSFR->_ACSR.bits._ACBG
#define acbg (1 << 6)
#define acbg_bp 6
#define acsr_acd pSFR->_ACSR.bits._ACD
#define acd (1 << 7)
#define acd_bp 7

#define ubrrl pSFR->_UBRRL.all
#define ubrrl_b0 pSFR->_UBRRL.bits.b0
#define ubrrl_b1 pSFR->_UBRRL.bits.b1
#define ubrrl_b2 pSFR->_UBRRL.bits.b2
#define ubrrl_b3 pSFR->_UBRRL.bits.b3
#define ubrrl_b4 pSFR->_UBRRL.bits.b4
#define ubrrl_b5 pSFR->_UBRRL.bits.b5
#define ubrrl_b6 pSFR->_UBRRL.bits.b6
#define ubrrl_b7 pSFR->_UBRRL.bits.b7

#define ucsrb pSFR->_UCSRB.all
#define ucsrb_txb8 pSFR->_UCSRB.bits._TXB8
#define txb8 (1 << 0)
#define txb8_bp 0
#define ucsrb_rxb8 pSFR->_UCSRB.bits._RXB8
#define rxb8 (1 << 1)
#define rxb8_bp 1
#define ucsrb_ucsz2 pSFR->_UCSRB.bits._UCSZ2
#define ucsz2 (1 << 2)
#define ucsz2_bp 2
#define ucsrb_txen pSFR->_UCSRB.bits._TXEN
#define txen (1 << 3)
#define txen_bp 3
#define ucsrb_rxen pSFR->_UCSRB.bits._RXEN
#define rxen (1 << 4)
#define rxen_bp 4
#define ucsrb_udrie pSFR->_UCSRB.bits._UDRIE
#define udrie (1 << 5)
#define udrie_bp 5
#define ucsrb_txcie pSFR->_UCSRB.bits._TXCIE
#define txcie (1 << 6)
#define txcie_bp 6
#define ucsrb_rxcie pSFR->_UCSRB.bits._RXCIE
#define rxcie (1 << 7)
#define rxcie_bp 7

#define ucsra pSFR->_UCSRA.all
#define ucsra_mpcm pSFR->_UCSRA.bits._MPCM
#define mpcm (1 << 0)
#define mpcm_bp 0
#define ucsra_u2x pSFR->_UCSRA.bits._U2X
#define u2x (1 << 1)
#define u2x_bp 1
#define ucsra_upe pSFR->_UCSRA.bits._UPE
#define upe (1 << 2)
#define upe_bp 2
#define ucsra_dor pSFR->_UCSRA.bits._DOR
#define dor (1 << 3)
#define dor_bp 3
#define ucsra_fe pSFR->_UCSRA.bits._FE
#define fe (1 << 4)
#define fe_bp 4
#define ucsra_udre pSFR->_UCSRA.bits._UDRE
#define udre (1 << 5)
#define udre_bp 5
#define ucsra_txc pSFR->_UCSRA.bits._TXC
#define txc (1 << 6)
#define txc_bp 6
#define ucsra_rxc pSFR->_UCSRA.bits._RXC
#define rxc (1 << 7)
#define rxc_bp 7

#define udr pSFR->_UDR.all
#define udr_b0 pSFR->_UDR.bits.b0
#define udr_b1 pSFR->_UDR.bits.b1
#define udr_b2 pSFR->_UDR.bits.b2
#define udr_b3 pSFR->_UDR.bits.b3
#define udr_b4 pSFR->_UDR.bits.b4
#define udr_b5 pSFR->_UDR.bits.b5
#define udr_b6 pSFR->_UDR.bits.b6
#define udr_b7 pSFR->_UDR.bits.b7

#define spcr pSFR->_SPCR.all
#define spcr_spr0 pSFR->_SPCR.bits._SPR0
#define spr0 (1 << 0)
#define spr0_bp 0
#define spcr_spr1 pSFR->_SPCR.bits._SPR1
#define spr1 (1 << 1)
#define spr1_bp 1
#define spcr_cpha pSFR->_SPCR.bits._CPHA
#define cpha (1 << 2)
#define cpha_bp 2
#define spcr_cpol pSFR->_SPCR.bits._CPOL
#define cpol (1 << 3)
#define cpol_bp 3
#define spcr_mstr pSFR->_SPCR.bits._MSTR
#define mstr (1 << 4)
#define mstr_bp 4
#define spcr_dord pSFR->_SPCR.bits._DORD
#define dord (1 << 5)
#define dord_bp 5
#define spcr_spe pSFR->_SPCR.bits._SPE
#define spe (1 << 6)
#define spe_bp 6
#define spcr_spie pSFR->_SPCR.bits._SPIE
#define spie (1 << 7)
#define spie_bp 7

#define spsr pSFR->_SPSR.all
#define spsr_spi2x pSFR->_SPSR.bits._SPI2X
#define spi2x (1 << 0)
#define spi2x_bp 0
#define spsr_wcol pSFR->_SPSR.bits._WCOL
#define wcol (1 << 6)
#define wcol_bp 6
#define spsr_spif pSFR->_SPSR.bits._SPIF
#define spif (1 << 7)
#define spif_bp 7

#define spdr pSFR->_SPDR.all
#define spdr_b0 pSFR->_SPDR.bits.b0
#define spdr_b1 pSFR->_SPDR.bits.b1
#define spdr_b2 pSFR->_SPDR.bits.b2
#define spdr_b3 pSFR->_SPDR.bits.b3
#define spdr_b4 pSFR->_SPDR.bits.b4
#define spdr_b5 pSFR->_SPDR.bits.b5
#define spdr_b6 pSFR->_SPDR.bits.b6
#define spdr_b7 pSFR->_SPDR.bits.b7

#define pind pSFR->_PIND.all
#define pind_b0 pSFR->_PIND.bits.b0
#define pind_b1 pSFR->_PIND.bits.b1
#define pind_b2 pSFR->_PIND.bits.b2
#define pind_b3 pSFR->_PIND.bits.b3
#define pind_b4 pSFR->_PIND.bits.b4
#define pind_b5 pSFR->_PIND.bits.b5
#define pind_b6 pSFR->_PIND.bits.b6
#define pind_b7 pSFR->_PIND.bits.b7

#define ddrd pSFR->_DDRD.all
#define ddrd_b0 pSFR->_DDRD.bits.b0
#define ddrd_b1 pSFR->_DDRD.bits.b1
#define ddrd_b2 pSFR->_DDRD.bits.b2
#define ddrd_b3 pSFR->_DDRD.bits.b3
#define ddrd_b4 pSFR->_DDRD.bits.b4
#define ddrd_b5 pSFR->_DDRD.bits.b5
#define ddrd_b6 pSFR->_DDRD.bits.b6
#define ddrd_b7 pSFR->_DDRD.bits.b7

#define portd pSFR->_PORTD.all
#define portd_b0 pSFR->_PORTD.bits.b0
#define portd_b1 pSFR->_PORTD.bits.b1
#define portd_b2 pSFR->_PORTD.bits.b2
#define portd_b3 pSFR->_PORTD.bits.b3
#define portd_b4 pSFR->_PORTD.bits.b4
#define portd_b5 pSFR->_PORTD.bits.b5
#define portd_b6 pSFR->_PORTD.bits.b6
#define portd_b7 pSFR->_PORTD.bits.b7

#define pinc pSFR->_PINC.all
#define pinc_b0 pSFR->_PINC.bits.b0
#define pinc_b1 pSFR->_PINC.bits.b1
#define pinc_b2 pSFR->_PINC.bits.b2
#define pinc_b3 pSFR->_PINC.bits.b3
#define pinc_b4 pSFR->_PINC.bits.b4
#define pinc_b5 pSFR->_PINC.bits.b5
#define pinc_b6 pSFR->_PINC.bits.b6
#define pinc_b7 pSFR->_PINC.bits.b7

#define ddrc pSFR->_DDRC.all
#define ddrc_b0 pSFR->_DDRC.bits.b0
#define ddrc_b1 pSFR->_DDRC.bits.b1
#define ddrc_b2 pSFR->_DDRC.bits.b2
#define ddrc_b3 pSFR->_DDRC.bits.b3
#define ddrc_b4 pSFR->_DDRC.bits.b4
#define ddrc_b5 pSFR->_DDRC.bits.b5
#define ddrc_b6 pSFR->_DDRC.bits.b6
#define ddrc_b7 pSFR->_DDRC.bits.b7

#define portc pSFR->_PORTC.all
#define portc_b0 pSFR->_PORTC.bits.b0
#define portc_b1 pSFR->_PORTC.bits.b1
#define portc_b2 pSFR->_PORTC.bits.b2
#define portc_b3 pSFR->_PORTC.bits.b3
#define portc_b4 pSFR->_PORTC.bits.b4
#define portc_b5 pSFR->_PORTC.bits.b5
#define portc_b6 pSFR->_PORTC.bits.b6
#define portc_b7 pSFR->_PORTC.bits.b7

#define pinb pSFR->_PINB.all
#define pinb_b0 pSFR->_PINB.bits.b0
#define pinb_b1 pSFR->_PINB.bits.b1
#define pinb_b2 pSFR->_PINB.bits.b2
#define pinb_b3 pSFR->_PINB.bits.b3
#define pinb_b4 pSFR->_PINB.bits.b4
#define pinb_b5 pSFR->_PINB.bits.b5
#define pinb_b6 pSFR->_PINB.bits.b6
#define pinb_b7 pSFR->_PINB.bits.b7

#define ddrb pSFR->_DDRB.all
#define ddrb_b0 pSFR->_DDRB.bits.b0
#define ddrb_b1 pSFR->_DDRB.bits.b1
#define ddrb_b2 pSFR->_DDRB.bits.b2
#define ddrb_b3 pSFR->_DDRB.bits.b3
#define ddrb_b4 pSFR->_DDRB.bits.b4
#define ddrb_b5 pSFR->_DDRB.bits.b5
#define ddrb_b6 pSFR->_DDRB.bits.b6
#define ddrb_b7 pSFR->_DDRB.bits.b7

#define portb pSFR->_PORTB.all
#define portb_b0 pSFR->_PORTB.bits.b0
#define portb_b1 pSFR->_PORTB.bits.b1
#define portb_b2 pSFR->_PORTB.bits.b2
#define portb_b3 pSFR->_PORTB.bits.b3
#define portb_b4 pSFR->_PORTB.bits.b4
#define portb_b5 pSFR->_PORTB.bits.b5
#define portb_b6 pSFR->_PORTB.bits.b6
#define portb_b7 pSFR->_PORTB.bits.b7

#define pina pSFR->_PINA.all
#define pina_b0 pSFR->_PINA.bits.b0
#define pina_b1 pSFR->_PINA.bits.b1
#define pina_b2 pSFR->_PINA.bits.b2
#define pina_b3 pSFR->_PINA.bits.b3
#define pina_b4 pSFR->_PINA.bits.b4
#define pina_b5 pSFR->_PINA.bits.b5
#define pina_b6 pSFR->_PINA.bits.b6
#define pina_b7 pSFR->_PINA.bits.b7

#define ddra pSFR->_DDRA.all
#define ddra_b0 pSFR->_DDRA.bits.b0
#define ddra_b1 pSFR->_DDRA.bits.b1
#define ddra_b2 pSFR->_DDRA.bits.b2
#define ddra_b3 pSFR->_DDRA.bits.b3
#define ddra_b4 pSFR->_DDRA.bits.b4
#define ddra_b5 pSFR->_DDRA.bits.b5
#define ddra_b6 pSFR->_DDRA.bits.b6
#define ddra_b7 pSFR->_DDRA.bits.b7

#define porta pSFR->_PORTA.all
#define porta_b0 pSFR->_PORTA.bits.b0
#define porta_b1 pSFR->_PORTA.bits.b1
#define porta_b2 pSFR->_PORTA.bits.b2
#define porta_b3 pSFR->_PORTA.bits.b3
#define porta_b4 pSFR->_PORTA.bits.b4
#define porta_b5 pSFR->_PORTA.bits.b5
#define porta_b6 pSFR->_PORTA.bits.b6
#define porta_b7 pSFR->_PORTA.bits.b7

#define eecr pSFR->_EECR.all
#define eecr_eere pSFR->_EECR.bits._EERE
#define eere (1 << 0)
#define eere_bp 0
#define eecr_eewe pSFR->_EECR.bits._EEWE
#define eewe (1 << 1)
#define eewe_bp 1
#define eecr_eemwe pSFR->_EECR.bits._EEMWE
#define eemwe (1 << 2)
#define eemwe_bp 2
#define eecr_eerie pSFR->_EECR.bits._EERIE
#define eerie (1 << 3)
#define eerie_bp 3

#define eedr pSFR->_EEDR.all
#define eedr_b0 pSFR->_EEDR.bits.b0
#define eedr_b1 pSFR->_EEDR.bits.b1
#define eedr_b2 pSFR->_EEDR.bits.b2
#define eedr_b3 pSFR->_EEDR.bits.b3
#define eedr_b4 pSFR->_EEDR.bits.b4
#define eedr_b5 pSFR->_EEDR.bits.b5
#define eedr_b6 pSFR->_EEDR.bits.b6
#define eedr_b7 pSFR->_EEDR.bits.b7

#define eear pSFR->_EEAR.all
#define eear_b0 pSFR->_EEAR.bits.b0
#define eear_b1 pSFR->_EEAR.bits.b1
#define eear_b2 pSFR->_EEAR.bits.b2
#define eear_b3 pSFR->_EEAR.bits.b3
#define eear_b4 pSFR->_EEAR.bits.b4
#define eear_b5 pSFR->_EEAR.bits.b5
#define eear_b6 pSFR->_EEAR.bits.b6
#define eear_b7 pSFR->_EEAR.bits.b7
#define eear_b8 pSFR->_EEAR.bits.b8
#define eear_b9 pSFR->_EEAR.bits.b9
#define eear_b10 pSFR->_EEAR.bits.b10
#define eear_b11 pSFR->_EEAR.bits.b11
#define eear_b12 pSFR->_EEAR.bits.b12
#define eear_b13 pSFR->_EEAR.bits.b13
#define eear_b14 pSFR->_EEAR.bits.b14
#define eear_b15 pSFR->_EEAR.bits.b15
#define eearl pSFR->_EEAR.halves.low
#define eearh pSFR->_EEAR.halves.high

#define ubrrh pSFR->_UBRRH.all
#define ubrrh_ucpol pSFR->_UBRRH.bits._UCPOL
#define ucpol (1 << 0)
#define ucpol_bp 0
#define ubrrh_ucsz0 pSFR->_UBRRH.bits._UCSZ0
#define ucsz0 (1 << 1)
#define ucsz0_bp 1
#define ubrrh_ucsz1 pSFR->_UBRRH.bits._UCSZ1
#define ucsz1 (1 << 2)
#define ucsz1_bp 2
#define ubrrh_usbs pSFR->_UBRRH.bits._USBS
#define usbs (1 << 3)
#define usbs_bp 3
#define ubrrh_upm0 pSFR->_UBRRH.bits._UPM0
#define upm0 (1 << 4)
#define upm0_bp 4
#define ubrrh_upm1 pSFR->_UBRRH.bits._UPM1
#define upm1 (1 << 5)
#define upm1_bp 5
#define ubrrh_umsel pSFR->_UBRRH.bits._UMSEL
#define umsel (1 << 6)
#define umsel_bp 6
#define ubrrh_ursel pSFR->_UBRRH.bits._URSEL
#define ursel (1 << 7)
#define ursel_bp 7

#define wdtcr pSFR->_WDTCR.all
#define wdtcr_wdp0 pSFR->_WDTCR.bits._WDP0
#define wdp0 (1 << 0)
#define wdp0_bp 0
#define wdtcr_wdp1 pSFR->_WDTCR.bits._WDP1
#define wdp1 (1 << 1)
#define wdp1_bp 1
#define wdtcr_wdp2 pSFR->_WDTCR.bits._WDP2
#define wdp2 (1 << 2)
#define wdp2_bp 2
#define wdtcr_wde pSFR->_WDTCR.bits._WDE
#define wde (1 << 3)
#define wde_bp 3
#define wdtcr_wdtoe pSFR->_WDTCR.bits._WDTOE
#define wdtoe (1 << 4)
#define wdtoe_bp 4

#define assr pSFR->_ASSR.all
#define assr_tcr2ub pSFR->_ASSR.bits._TCR2UB
#define tcr2ub (1 << 0)
#define tcr2ub_bp 0
#define assr_ocr2ub pSFR->_ASSR.bits._OCR2UB
#define ocr2ub (1 << 1)
#define ocr2ub_bp 1
#define assr_tcn2ub pSFR->_ASSR.bits._TCN2UB
#define tcn2ub (1 << 2)
#define tcn2ub_bp 2
#define assr_as2 pSFR->_ASSR.bits._AS2
#define as2 (1 << 3)
#define as2_bp 3

#define ocr2 pSFR->_OCR2.all
#define ocr2_b0 pSFR->_OCR2.bits.b0
#define ocr2_b1 pSFR->_OCR2.bits.b1
#define ocr2_b2 pSFR->_OCR2.bits.b2
#define ocr2_b3 pSFR->_OCR2.bits.b3
#define ocr2_b4 pSFR->_OCR2.bits.b4
#define ocr2_b5 pSFR->_OCR2.bits.b5
#define ocr2_b6 pSFR->_OCR2.bits.b6
#define ocr2_b7 pSFR->_OCR2.bits.b7

#define tcnt2 pSFR->_TCNT2.all
#define tcnt2_b0 pSFR->_TCNT2.bits.b0
#define tcnt2_b1 pSFR->_TCNT2.bits.b1
#define tcnt2_b2 pSFR->_TCNT2.bits.b2
#define tcnt2_b3 pSFR->_TCNT2.bits.b3
#define tcnt2_b4 pSFR->_TCNT2.bits.b4
#define tcnt2_b5 pSFR->_TCNT2.bits.b5
#define tcnt2_b6 pSFR->_TCNT2.bits.b6
#define tcnt2_b7 pSFR->_TCNT2.bits.b7

#define tccr2 pSFR->_TCCR2.all
#define tccr2_cs20 pSFR->_TCCR2.bits._CS20
#define cs20 (1 << 0)
#define cs20_bp 0
#define tccr2_cs21 pSFR->_TCCR2.bits._CS21
#define cs21 (1 << 1)
#define cs21_bp 1
#define tccr2_cs22 pSFR->_TCCR2.bits._CS22
#define cs22 (1 << 2)
#define cs22_bp 2
#define tccr2_wgm21 pSFR->_TCCR2.bits._WGM21
#define wgm21 (1 << 3)
#define wgm21_bp 3
#define tccr2_com20 pSFR->_TCCR2.bits._COM20
#define com20 (1 << 4)
#define com20_bp 4
#define tccr2_com21 pSFR->_TCCR2.bits._COM21
#define com21 (1 << 5)
#define com21_bp 5
#define tccr2_wgm20 pSFR->_TCCR2.bits._WGM20
#define wgm20 (1 << 6)
#define wgm20_bp 6
#define tccr2_foc2 pSFR->_TCCR2.bits._FOC2
#define foc2 (1 << 7)
#define foc2_bp 7

#define icr1 pSFR->_ICR1.all
#define icr1_b0 pSFR->_ICR1.bits.b0
#define icr1_b1 pSFR->_ICR1.bits.b1
#define icr1_b2 pSFR->_ICR1.bits.b2
#define icr1_b3 pSFR->_ICR1.bits.b3
#define icr1_b4 pSFR->_ICR1.bits.b4
#define icr1_b5 pSFR->_ICR1.bits.b5
#define icr1_b6 pSFR->_ICR1.bits.b6
#define icr1_b7 pSFR->_ICR1.bits.b7
#define icr1_b8 pSFR->_ICR1.bits.b8
#define icr1_b9 pSFR->_ICR1.bits.b9
#define icr1_b10 pSFR->_ICR1.bits.b10
#define icr1_b11 pSFR->_ICR1.bits.b11
#define icr1_b12 pSFR->_ICR1.bits.b12
#define icr1_b13 pSFR->_ICR1.bits.b13
#define icr1_b14 pSFR->_ICR1.bits.b14
#define icr1_b15 pSFR->_ICR1.bits.b15
#define icr1l pSFR->_ICR1.halves.low
#define icr1h pSFR->_ICR1.halves.high

#define ocr1b pSFR->_OCR1B.all
#define ocr1b_b0 pSFR->_OCR1B.bits.b0
#define ocr1b_b1 pSFR->_OCR1B.bits.b1
#define ocr1b_b2 pSFR->_OCR1B.bits.b2
#define ocr1b_b3 pSFR->_OCR1B.bits.b3
#define ocr1b_b4 pSFR->_OCR1B.bits.b4
#define ocr1b_b5 pSFR->_OCR1B.bits.b5
#define ocr1b_b6 pSFR->_OCR1B.bits.b6
#define ocr1b_b7 pSFR->_OCR1B.bits.b7
#define ocr1b_b8 pSFR->_OCR1B.bits.b8
#define ocr1b_b9 pSFR->_OCR1B.bits.b9
#define ocr1b_b10 pSFR->_OCR1B.bits.b10
#define ocr1b_b11 pSFR->_OCR1B.bits.b11
#define ocr1b_b12 pSFR->_OCR1B.bits.b12
#define ocr1b_b13 pSFR->_OCR1B.bits.b13
#define ocr1b_b14 pSFR->_OCR1B.bits.b14
#define ocr1b_b15 pSFR->_OCR1B.bits.b15
#define ocr1bl pSFR->_OCR1B.halves.low
#define ocr1bh pSFR->_OCR1B.halves.high

#define ocr1a pSFR->_OCR1A.all
#define ocr1a_b0 pSFR->_OCR1A.bits.b0
#define ocr1a_b1 pSFR->_OCR1A.bits.b1
#define ocr1a_b2 pSFR->_OCR1A.bits.b2
#define ocr1a_b3 pSFR->_OCR1A.bits.b3
#define ocr1a_b4 pSFR->_OCR1A.bits.b4
#define ocr1a_b5 pSFR->_OCR1A.bits.b5
#define ocr1a_b6 pSFR->_OCR1A.bits.b6
#define ocr1a_b7 pSFR->_OCR1A.bits.b7
#define ocr1a_b8 pSFR->_OCR1A.bits.b8
#define ocr1a_b9 pSFR->_OCR1A.bits.b9
#define ocr1a_b10 pSFR->_OCR1A.bits.b10
#define ocr1a_b11 pSFR->_OCR1A.bits.b11
#define ocr1a_b12 pSFR->_OCR1A.bits.b12
#define ocr1a_b13 pSFR->_OCR1A.bits.b13
#define ocr1a_b14 pSFR->_OCR1A.bits.b14
#define ocr1a_b15 pSFR->_OCR1A.bits.b15
#define ocr1al pSFR->_OCR1A.halves.low
#define ocr1ah pSFR->_OCR1A.halves.high

#define tcnt1 pSFR->_TCNT1.all
#define tcnt1_b0 pSFR->_TCNT1.bits.b0
#define tcnt1_b1 pSFR->_TCNT1.bits.b1
#define tcnt1_b2 pSFR->_TCNT1.bits.b2
#define tcnt1_b3 pSFR->_TCNT1.bits.b3
#define tcnt1_b4 pSFR->_TCNT1.bits.b4
#define tcnt1_b5 pSFR->_TCNT1.bits.b5
#define tcnt1_b6 pSFR->_TCNT1.bits.b6
#define tcnt1_b7 pSFR->_TCNT1.bits.b7
#define tcnt1_b8 pSFR->_TCNT1.bits.b8
#define tcnt1_b9 pSFR->_TCNT1.bits.b9
#define tcnt1_b10 pSFR->_TCNT1.bits.b10
#define tcnt1_b11 pSFR->_TCNT1.bits.b11
#define tcnt1_b12 pSFR->_TCNT1.bits.b12
#define tcnt1_b13 pSFR->_TCNT1.bits.b13
#define tcnt1_b14 pSFR->_TCNT1.bits.b14
#define tcnt1_b15 pSFR->_TCNT1.bits.b15
#define tcnt1l pSFR->_TCNT1.halves.low
#define tcnt1h pSFR->_TCNT1.halves.high

#define tccr1b pSFR->_TCCR1B.all
#define tccr1b_cs10 pSFR->_TCCR1B.bits._CS10
#define cs10 (1 << 0)
#define cs10_bp 0
#define tccr1b_cs11 pSFR->_TCCR1B.bits._CS11
#define cs11 (1 << 1)
#define cs11_bp 1
#define tccr1b_cs12 pSFR->_TCCR1B.bits._CS12
#define cs12 (1 << 2)
#define cs12_bp 2
#define tccr1b_wgm12 pSFR->_TCCR1B.bits._WGM12
#define wgm12 (1 << 3)
#define wgm12_bp 3
#define tccr1b_wgm13 pSFR->_TCCR1B.bits._WGM13
#define wgm13 (1 << 4)
#define wgm13_bp 4
#define tccr1b_ices1 pSFR->_TCCR1B.bits._ICES1
#define ices1 (1 << 6)
#define ices1_bp 6
#define tccr1b_icnc1 pSFR->_TCCR1B.bits._ICNC1
#define icnc1 (1 << 7)
#define icnc1_bp 7

#define tccr1a pSFR->_TCCR1A.all
#define tccr1a_wgm10 pSFR->_TCCR1A.bits._WGM10
#define wgm10 (1 << 0)
#define wgm10_bp 0
#define tccr1a_wgm11 pSFR->_TCCR1A.bits._WGM11
#define wgm11 (1 << 1)
#define wgm11_bp 1
#define tccr1a_foc1b pSFR->_TCCR1A.bits._FOC1B
#define foc1b (1 << 2)
#define foc1b_bp 2
#define tccr1a_foc1a pSFR->_TCCR1A.bits._FOC1A
#define foc1a (1 << 3)
#define foc1a_bp 3
#define tccr1a_com1b0 pSFR->_TCCR1A.bits._COM1B0
#define com1b0 (1 << 4)
#define com1b0_bp 4
#define tccr1a_com1b1 pSFR->_TCCR1A.bits._COM1B1
#define com1b1 (1 << 5)
#define com1b1_bp 5
#define tccr1a_com1a0 pSFR->_TCCR1A.bits._COM1A0
#define com1a0 (1 << 6)
#define com1a0_bp 6
#define tccr1a_com1a1 pSFR->_TCCR1A.bits._COM1A1
#define com1a1 (1 << 7)
#define com1a1_bp 7

#define sfior pSFR->_SFIOR.all
#define sfior_psr10 pSFR->_SFIOR.bits._PSR10
#define psr10 (1 << 0)
#define psr10_bp 0
#define sfior_psr2 pSFR->_SFIOR.bits._PSR2
#define psr2 (1 << 1)
#define psr2_bp 1
#define sfior_pud pSFR->_SFIOR.bits._PUD
#define pud (1 << 2)
#define pud_bp 2
#define sfior_acme pSFR->_SFIOR.bits._ACME
#define acme (1 << 3)
#define acme_bp 3
#define sfior_adts0 pSFR->_SFIOR.bits._ADTS0
#define adts0 (1 << 5)
#define adts0_bp 5
#define sfior_adts1 pSFR->_SFIOR.bits._ADTS1
#define adts1 (1 << 6)
#define adts1_bp 6
#define sfior_adts2 pSFR->_SFIOR.bits._ADTS2
#define adts2 (1 << 7)
#define adts2_bp 7

#define ocdr pSFR->_OCDR.all
#define ocdr_osccal0 pSFR->_OCDR.bits._OSCCAL0
#define osccal0 (1 << 0)
#define osccal0_bp 0
#define ocdr_osccal1 pSFR->_OCDR.bits._OSCCAL1
#define osccal1 (1 << 1)
#define osccal1_bp 1
#define ocdr_osccal2 pSFR->_OCDR.bits._OSCCAL2
#define osccal2 (1 << 2)
#define osccal2_bp 2
#define ocdr_osccal3 pSFR->_OCDR.bits._OSCCAL3
#define osccal3 (1 << 3)
#define osccal3_bp 3
#define ocdr_osccal4 pSFR->_OCDR.bits._OSCCAL4
#define osccal4 (1 << 4)
#define osccal4_bp 4
#define ocdr_osccal5 pSFR->_OCDR.bits._OSCCAL5
#define osccal5 (1 << 5)
#define osccal5_bp 5
#define ocdr_osccal6 pSFR->_OCDR.bits._OSCCAL6
#define osccal6 (1 << 6)
#define osccal6_bp 6
#define ocdr_osccal7 pSFR->_OCDR.bits._OSCCAL7
#define osccal7 (1 << 7)
#define osccal7_bp 7

#define tcnt0 pSFR->_TCNT0.all
#define tcnt0_b0 pSFR->_TCNT0.bits.b0
#define tcnt0_b1 pSFR->_TCNT0.bits.b1
#define tcnt0_b2 pSFR->_TCNT0.bits.b2
#define tcnt0_b3 pSFR->_TCNT0.bits.b3
#define tcnt0_b4 pSFR->_TCNT0.bits.b4
#define tcnt0_b5 pSFR->_TCNT0.bits.b5
#define tcnt0_b6 pSFR->_TCNT0.bits.b6
#define tcnt0_b7 pSFR->_TCNT0.bits.b7

#define tccr0 pSFR->_TCCR0.all
#define tccr0_cs00 pSFR->_TCCR0.bits._CS00
#define cs00 (1 << 0)
#define cs00_bp 0
#define tccr0_cs01 pSFR->_TCCR0.bits._CS01
#define cs01 (1 << 1)
#define cs01_bp 1
#define tccr0_cs02 pSFR->_TCCR0.bits._CS02
#define cs02 (1 << 2)
#define cs02_bp 2
#define tccr0_wgm01 pSFR->_TCCR0.bits._WGM01
#define wgm01 (1 << 3)
#define wgm01_bp 3
#define tccr0_com00 pSFR->_TCCR0.bits._COM00
#define com00 (1 << 4)
#define com00_bp 4
#define tccr0_com01 pSFR->_TCCR0.bits._COM01
#define com01 (1 << 5)
#define com01_bp 5
#define tccr0_wgm00 pSFR->_TCCR0.bits._WGM00
#define wgm00 (1 << 6)
#define wgm00_bp 6
#define tccr0_foc0 pSFR->_TCCR0.bits._FOC0
#define foc0 (1 << 7)
#define foc0_bp 7

#define mcucsr pSFR->_MCUCSR.all
#define mcucsr_porf pSFR->_MCUCSR.bits._PORF
#define porf (1 << 0)
#define porf_bp 0
#define mcucsr_extrf pSFR->_MCUCSR.bits._EXTRF
#define extrf (1 << 1)
#define extrf_bp 1
#define mcucsr_borf pSFR->_MCUCSR.bits._BORF
#define borf (1 << 2)
#define borf_bp 2
#define mcucsr_wdrf pSFR->_MCUCSR.bits._WDRF
#define wdrf (1 << 3)
#define wdrf_bp 3
#define mcucsr_jtrf pSFR->_MCUCSR.bits._JTRF
#define jtrf (1 << 4)
#define jtrf_bp 4
#define mcucsr_isc2 pSFR->_MCUCSR.bits._ISC2
#define isc2 (1 << 6)
#define isc2_bp 6
#define mcucsr_jtd pSFR->_MCUCSR.bits._JTD
#define jtd (1 << 7)
#define jtd_bp 7

#define mcucr pSFR->_MCUCR.all
#define mcucr_isc00 pSFR->_MCUCR.bits._ISC00
#define isc00 (1 << 0)
#define isc00_bp 0
#define mcucr_isc01 pSFR->_MCUCR.bits._ISC01
#define isc01 (1 << 1)
#define isc01_bp 1
#define mcucr_isc10 pSFR->_MCUCR.bits._ISC10
#define isc10 (1 << 2)
#define isc10_bp 2
#define mcucr_isc11 pSFR->_MCUCR.bits._ISC11
#define isc11 (1 << 3)
#define isc11_bp 3
#define mcucr_sm0 pSFR->_MCUCR.bits._SM0
#define sm0 (1 << 4)
#define sm0_bp 4
#define mcucr_sm1 pSFR->_MCUCR.bits._SM1
#define sm1 (1 << 5)
#define sm1_bp 5
#define mcucr_sm2 pSFR->_MCUCR.bits._SM2
#define sm2 (1 << 6)
#define sm2_bp 6
#define mcucr_se pSFR->_MCUCR.bits._SE
#define se (1 << 6)
#define se_bp 6

#define twcr pSFR->_TWCR.all
#define twcr_twie pSFR->_TWCR.bits._TWIE
#define twie (1 << 0)
#define twie_bp 0
#define twcr_twen pSFR->_TWCR.bits._TWEN
#define twen (1 << 2)
#define twen_bp 2
#define twcr_twwc pSFR->_TWCR.bits._TWWC
#define twwc (1 << 3)
#define twwc_bp 3
#define twcr_twsto pSFR->_TWCR.bits._TWSTO
#define twsto (1 << 4)
#define twsto_bp 4
#define twcr_twsta pSFR->_TWCR.bits._TWSTA
#define twsta (1 << 5)
#define twsta_bp 5
#define twcr_twea pSFR->_TWCR.bits._TWEA
#define twea (1 << 6)
#define twea_bp 6
#define twcr_twint pSFR->_TWCR.bits._TWINT
#define twint (1 << 7)
#define twint_bp 7

#define spmcsr pSFR->_SPMCSR.all
#define spmcsr_spmen pSFR->_SPMCSR.bits._SPMEN
#define spmen (1 << 0)
#define spmen_bp 0
#define spmcsr_pgers pSFR->_SPMCSR.bits._PGERS
#define pgers (1 << 1)
#define pgers_bp 1
#define spmcsr_pgwrt pSFR->_SPMCSR.bits._PGWRT
#define pgwrt (1 << 2)
#define pgwrt_bp 2
#define spmcsr_blbset pSFR->_SPMCSR.bits._BLBSET
#define blbset (1 << 3)
#define blbset_bp 3
#define spmcsr_rwwsre pSFR->_SPMCSR.bits._RWWSRE
#define rwwsre (1 << 4)
#define rwwsre_bp 4
#define spmcsr_rwwsb pSFR->_SPMCSR.bits._RWWSB
#define rwwsb (1 << 6)
#define rwwsb_bp 6
#define spmcsr_spmie pSFR->_SPMCSR.bits._SPMIE
#define spmie (1 << 7)
#define spmie_bp 7

#define tifr pSFR->_TIFR.all
#define tifr_tov0 pSFR->_TIFR.bits._TOV0
#define tov0 (1 << 0)
#define tov0_bp 0
#define tifr_ocf0 pSFR->_TIFR.bits._OCF0
#define ocf0 (1 << 1)
#define ocf0_bp 1
#define tifr_tov1 pSFR->_TIFR.bits._TOV1
#define tov1 (1 << 2)
#define tov1_bp 2
#define tifr_ocf1b pSFR->_TIFR.bits._OCF1B
#define ocf1b (1 << 3)
#define ocf1b_bp 3
#define tifr_ocf1a pSFR->_TIFR.bits._OCF1A
#define ocf1a (1 << 4)
#define ocf1a_bp 4
#define tifr_icf1 pSFR->_TIFR.bits._ICF1
#define icf1 (1 << 5)
#define icf1_bp 5
#define tifr_tov2 pSFR->_TIFR.bits._TOV2
#define tov2 (1 << 6)
#define tov2_bp 6
#define tifr_ocf2 pSFR->_TIFR.bits._OCF2
#define ocf2 (1 << 7)
#define ocf2_bp 7

#define timsk pSFR->_TIMSK.all
#define timsk_toie0 pSFR->_TIMSK.bits._TOIE0
#define toie0 (1 << 0)
#define toie0_bp 0
#define timsk_ocie0 pSFR->_TIMSK.bits._OCIE0
#define ocie0 (1 << 1)
#define ocie0_bp 1
#define timsk_toie1 pSFR->_TIMSK.bits._TOIE1
#define toie1 (1 << 2)
#define toie1_bp 2
#define timsk_ocie1b pSFR->_TIMSK.bits._OCIE1B
#define ocie1b (1 << 3)
#define ocie1b_bp 3
#define timsk_ocie1a pSFR->_TIMSK.bits._OCIE1A
#define ocie1a (1 << 4)
#define ocie1a_bp 4
#define timsk_ticie1 pSFR->_TIMSK.bits._TICIE1
#define ticie1 (1 << 5)
#define ticie1_bp 5
#define timsk_toie2 pSFR->_TIMSK.bits._TOIE2
#define toie2 (1 << 6)
#define toie2_bp 6
#define timsk_ocie2 pSFR->_TIMSK.bits._OCIE2
#define ocie2 (1 << 7)
#define ocie2_bp 7

#define gifr pSFR->_GIFR.all
#define gifr_intf2 pSFR->_GIFR.bits._INTF2
#define intf2 (1 << 5)
#define intf2_bp 5
#define gifr_intf0 pSFR->_GIFR.bits._INTF0
#define intf0 (1 << 6)
#define intf0_bp 6
#define gifr_intf1 pSFR->_GIFR.bits._INTF1
#define intf1 (1 << 7)
#define intf1_bp 7

#define gicr pSFR->_GICR.all
#define gicr_ivce pSFR->_GICR.bits._IVCE
#define ivce (1 << 0)
#define ivce_bp 0
#define gicr_ivsel pSFR->_GICR.bits._IVSEL
#define ivsel (1 << 1)
#define ivsel_bp 1
#define gicr_int2 pSFR->_GICR.bits._INT2
#define int2 (1 << 5)
#define int2_bp 5
#define gicr_int0 pSFR->_GICR.bits._INT0
#define int0 (1 << 6)
#define int0_bp 6
#define gicr_int1 pSFR->_GICR.bits._INT1
#define int1 (1 << 7)
#define int1_bp 7

#define ocr0 pSFR->_OCR0.all
#define ocr0_b0 pSFR->_OCR0.bits.b0
#define ocr0_b1 pSFR->_OCR0.bits.b1
#define ocr0_b2 pSFR->_OCR0.bits.b2
#define ocr0_b3 pSFR->_OCR0.bits.b3
#define ocr0_b4 pSFR->_OCR0.bits.b4
#define ocr0_b5 pSFR->_OCR0.bits.b5
#define ocr0_b6 pSFR->_OCR0.bits.b6
#define ocr0_b7 pSFR->_OCR0.bits.b7

#define sp pSFR->_SP.all
#define sp_b0 pSFR->_SP.bits.b0
#define sp_b1 pSFR->_SP.bits.b1
#define sp_b2 pSFR->_SP.bits.b2
#define sp_b3 pSFR->_SP.bits.b3
#define sp_b4 pSFR->_SP.bits.b4
#define sp_b5 pSFR->_SP.bits.b5
#define sp_b6 pSFR->_SP.bits.b6
#define sp_b7 pSFR->_SP.bits.b7
#define sp_b8 pSFR->_SP.bits.b8
#define sp_b9 pSFR->_SP.bits.b9
#define sp_b10 pSFR->_SP.bits.b10
#define sp_b11 pSFR->_SP.bits.b11
#define sp_b12 pSFR->_SP.bits.b12
#define sp_b13 pSFR->_SP.bits.b13
#define sp_b14 pSFR->_SP.bits.b14
#define sp_b15 pSFR->_SP.bits.b15
#define spl pSFR->_SP.halves.low
#define sph pSFR->_SP.halves.high

#define sreg pSFR->_SREG.all
#define sreg_c pSFR->_SREG.bits._C
#define c_flag (1 << 0)
#define c_bp 0
#define sreg_z pSFR->_SREG.bits._Z
#define z_flag (1 << 1)
#define z_bp 1
#define sreg_n pSFR->_SREG.bits._N
#define n_flag (1 << 2)
#define n_bp 2
#define sreg_v pSFR->_SREG.bits._V
#define v_flag (1 << 3)
#define v_bp 3
#define sreg_s pSFR->_SREG.bits._S
#define s_flag (1 << 4)
#define s_bp 4
#define sreg_h pSFR->_SREG.bits._H
#define h_flag (1 << 5)
#define h_bp 5
#define sreg_t pSFR->_SREG.bits._T
#define t_flag (1 << 6)
#define t_bp 6
#define sreg_i pSFR->_SREG.bits._I
#define i_flag (1 << 7)
#define i_bp 7

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

PS anyone spot the obvious bug? ;-)

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

Something's weird with the comment for the ADATE bit in ADCSRA.  It bears the comment for bit 2 (PSR2) of SFIOR.

 

 

... but not really a 'bug'.

"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]

 

Last Edited: Tue. Apr 5, 2016 - 10:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Believe it or not what you have found there is not a bug in my utility but in the original XML:

        <register caption="The ADC Control and Status register" name="ADCSRA" offset="0x26" size="1" ocd-rw="R">
          <bitfield caption="ADC Enable" mask="0x80" name="ADEN"/>
          <bitfield caption="ADC Start Conversion" mask="0x40" name="ADSC"/>
          <bitfield caption="When this bit is written to one,the Timer/Counter2 prescaler will be reset.The bit will be cleared by hardware after the operation is performed.Writing a zero to this bit will have no effect.This bit will always be read as zero if Timer/Counter2 is clocked by the internal CPU clock.If this bit is written when Timer/Counter2 is operating in asynchronous mode,the bit will remain one until the prescaler has been reset." mask="0x20" name="ADATE"/>
          <bitfield caption="ADC Interrupt Flag" mask="0x10" name="ADIF"/>
          <bitfield caption="ADC Interrupt Enable" mask="0x08" name="ADIE"/>
          <bitfield caption="ADC  Prescaler Select Bits" mask="0x07" name="ADPS" values="ANALOG_ADC_PRESCALER"/>
        </register>

It's a bit of a mad "caption" anyway! (I thought about truncating stupidly long ones)

 

Nope. the bug is in the SM bits of MCUCR:

	union {
		uint8_t all; // (@ 0x55) MCU Control Register
		struct {
			unsigned int _ISC00:1; // b0 Interrupt Sense Control 0 Bits
			unsigned int _ISC01:1; // b1 Interrupt Sense Control 0 Bits
			unsigned int _ISC10:1; // b2 Interrupt Sense Control 1 Bits
			unsigned int _ISC11:1; // b3 Interrupt Sense Control 1 Bits
			unsigned int _SM0:1; // b4 Sleep Mode Select
			unsigned int _SM1:1; // b5 Sleep Mode Select
			unsigned int _SM2:1; // b6 Sleep Mode Select
			unsigned int _SE:1; // b6 Sleep Enable
		} bits;
	} _MCUCR;

who ever thought that mask=0xB0 was a good idea ?!? It occurs in:

          <bitfield caption="Sleep Mode Select" mask="0xB0" name="SM" values="CPU_SLEEP_MODE_3BITS"/>

I had been working on the theory that multiple bit masks would always be adjacent not 10110000 :-(

 

Time for a rethink...

Last Edited: Tue. Apr 5, 2016 - 10:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But I wanted to keep this simple(ish!) and, if possible, standard C for all compilers and hence I decided on one all encompassing stuct{} with one pointer to it with a single, fixed base address (which is why I also went for all the "unused" padding entries).

I don't understand.  Unnamed bit-fields are part of the standard.  What are you concerned about?  Is it this?

 

"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