avr-device icon indicating copy to clipboard operation
avr-device copied to clipboard

attiny412 support

Open trembel opened this issue 4 years ago • 17 comments

Hi I would like to have support for the attiny412. As it is a MCU of the new AVR-1 series, will it work with your tool?

Also am I understanding correctly, that this crate is providing something similar to the "PAC" crates for the different cortex-m MCUs?

Best, trembel

trembel avatar Jun 16 '20 16:06 trembel

Yes, avr-device is the PAC crate with the raw register definitions. avr-hal builds on top and has safe abstractions over the peripherals.

As it is a MCU of the new AVR-1 series, will it work with your tool?

I don't see a problem with that, it should work just fine.

Are you interested in taking a stab at adding the support yourself? I can guide you through it if you want.

Word of caution if you don't yet have the avr-rust toolchain set up: There's quite a few pitfalls still, you need the avr-support branch from https://github.com/avr-rust/rust as the recently merged upstream support still has a few issues for now.

Rahix avatar Jun 16 '20 17:06 Rahix

Perfect, thank you.

At the moment I'm to busy, but I'll give it a try in a month. I think your "instruction" is quite self-explaining, but if I get trouble I'll ask you :)

trembel avatar Jun 16 '20 17:06 trembel

Sounds good, thanks a lot! :)

Rahix avatar Jun 16 '20 18:06 Rahix

I'm at the moment trying to include the attiny412. However, on compiling atdf2svd fails:

Warning: Unhandled register node: "<register-group offset=\"0\" union-tag-value=\"0\" name=\"SINGLE\" name-in-module=\"TCA_SINGLE\" ...>"
Warning: Unhandled register node: "<register-group name=\"SPLIT\" offset=\"0\" union-tag-value=\"1\" name-in-module=\"TCA_SPLIT\" ...>"
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Warning: Could not apply 'signals_to_port_fields' patch!
Warning: Description missing for peripheral "AC0"
Warning: Description missing for peripheral "ADC0"
Warning: Description missing for peripheral "BOD"
Warning: Description missing for peripheral "CCL"
Warning: Description missing for peripheral "CLKCTRL"
Warning: Description missing for peripheral "CPU"
Warning: Description missing for peripheral "CPUINT"
Warning: Description missing for peripheral "CRCSCAN"
Warning: Description missing for peripheral "DAC0"
Warning: Description missing for peripheral "EVSYS"
Warning: Description missing for peripheral "FUSE"
Warning: Description missing for peripheral "GPIO"
Warning: Description missing for peripheral "LOCKBIT"
Warning: Description missing for peripheral "NVMCTRL"
Warning: Description missing for peripheral "PORTA"
Warning: Description missing for peripheral "PORTMUX"
Warning: Description missing for peripheral "RSTCTRL"
Warning: Description missing for peripheral "RTC"
Warning: Description missing for peripheral "SIGROW"
Warning: Description missing for peripheral "SLPCTRL"
Warning: Description missing for peripheral "SPI0"
Warning: Description missing for peripheral "SYSCFG"

The new tiny series has completely different peripherals (and thus also pin descriptions). Maybe I'll later give a look to atdf2svd.

My changes to avr-device can be found here: https://github.com/trembel/avr-device/commit/b16f21e510bff6e11421e691bb3a62e914889650

trembel avatar Aug 08 '20 14:08 trembel

It looks like this chip does not follow the standard register layout for IO ports. We'll have to fix atdf2svd to detect this case and behave differently for it, I think ...

Rahix avatar Aug 08 '20 14:08 Rahix

It looks like this chip does not follow the standard register layout for IO ports. We'll have to fix atdf2svd to detect this case and behave differently for it, I think ...

I think this affects all chips with the avrxmega3 core, in special the chips I wanted to port of the tinyAVR 1-series & tinyAVR 0-series.

trembel avatar Aug 08 '20 14:08 trembel

I see ... So, it's failing in the signals_to_port_fields patch which is applied after parsing the ATDF to create fields for individual pins in the port registers (PORTn, DDRn, PINn). We added this for convenience, because this was something necessary for all files we looked at.

Now, I don't know much about the MCUs you're referencing, so maybe you can give some insight: Do we need to apply this 'post-processing' (in some modified form) as well, or does the ATDF file correctly name all pin fields already?


Additionally, these two messages:

Warning: Unhandled register node: "<register-group offset=\"0\" union-tag-value=\"0\" name=\"SINGLE\" name-in-module=\"TCA_SINGLE\" ...>"
Warning: Unhandled register node: "<register-group name=\"SPLIT\" offset=\"0\" union-tag-value=\"1\" name-in-module=\"TCA_SPLIT\" ...>"

probably relate to https://github.com/Rahix/atdf2svd/issues/4, so you'll also need this issue resolved I guess ...

Rahix avatar Aug 08 '20 14:08 Rahix

I think its necessary. If I look at the atdf of the bigger AVR128DA28 (the ATtiny412 has only one port, spi, twi, ...), it seems that there is one module including the different PORTn:

        <module id="gpio_ports_v6_port" name="PORT">
          <instance name="PORTA">
            <register-group address-space="data" name="PORTA" name-in-module="PORT" offset="0x0400"/>
            <signals>
              <signal function="IOPORT" group="PIN" index="0" pad="PA0"/>
              <signal function="IOPORT" group="PIN" index="1" pad="PA1"/>
              <signal function="IOPORT" group="PIN" index="2" pad="PA2"/>
              <signal function="IOPORT" group="PIN" index="3" pad="PA3"/>
              <signal function="IOPORT" group="PIN" index="4" pad="PA4"/>
              <signal function="IOPORT" group="PIN" index="5" pad="PA5"/>
              <signal function="IOPORT" group="PIN" index="6" pad="PA6"/>
              <signal function="IOPORT" group="PIN" index="7" pad="PA7"/>
            </signals>
          </instance>
          <instance name="PORTC">
            <register-group address-space="data" name="PORTC" name-in-module="PORT" offset="0x0440"/>
            <signals>
              <signal function="IOPORT" group="PIN" index="0" pad="PC0"/>
              <signal function="IOPORT" group="PIN" index="1" pad="PC1"/>
              <signal function="IOPORT" group="PIN" index="2" pad="PC2"/>
              <signal function="IOPORT" group="PIN" index="3" pad="PC3"/>
            </signals>
          </instance>
          <instance name="PORTD">
            <register-group address-space="data" name="PORTD" name-in-module="PORT" offset="0x0460"/>
            <signals>
              <signal function="IOPORT" group="PIN" index="0" pad="PD0"/>
              <signal function="IOPORT" group="PIN" index="1" pad="PD1"/>
              <signal function="IOPORT" group="PIN" index="2" pad="PD2"/>
              <signal function="IOPORT" group="PIN" index="3" pad="PD3"/>
              <signal function="IOPORT" group="PIN" index="4" pad="PD4"/>
              <signal function="IOPORT" group="PIN" index="5" pad="PD5"/>
              <signal function="IOPORT" group="PIN" index="6" pad="PD6"/>
              <signal function="IOPORT" group="PIN" index="7" pad="PD7"/>
            </signals>
          </instance>
          <instance name="PORTF">
            <register-group address-space="data" name="PORTF" name-in-module="PORT" offset="0x04A0"/>
            <signals>
              <signal function="IOPORT" group="PIN" index="0" pad="PF0"/>
              <signal function="IOPORT" group="PIN" index="1" pad="PF1"/>
              <signal function="IOPORT" group="PIN" index="6" pad="PF6"/>
            </signals>
          </instance>
        </module>

And then one with the registers of the PORT:

    <module caption="I/O Ports" id="gpio_ports_v6_port" name="PORT">
      <register-group caption="I/O Ports" name="PORT" size="0x20">
        <register caption="Data Direction" initval="0x00" name="DIR" offset="0x00" rw="RW" size="1">
          <bitfield caption="Data Direction" mask="0xff" name="DIR" rw="RW"/>
        </register>
        <register caption="Data Direction Clear" initval="0x00" name="DIRCLR" offset="0x02" rw="RW" size="1">
          <bitfield caption="Data Direction Clear" mask="0xff" name="DIRCLR" rw="RW"/>
        </register>
        <register caption="Data Direction Set" initval="0x00" name="DIRSET" offset="0x01" rw="RW" size="1">
          <bitfield caption="Data Direction Set" mask="0xff" name="DIRSET" rw="RW"/>
        </register>
        <register caption="Data Direction Toggle" initval="0x00" name="DIRTGL" offset="0x03" rw="RW" size="1">
          <bitfield caption="Data Direction Toggle" mask="0xff" name="DIRTGL" rw="RW"/>
        </register>
        <register caption="Input Value" initval="0x00" name="IN" offset="0x08" rw="RW" size="1">
          <bitfield caption="Input Value" mask="0xff" name="IN" rw="R"/>
        </register>
        <register caption="Interrupt Flags" initval="0x00" name="INTFLAGS" offset="0x09" rw="RW" size="1">
          <bitfield caption="Pin Interrupt Flag" mask="0xff" name="INT" rw="RW"/>
        </register>
        <register caption="Output Value" initval="0x00" name="OUT" offset="0x04" rw="RW" size="1">
          <bitfield caption="Output Value" mask="0xff" name="OUT" rw="RW"/>
        </register>
        <register caption="Output Value Clear" initval="0x00" name="OUTCLR" offset="0x06" rw="RW" size="1">
          <bitfield caption="Output Value Clear" mask="0xff" name="OUTCLR" rw="RW"/>
        </register>
        <register caption="Output Value Set" initval="0x00" name="OUTSET" offset="0x05" rw="RW" size="1">
          <bitfield caption="Output Value Set" mask="0xff" name="OUTSET" rw="RW"/>
        </register>
        <register caption="Output Value Toggle" initval="0x00" name="OUTTGL" offset="0x07" rw="RW" size="1">
          <bitfield caption="Output Value Toggle" mask="0xff" name="OUTTGL" rw="RW"/>
        </register>
        <register caption="Pin Control Config" initval="0x00" name="PINCONFIG" offset="0x0B" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin Control Clear" initval="0x00" name="PINCTRLCLR" offset="0x0E" rw="RW" size="1">
          <bitfield caption="Pin control clear mask" mask="0xff" name="PINCTRLCLR" rw="RW"/>
        </register>
        <register caption="Pin Control Set" initval="0x00" name="PINCTRLSET" offset="0x0D" rw="RW" size="1">
          <bitfield caption="Pin control set mask" mask="0xff" name="PINCTRLSET" rw="RW"/>
        </register>
        <register caption="Pin Control Update" initval="0x00" name="PINCTRLUPD" offset="0x0C" rw="RW" size="1">
          <bitfield caption="Pin control update mask" mask="0xff" name="PINCTRLUPD" rw="RW"/>
        </register>
        <register caption="Pin 0 Control" initval="0x00" name="PIN0CTRL" offset="0x10" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 1 Control" initval="0x00" name="PIN1CTRL" offset="0x11" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 2 Control" initval="0x00" name="PIN2CTRL" offset="0x12" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 3 Control" initval="0x00" name="PIN3CTRL" offset="0x13" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 4 Control" initval="0x00" name="PIN4CTRL" offset="0x14" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 5 Control" initval="0x00" name="PIN5CTRL" offset="0x15" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 6 Control" initval="0x00" name="PIN6CTRL" offset="0x16" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Pin 7 Control" initval="0x00" name="PIN7CTRL" offset="0x17" rw="RW" size="1">
          <bitfield caption="Inverted I/O Enable" mask="0x80" name="INVEN" rw="RW"/>
          <bitfield caption="Input/Sense Configuration" mask="0x7" name="ISC" rw="RW" values="PORT_ISC"/>
          <bitfield caption="Pullup enable" mask="0x8" name="PULLUPEN" rw="RW"/>
        </register>
        <register caption="Port Control" initval="0x00" name="PORTCTRL" offset="0x0A" rw="RW" size="1">
          <bitfield caption="Slew Rate Limit Enable" mask="0x1" name="SRL" rw="RW"/>
        </register>
      </register-group>
      <value-group caption="Input/Sense Configuration select" name="PORT_ISC">
        <value caption="Interrupt disabled but input buffer enabled" name="INTDISABLE" value="0x0"/>
        <value caption="Sense Both Edges" name="BOTHEDGES" value="0x1"/>
        <value caption="Sense Rising Edge" name="RISING" value="0x2"/>
        <value caption="Sense Falling Edge" name="FALLING" value="0x3"/>
        <value caption="Digital Input Buffer disabled" name="INPUT_DISABLE" value="0x4"/>
        <value caption="Sense low Level" name="LEVEL" value="0x5"/>
      </value-group>
    </module>

trembel avatar Aug 08 '20 14:08 trembel

Okay, I'd say the best way to deal with this is a whitelist approach. So the patch should only touch registers named

  • For 'old' scheme (n is port letter)
    • DDRn
    • PORTn
    • PINn
  • For 'new' scheme
    • DIR, DIRSET, DIRCLR, DIRTGL
    • OUT, OUTSET, OUTCLR, OUTTGL
    • IN
    • INTFLAGS

What do you think?

Rahix avatar Aug 08 '20 15:08 Rahix

Yes, I think this should work (but not 100% sure if this is the only place were the scheme differs).

For the 'new' scheme: These registers are listened only once in the atdf, but each port has them. So basically it is needed that each port gets a "copy" of all those registers.

Maybe an additional atdf2svd flag can be set for the avrxmega3 architecture and in the Makefile the targets could be split in two groups (traditional and avrxmega3), where the avrxmega3 uses atdf2svd with the flag set. In this way the whitelist has not to be in the atdf2svd.

Or atdf2svd automatically recognizes which family the atdf belongs to (if it finds DIR, DIRSER, ... use 'new' scheme).

trembel avatar Aug 08 '20 17:08 trembel

For the 'new' scheme: These registers are listened only once in the atdf, but each port has them. So basically it is needed that each port gets a "copy" of all those registers.

If I'm not mistaken, this is already working. But we'll have to check, of course.

Maybe an additional atdf2svd flag can be set for the avrxmega3 architecture and in the Makefile the targets could be split in two groups (traditional and avrxmega3), where the avrxmega3 uses atdf2svd with the flag set. In this way the whitelist has not to be in the atdf2svd.

IMO it would really cool if atdf2svd can figure this out on its own so you can't accidentally forget the flag. But if that's not reliably possible, your idea is the way to go, I'd say.

Rahix avatar Aug 08 '20 17:08 Rahix

Very cool to see people working on support for the newer series of AVR. I have been looking at adding support for these newer chips too.

For detecting version I think it might be possible to use the schema-version attribute in the avr-tools-device-file tag. For the atmega328p it is 0.3 and for the avr128da48 it is 4.4. Unfortunately it is 0.3 for both xmega, tiny0, tiny1 and mega0 so it might not work.

Another attribute that might work is the architecture attribute in the device tag. It is AVR8 for most older megas and tinys, AVR8_XMEGA for xmegas, and AVR8X for tiny0, tiny1, mega0 and AVRDx.

There is also an issue that module list contain the caption attribute of that module, but the instances of that module does not contain the caption attribute. Currently atdf2svd expects it to be on the instance.

jwagen avatar Aug 09 '20 12:08 jwagen

There is also an issue that module list contain the caption attribute of that module, but the instances of that module does not contain the caption attribute. Currently atdf2svd expects it to be on the instance.

Would adding a fall-back for the other tag fix this, or is a more elaborate distinction needed?

Rahix avatar Aug 09 '20 12:08 Rahix

Would adding a fall-back for the other tag fix this, or is a more elaborate distinction needed?

Yes a fall-back does seem to be sufficient. So I don't think something more elaborate is necessary at least for now.

jwagen avatar Aug 09 '20 13:08 jwagen

Are there any updates to this?

trembel avatar Aug 24 '20 19:08 trembel

Let's make a list of necessary work in atdf2svd:

  • [x] Fix signals_to_port_fields patch: Rahix/atdf2svd#6
  • [x] Fall back to caption from module if instance caption is missing: Rahix/atdf2svd#5
  • [ ] Fix parsing of nested register groups: Rahix/atdf2svd#4
  • [ ] Fix parsing of nested interrupt groups: No issue yet

For minimal support, fixing just the first one should be a good start. For supporting more peripherals, the rest (especially the 3rd one) are needed.

Rahix avatar Aug 25 '20 06:08 Rahix

I now released version 0.2.0 of atdf2svd with lots of improvements related to this issue. Thanks a lot to @trembel and @explicite who did most of the work!

Rahix avatar Nov 25 '20 21:11 Rahix