askn37 / avrdude

AVRDUDE is a utility to program AVR microcontrollers
GNU General Public License v2.0
0 stars 0 forks source link

全般的なTODO(日本語) #2

Open askn37 opened 9 months ago

askn37 commented 9 months ago

このページは気がつくと更新されます。

It's written frankly, so even if it's automatically translated into English, it might not come across correctly.

進行中

提案、報告済

解決済

些細な、あるいはまだ報告していない提案と問題

(core)

(moderAVR 構成)

(serialupdi)

(jtagmkII)

(これはずっと後回しで良い)

ちょっと別な話(ゆるい結合性)

AVRデータシート日本語翻訳 https://avr.jp/ (添削)

mcuee commented 9 months ago

Thanks a lot. どうもありがとうございます. (Using Google Translate).

mcuee commented 9 months ago

些細な、あるいはまだ報告していない提案と問題 Minor or unreported suggestions and issues (Google Translate)

If you can, please still report the issue to avrdude project. Thanks.

askn37 commented 8 months ago

喫緊ではないが、考えなければならないこと。

Not urgent, but something to think about.

askn37 commented 8 months ago

整理整頓の季節

Tidying up season

askn37 commented 8 months ago

ちょっと気になるので、preqを準備

askn@alicia avrdude_preq % gh pr checkout 1549
Switched to branch 'issue1546'
Your branch is up to date with 'origin/issue1546'.
Already up to date.
askn@alicia avrdude_preq % gh pr checkout 1543
Switched to branch 'issue_serialupdi_REVID_check'
Your branch is behind 'origin/issue_serialupdi_REVID_check' by 9 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
Updating 4be0f371..f5a86336
Fast-forward
 NEWS                 |  3 +++
 src/CMakeLists.txt   |  1 +
 src/avrdude.conf.in  | 16 ++++++++++------
 src/config.c         |  2 ++
 src/config_gram.y    |  6 ++++++
 src/configure.ac     |  4 ++++
 src/developer_opts.c |  2 +-
 src/doc/avrdude.texi |  5 ++++-
 src/lexer.l          |  1 +
 src/libavrdude.h     |  1 +
 src/main.c           |  2 ++
 11 files changed, 35 insertions(+), 8 deletions(-)
askn@alicia avrdude_preq % gh pr checkout 1538
remote: Enumerating objects: 51, done.
remote: Counting objects: 100% (51/51), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 51 (delta 28), reused 41 (delta 25), pack-reused 0
Unpacking objects: 100% (51/51), 238.18 KiB | 1.62 MiB/s, done.
From https://github.com/avrdudes/avrdude
   566cfad7..9c894e15  refs/pull/1538/head -> memory-types
Switched to branch 'memory-types'

デバッグ出力を追加。

diff --git a/src/jtagmkII.c b/src/jtagmkII.c
index c8d330d9..ddaca713 100644
--- a/src/jtagmkII.c
+++ b/src/jtagmkII.c
@@ -2112,12 +2112,17 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV

 static int jtagmkII_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, char *chip_rev) {
   // XMEGA using JTAG or PDI, tinyAVR0/1/2, megaAVR0, AVR-Dx, AVR-Ex using UPDI
+  pmsg_debug("jtagmkII_read_chip_rev(): check start\n");
   if(p->prog_modes & (PM_PDI | PM_UPDI)) {
     AVRMEM *m = avr_locate_io(p);
     if(!m) {
       pmsg_error("cannot locate io memory; is avrdude.conf up to date?\n");
       return -1;
     }
+    pmsg_debug("jtagmkII_read_chip_rev(): p : 0x%02x\n", p);
+    pmsg_debug("jtagmkII_read_chip_rev(): m : 0x%02x\n", m);
+    pmsg_debug("jtagmkII_read_chip_rev(): p->prog_modes : 0x%04lx\n", p->prog_modes);
+    pmsg_debug("jtagmkII_read_chip_rev(): p->syscfg_base+1 : 0x%04lx\n", p->syscfg_base+1);
     int status = pgm->read_byte(pgm, p, m,
         p->prog_modes & PM_PDI? p->mcu_base+3 :p->syscfg_base+1,
         (unsigned char *)chip_rev);

実行

+/Users/askn/Collaborator/avrdude_preq/build_darwin/src/avrdude -qvvvv -p t202 -c jtag2updi -P /dev/cu.usbserial-230 -l block_avrdude_preq_updi4avr.log -U sig:r:block_sig_updi4avr_avrdude_preq.hex:i -U fuses:r:block_fuses_updi4avr_avrdude_preq.hex:i -U lock:r:block_lock_updi4avr_avrdude_preq.hex:i -U prodsig:r:block_prodsig_updi4avr_avrdude_preq.hex:i -U sernum:r:block_sernum_updi4avr_avrdude_preq.hex:i -U usersig:r:block_usersig_updi4avr_avrdude_preq.hex:i -U eeprom:r:block_eeprom_updi4avr_avrdude_preq.hex:i -U flash:r:block_flash_updi4avr_avrdude_preq.hex:i
avrdude: Version 7.2-20231102 (9c894e15)

ログを精査

avrdude: jtagmkII_read_chip_rev(): check start
avrdude: jtagmkII_read_chip_rev(): p : 0x1d85e4c0
avrdude: jtagmkII_read_chip_rev(): m : 0x2782560
avrdude: jtagmkII_read_chip_rev(): p->prog_modes : 0x0011
avrdude: jtagmkII_read_chip_rev(): p->syscfg_base+1 : 0x0f01
avrdude: jtagmkII_read_byte(.., io, 0xf01, ...)
avrdude: jtagmkII_program_enable(): Sending enter progmode command: 
avrdude: jtagmkII_send(): sending 1 bytes

~~Omission~~

avrdude: jtagmkII_read_byte(): sending read memory command: 
avrdude: jtagmkII_send(): sending 10 bytes
avrdude: ser_send: . [1b] . [09] . [00] 
. [0a] . [00] . [00] . [00] 
. [0e] . [05] . [c0] 
. [01] . [00] . [00] . [00] 
. [01] . [0f] . [00] . [01] 
. [93] . [bd]

なんだって!?どこで 0x01000f01 に化けた?

  } else if (mem_is_io(mem)) {
    cmd[1] = MTYPE_FLASH;
    addr += avr_data_offset(p);
    pmsg_notice2("jtagmkII_read_byte : 2235 : addr : 0x%lx\n", addr);
  } else {

ここかな?

avrdude: jtagmkII_read_byte : 2152 : addr : 0xf01
avrdude: jtagmkII_read_byte : mem->offset : 0x00000000
avrdude: jtagmkII_read_byte : 2235 : addr : 0x1000f01
avrdude: jtagmkII_read_byte(): sending read memory command: 
avrdude: jtagmkII_send(): sending 10 bytes
avrdude: ser_send: . [1b] . [09] . [00] 
. [0a] . [00] . [00] . [00] 
. [0e] . [05] . [c0] 
. [01] . [00] . [00] . [00] 
. [01] . [0f] . [00] . [01] 
. [93] . [bd]

ブルズアイ

  } else if (mem_is_io(mem)) {
    cmd[1] = MTYPE_FLASH;
    if (!(p->prog_modes & (PM_UPDI)))
      addr += avr_data_offset(p);
    pmsg_notice2("jtagmkII_read_byte : 2236 : addr : 0x%lx\n", addr);
  } else {

PM_UPDIを除外する。

avrdude: jtagmkII_read_byte : 2152 : addr : 0xf01
avrdude: jtagmkII_read_byte : mem->offset : 0x00000000
avrdude: jtagmkII_read_byte : 2236 : addr : 0xf01
avrdude: jtagmkII_read_byte(): sending read memory command: 
avrdude: jtagmkII_send(): sending 10 bytes
avrdude: ser_send: . [1b] . [09] . [00] 
. [0a] . [00] . [00] . [00] 
. [0e] . [05] . [c0] 
. [01] . [00] . [00] . [00] 
. [01] . [0f] . [00] . [00] 
. [1a] . [ac]

正解

avrdude: jtagmkII_read_chip_rev(): received chip silicon revision: 0x02
avrdude: silicon revision: 0.2

じゃあt202本来のSRAM先頭アドレスを入れてみよう。

    memory "data"
        size               = 128;
        offset             = 0x3f80;
    ;
avrdude: jtagmkII_read_byte : 2152 : addr : 0xf01
avrdude: jtagmkII_read_byte : mem->offset : 0x00000000
avrdude: jtagmkII_read_byte : 2236 : addr : 0xf01
avrdude: jtagmkII_read_byte(): sending read memory command: 
avrdude: jtagmkII_send(): sending 10 bytes
avrdude: ser_send: . [1b] . [09] . [00] 
. [0a] . [00] . [00] . [00] 
. [0e] . [05] . [c0] 
. [01] . [00] . [00] . [00] 
. [01] . [0f] . [00] . [00] 
. [1a] . [ac]
avrdude: jtagmkII_read_chip_rev(): received chip silicon revision: 0x02
avrdude: silicon revision: 0.2

OK、影響されていない。これが正しい。

ダブルチェック。現在のavrdude_mainの"data"を書き換えて比較。

avrdude: jtagmkII_read_byte(): sending read memory command: 
avrdude: jtagmkII_send(): sending 10 bytes
avrdude: ser_send: . [1b] . [09] . [00] 
. [0a] . [00] . [00] . [00] 
. [0e] . [05] . [c0] 
. [01] . [00] . [00] . [00] 
. [81] N [4e] . [00] . [00] 
. [de] . [dd]
avrdude: jtagmkII_recv():
avrdude: ser_recv: . [1b]
avrdude: ser_recv: . [09]
avrdude: ser_recv: . [00]
avrdude: ser_recv: . [02]
avrdude: ser_recv: . [00]
avrdude: ser_recv: . [00]
avrdude: ser_recv: . [00]
avrdude: ser_recv: . [0e]
avrdude: ser_recv: . [82] . [9f]
avrdude: ser_recv: . [00]
avrdude: ser_recv: . [95]

avrdude: jtagmkII_recv(): got message seqno 9 (command_sequence == 9)
avrdude: jtagmkII_recv: . [82] . [9f]

Raw message:
0x82 0x9f 
memory contents:
0x9f  
avrdude: jtagmkII_read_chip_rev(): received chip silicon revision: 0xffffff9f
avrdude: silicon revision: fffffff9.f

0x100f01 でも 0x0f01 でもなく、0x4e81 が読まれたので、結果は 0x9f そして'%x.%x'なので、'fffffff9.f'と表示。 ここもダメじゃねえか。Σ( ̄。 ̄ノ)ノ

-    pmsg_notice("silicon revision: %x.%x\n", chip_rev[0] >> 4, chip_rev[0] & 0x0f);
+    pmsg_notice("silicon revision: %x.%x\n", (unsigned char)(chip_rev[0]) >> 4, chip_rev[0] & 0x0f);
avrdude: jtagmkII_read_chip_rev(): received chip silicon revision: 0xffffff9f
avrdude: silicon revision: 9.f

どうよ?

askn37 commented 8 months ago

30.3.8.3 User Row Programming

このセクションの記述は、最初の実装のATtiny202から、最新のAVR64EB32まで一貫して同じだが、どう解釈していいかわからん。以下、英語と日本語の対訳。

原文:

30.3.8.3 User Row Programming

The User Row Programming feature allows programming new values to the user row (USERROW) on a locked device. To program with this functionality enabled, the following sequence must be followed:

  1. Enter the USERROW-Write key located in Table 30-5 by using the KEY instruction. See Table 30-5 for the USERROW-Write signature.
  2. Optional: Read the User Row Write Key Status (UROWWRITE) bit from the ASI Key Status (UPDI.ASI_KEY_STATUS) register to see if the key has been activated.
  3. Write the signature to the Reset Request (RSTREQ) bit in the ASI Reset Request (UPDI.ASI_RESET_REQ) register. This will issue a System Reset.
  4. Write 0x00 to the ASI Reset Request (UPDI.ASI_RESET_REQ) register to clear the System Reset.
  5. Read the Start User Row Programming (UROWPROG) bit from the ASI System Status (UPDI.ASI_SYS_STATUS) register.
  6. User Row Programming can start when the UROWPROG bit is ‘1’. If UROWPROG is ‘0’, return to step 5.
  7. The data to be written to the User Row must first be written to a buffer in the RAM. The writable area in the RAM has a size of 32 bytes, and it is only possible to write user row data to the first 32 byte addresses of the RAM. Addressing outside this memory range will result in a nonexecuted write. The data will map 1:1 with the user row space when the data is copied into the user row upon completion of the Programming sequence.
  8. When all user row data has been written to the RAM, write the User Row Programming Done (UROWDONE) bit in the ASI System Control A (UPDI.ASI_SYS_CTRLA) register.
  9. Read the Start User Row Programming (UROWPROG) bit from the ASI System Status (UPDI.ASI_SYS_STATUS) register.
  10. The User Row Programming is completed when UROWPROG bit is ‘0’. If UROWPROG bit is ‘1’, return to step 9.
  11. Write to the User Row Write Key Status (UROWWRITE) bit in the ASI Key Status (UPDI.ASI_KEY_STATUS) register.
  12. Write the signature to the Reset Request (RSTREQ) bit in the ASI Reset Request (UPDI.ASI_RESET_REQ) register. This will issue a System Reset.
  13. Write 0x00 to the ASI Reset Request (UPDI.ASI_RESET_REQ) register to clear the System Reset.
  14. The User Row Programming is complete.

It is not possible to read back data from the RAM in this mode. Only writes to the first 32 bytes of the RAM are allowed.

現在採用されている対訳 https://avr.jp/

30.3.8.3. 使用者列プログラミング

使用者列プログラミング機能は施錠されたデバイスで使用者列(USERROW)に新しい値を書くことを許します。許可されたこの機能で書き込むには、以下の手順に従わなければなりません。

  1. KEY命令を使うことによって表30-5.で示される使用者列書き込み(UROWWRITE)鍵を入力してください。UROWWRITE符号については表30-5.をご覧ください。
  2. 任意選択: 鍵が認証されたかを知るためにASI鍵状態(UPDI.ASI_KEY_STATUS)レジスタの使用者列書き込み鍵状態(UROWWRITE)ビットを読んでください。
  3. ASIリセット要求(UPDI.ASI_RESET_REQ)レジスタのリセット要求(RESREQ)ビット領域に識票を書いてください。これはシステム リセットを発行します。
  4. システム リセットを解除するためにUPDI.ASI_RESET_REQレジスタに$00を書いてください。
  5. ASIシステム状態(UPDI.ASI_SYS_STATUS)レジスタの使用者列プログラミング開始(UROWPROG)ビットを読んでください。
  6. 使用者列プログラミングはUROWPROGが’1’の時に開始することができます。UROWPROGが’0’なら、手順5.に戻ってください。
  7. 使用者列に書かれるデータは最初にRAM内の緩衝部に書かれなければなりません。RAMの書き込み可能な領域は32バイトで、 RAMの最初の32バイトのアドレスにだけ使用者列データを書くことが可能です。このメモリ範囲外のアドレス指定は実行されない書き込みに終わります。書き込み手順の完了でデータが使用者列データに複写される時に、このデータが使用者列空間と1対1で割り当てられます。
  8. 全ての使用者列データがRAMに書かれると、ASIシステム制御A(UPDI.ASI_SYS_CTRLA)レジスタの使用者列書き込み終了(URO WWRITE_FINAL)ビットに(’1’を)書いてください。
  9. UPDI.ASI_SYS_STATUSレジスタのUROWPROGビットを読んでください。
  10. 使用者列プログラミングはUROWPROGが’0’の時に完了されます。UROWPROGが’1’なら、手順9.に戻ってください。
  11. ASI鍵状態(UPDI.ASI_KEY_STATUS)レジスタの使用者列書き込み鍵状態(UROWWRITE)ビットを書いてください。
  12. ASIリセット要求(UPDI.ASI_RESET_REQ)レジスタのリセット要求(RESREQ)ビット領域に識票を書いてください。これはシステム リセットを発行 します。
  13. システム リセットを解除するためにUPDI.ASI_RESET_REQレジスタに$00を書いてください。
  14. 使用者列プログラミングは完了です。 この動作形態でSRAMからデータを読み戻すことはできません。SRAMの最初の32バイトへの書き込みだけが許されます。

肝心なのは 手順7 の解釈。長い説明の割に、この RAM について、直接の言及がなくて曖昧だ。

自分は最初、字面通りこれは RAM (==SRAM) の先頭アドレスを指していると解釈した。実際、それで正常に動作する。だがその方法は全てのチップで異なる SRAM先頭アドレス を知っていなければならない。従って ATDF の情報が、正確に構成ファイルに転写されていないとこれは実現できないはずだ。だがそれはちょっと変だ。この機能を使う時、使用者は UPDI_SIB以外の情報を決してチップから得られず、署名も確認できないので、結構当てずっぽうで書くしかない。

改めて検証コードを書いて調査すると、このアドレス指定に USER_SIGNATURES_START を用いても正常に機能することを確認できた。つまり USERROW の上に バッファメモリ が重ねられている事実が判明する。この仕組みは FLASH write と同じであるから不思議ではない。だが前述の原文からそれは読み取れるだろうか?

The data will map 1:1 with the user row space はRAMからUSERROWにコピーする動作を示す。実際にそうなのだが、ここからRAM==USERROW address だと考えるのは、ずいぶん飛躍してないか?

多分、RAM という言葉が何気なく使われていることが読み手の解釈を曖昧にしており、memory という語句が使われるべきだったように思える。いやそもそも That RAM buffer address is superimposed on USERROW. としっかり説明しろよと思うのだ。Microchip本社にドキュメント改善要求を出すべきだな。

askn37 commented 8 months ago

諸事情から、JTAG2UPDI を再テストしている。それで気付いた。avrdude_main は現在まで、CMND_XMEGA_ERASE+XMEGA_ERASE_USERSIG を送ってくる形跡が見られない。JTAG2UPDI はこれに対応しているのだが、送ってこないために NVMCTRL v2 以降の場合、USERROW を再初期化できないので、ただ1回しか正常に書くことができない。

なんやかやで JTAG2UPDI を NVMCTRL v3 以上に対応させる自作パッチを作り始めないと解らなかっただろう。

-D オプションの挙動(いつからかリードライトバック動作に変更された)も納得いかないので、自分の価値観だと JTAGmkII 実装は JTAGICEmkII と多くの面で合致していないし「動いてるからそれでよし」になってる。大元のAVR067が暫定データシートとして放置されてるのが悪いのだけど、JTAGICEmk3 以降は情報公開しない方針になったため、クローン実装可能な最新公開文書はそれが最後だ。

結局既存のドライバーモジュールを改善するのは諦めて、互換実装を改めて再定義し(全く違う実装を新たに作るのは、違う話だ)公開技術文書をアーカイブするのが一番後の世のためになりそうだ。

Due to various circumstances, we are retesting JTAG2UPDI. That's when I realized. Until now, there is no evidence that avrdude_main sends CMND_XMEGA_ERASE+XMEGA_ERASE_USERSIG. JTAG2UPDI supports this, but because it is not sent, he cannot reinitialize USERROW in NVMCTRL v2 or later, so it can only be successfully written once.

For some reason, he probably didn't understand JTAG2UPDI until he started making his own patch to make it compatible with NVMCTRL v3 or higher.

I also don't understand the behavior of the -D option (which has been changed to read/write back behavior at some point), so from my perspective, he thinks that the JTAGmkII implementation doesn't match his JTAGICEmkII in many aspects, and that it's working. That's fine.'' It's a shame that the original AVR067 has been left as a provisional data sheet, but since the policy has been not to release information after JTAGICEmk3, that is the last latest public document that can be cloned.

In the end, the best thing to do for future generations is to give up on improving the existing driver module, redefine a compatible implementation (creating a completely different implementation is a different story), and archive the public technical documentation. It looks like it's going to be.

askn37 commented 8 months ago

Until now, there is no evidence that avrdude_main sends CMND_XMEGA_ERASE+XMEGA_ERASE_USERSIG.

この話には少し補足がいるだろう。UPDI実装に限れば、実はUSERROWは四通りの方法で書き換えができる。そのうちの二つでは、送ってこなくても構わない。送られてきても無視すれば良い。

どの方法を選択するかはプログラマーの自由なので、単にその選択肢を AVRDUDE が知らないだけだ。

JTAG2UPDI が AVRDUDE の知らない方法を選択した理由はわからないが、これは別のリファレンス実装を元に JTAG2UPDI が作られたことを示唆する。あとから AVRDUDE が JTAG2UPDI をサポートした事実もある。それを行ったのは JTAG2UPDI 作者本人ではないのだろう。そこで齟齬が生じた。多分そういうこと。

This story may require some additions. As far as UPDI implementation is concerned, USERROW can actually be rewritten in four ways. For two of them, you don't have to send it. If you receive one, just ignore it.

It's up to the programmer to choose which method to use, so AVRDUDE simply doesn't know about that option.

I don't know why JTAG2UPDI chose a method that her AVRDUDE does not, but this suggests that her JTAG2UPDI was based on a different reference implementation. Later on, he also found out that AVRDUDE supported her JTAG2UPDI. He probably wasn't the author of JTAG2UPDI who did that. There, a discrepancy arose. Probably something like that.

askn37 commented 7 months ago

ATパックリポジトリが更新され、[Microchip AVR-Dx Series Device Support (2.4.286)]が公開された。

2.4.286 (2023-12-12) - Added AVR64DU28 and AVR64DU32.

待望の AVR-DUサポート初公開。ただしデータシートはまだ公開されていない。見つけられるのは ATDFとヘッダーファイルだけということだ。

早速ARパックをダウンロードしてAVR-DA/DBのヘッダーファイルと比較してみると、早速驚愕の事実が。AVRDUDE やブートローダーの実装に直接関わる部分を抜き書きすると、、、

--- test/PACK4/include/avr/ioavr64db32.h    2023-12-01 00:00:00
+++ test/PACK4/include/avr/ioavr64du32.h    2023-12-01 00:00:00

~~~

 ---------------------------------------------------------------------------
 NVMCTRL - Non-volatile Memory Controller
 --------------------------------------------------------------------------
 */
@@ -1503,13 +1055,14 @@
 {
     register8_t CTRLA;  /* Control A */
     register8_t CTRLB;  /* Control B */
-    register8_t STATUS;  /* Status */
+    register8_t CTRLC;  /* Control C */
+    register8_t reserved_1[1];
     register8_t INTCTRL;  /* Interrupt Control */
     register8_t INTFLAGS;  /* Interrupt Flags */
-    register8_t reserved_1[1];
-    _WORDREGISTER(DATA);  /* Data */
+    register8_t STATUS;  /* Status */
+    register8_t reserved_2[1];
+    _DWORDREGISTER(DATA);  /* Data */
     _DWORDREGISTER(ADDR);  /* Address */
-    register8_t reserved_2[4];
 } NVMCTRL_t;

 /* Command select */
@@ -1540,10 +1093,9 @@
 typedef enum NVMCTRL_ERROR_enum
 {
     NVMCTRL_ERROR_NOERROR_gc = (0x00<<4),  /* No Error */
-    NVMCTRL_ERROR_ILLEGALCMD_gc = (0x01<<4),  /* Write command not selected */
-    NVMCTRL_ERROR_ILLEGALSADDR_gc = (0x02<<4),  /* Write to section not allowed */
-    NVMCTRL_ERROR_DOUBLESELECT_gc = (0x03<<4),  /* Selecting new write command while write command already seleted */
-    NVMCTRL_ERROR_ONGOINGPROG_gc = (0x04<<4)  /* Starting a new programming operation before previous is completed */
+    NVMCTRL_ERROR_INVALIDCMD_gc = (0x01<<4),  /* Write command not selected or not valid */
+    NVMCTRL_ERROR_WRITEPROTECT_gc = (0x02<<4),  /* Write to section not allowed */
+    NVMCTRL_ERROR_CMDCOLLISION_gc = (0x03<<4)  /* Selecting new write command while programming is ongoing */
 } NVMCTRL_ERROR_t;

~~~

 /* NVMCTRL - Non-volatile Memory Controller */
 #define NVMCTRL_CTRLA  _SFR_MEM8(0x1000)
 #define NVMCTRL_CTRLB  _SFR_MEM8(0x1001)
-#define NVMCTRL_STATUS  _SFR_MEM8(0x1002)
-#define NVMCTRL_INTCTRL  _SFR_MEM8(0x1003)
-#define NVMCTRL_INTFLAGS  _SFR_MEM8(0x1004)
-#define NVMCTRL_DATA  _SFR_MEM16(0x1006)
-#define NVMCTRL_DATAL  _SFR_MEM8(0x1006)
-#define NVMCTRL_DATAH  _SFR_MEM8(0x1007)
-#define NVMCTRL_ADDR  _SFR_MEM32(0x1008)
-#define NVMCTRL_ADDR0  _SFR_MEM8(0x1008)
-#define NVMCTRL_ADDR1  _SFR_MEM8(0x1009)
-#define NVMCTRL_ADDR2  _SFR_MEM8(0x100A)
-#define NVMCTRL_ADDR3  _SFR_MEM8(0x100B)
+#define NVMCTRL_CTRLC  _SFR_MEM8(0x1002)
+#define NVMCTRL_INTCTRL  _SFR_MEM8(0x1004)
+#define NVMCTRL_INTFLAGS  _SFR_MEM8(0x1005)
+#define NVMCTRL_STATUS  _SFR_MEM8(0x1006)
+#define NVMCTRL_DATA  _SFR_MEM32(0x1008)
+#define NVMCTRL_DATA0  _SFR_MEM8(0x1008)
+#define NVMCTRL_DATA1  _SFR_MEM8(0x1009)
+#define NVMCTRL_DATA2  _SFR_MEM8(0x100A)
+#define NVMCTRL_DATA3  _SFR_MEM8(0x100B)
+#define NVMCTRL_ADDR  _SFR_MEM32(0x100C)
+#define NVMCTRL_ADDR0  _SFR_MEM8(0x100C)
+#define NVMCTRL_ADDR1  _SFR_MEM8(0x100D)
+#define NVMCTRL_ADDR2  _SFR_MEM8(0x100E)
+#define NVMCTRL_ADDR3  _SFR_MEM8(0x100F)

~~~

 #if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
-#  define USER_SIGNATURES_START     (0x1080)
-#  define USER_SIGNATURES_SIZE      (32)
-#  define USER_SIGNATURES_PAGE_SIZE (32)
-#else
-#  define USER_SIGNATURES_START     (0x1080U)
-#  define USER_SIGNATURES_SIZE      (32U)
-#  define USER_SIGNATURES_PAGE_SIZE (32U)
-#endif
-#define USER_SIGNATURES_END       (USER_SIGNATURES_START + USER_SIGNATURES_SIZE - 1)
-
-#if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
-#  define SIGNATURES_START     (0x1100)
+#  define SIGNATURES_START     (0x1080)
 #  define SIGNATURES_SIZE      (3)
 #  define SIGNATURES_PAGE_SIZE (128)
 #else
-#  define SIGNATURES_START     (0x1100U)
+#  define SIGNATURES_START     (0x1080U)
 #  define SIGNATURES_SIZE      (3U)
 #  define SIGNATURES_PAGE_SIZE (128U)
 #endif
 #define SIGNATURES_END       (SIGNATURES_START + SIGNATURES_SIZE - 1)

~~~

 #if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
-#  define PROD_SIGNATURES_START     (0x1103)
+#  define PROD_SIGNATURES_START     (0x1083)
 #  define PROD_SIGNATURES_SIZE      (125)
 #  define PROD_SIGNATURES_PAGE_SIZE (128)
 #else
-#  define PROD_SIGNATURES_START     (0x1103U)
+#  define PROD_SIGNATURES_START     (0x1083U)
 #  define PROD_SIGNATURES_SIZE      (125U)
 #  define PROD_SIGNATURES_PAGE_SIZE (128U)
 #endif
 #define PROD_SIGNATURES_END       (PROD_SIGNATURES_START + PROD_SIGNATURES_SIZE - 1)

 #if (defined(__ASSEMBLER__) || defined(__IAR_SYSTEMS_ASM__))
+#  define BOOTROW_START     (0x1100)
+#  define BOOTROW_SIZE      (256)
+#  define BOOTROW_PAGE_SIZE (256)
+#else
+#  define BOOTROW_START     (0x1100U)
+#  define BOOTROW_SIZE      (256U)
+#  define BOOTROW_PAGE_SIZE (256U)
+#endif
+#define BOOTROW_END       (BOOTROW_START + BOOTROW_SIZE - 1)

~~~

@@ -7078,6 +6162,26 @@
 #define FUSE8_DEFAULT  (0x0)
 #define FUSE_BOOTSIZE_DEFAULT  (0x0)

+/* Fuse Byte 9 Reserved */
+
+/* Fuse Byte 10 (PDICFG) */
+#define FUSE_LEVEL0  (unsigned char)_BV(0)  /* Protection Level Bit 0 */
+#define FUSE_LEVEL1  (unsigned char)_BV(1)  /* Protection Level Bit 1 */
+#define FUSE_KEY0  (unsigned char)_BV(4)  /* NVM Protection Activation Key Bit 0 */
+#define FUSE_KEY1  (unsigned char)_BV(5)  /* NVM Protection Activation Key Bit 1 */
+#define FUSE_KEY2  (unsigned char)_BV(6)  /* NVM Protection Activation Key Bit 2 */
+#define FUSE_KEY3  (unsigned char)_BV(7)  /* NVM Protection Activation Key Bit 3 */
+#define FUSE_KEY4  (unsigned char)_BV(8)  /* NVM Protection Activation Key Bit 4 */
+#define FUSE_KEY5  (unsigned char)_BV(9)  /* NVM Protection Activation Key Bit 5 */
+#define FUSE_KEY6  (unsigned char)_BV(10)  /* NVM Protection Activation Key Bit 6 */
+#define FUSE_KEY7  (unsigned char)_BV(11)  /* NVM Protection Activation Key Bit 7 */
+#define FUSE_KEY8  (unsigned char)_BV(12)  /* NVM Protection Activation Key Bit 8 */
+#define FUSE_KEY9  (unsigned char)_BV(13)  /* NVM Protection Activation Key Bit 9 */
+#define FUSE_KEY10  (unsigned char)_BV(14)  /* NVM Protection Activation Key Bit 10 */
+#define FUSE_KEY11  (unsigned char)_BV(15)  /* NVM Protection Activation Key Bit 11 */
+#define FUSE10_DEFAULT  (0x3)
+#define FUSE_PDICFG_DEFAULT  (0x3)

AVR-DUは AVR-DBをベースに MVIOを削除してUSB周辺機能に置き換えるだけかと想像していたが、その程度の変更では済まなかったようだ。長らくペンディングしていた理由はこれだろうか。AC/ADCや CLKCTRLにも細かな差異があるし、もしかするとチップマスクを丸ごと全部再設計したのか?