AVR-LIBC + AVR-Dx_DFP.2.4.286.atpack
で、AVR64DU28 と AVR64DU32 のエンジニアサンプル向け暫定対応ビルドが可能になった。実に2年以上のペンディング期間を経て、待望の AVR-DUシリーズ登場である。
え?何が待望だったかって? 現時点ではまだ他に何も公開情報もない状態だが、取り下げ前のブリーフノート(2021/08)と、今回公開された ATpack中の ATDFファイルからは以下の情報が読み取れる。
- AVR-Dxシリコンベースの新世代AVR(俗に modernAVR)
- フラッシュ搭載量は 16/32/64KiB の 3グレード。
- 最大動作周波数は内蔵RCを使っても動作電圧 1.8V〜5.5V 全域で 32 MHz。オールインワン 8-bit MCU では最速クラスの 32 MIPS。
- 当時のブリーフノートでは最大 24 MHzだが、公開 ATDFでは訂正されたように見える。まあ 32 MHz / 28 MHz 駆動は公称 5V駆動時制限でも不思議ではないが。
- 逆に最低動作周波数は 512 Hz。それで使用する変人はそうそういないが、できるものはできる。
- USB 2.0
Full-Speed
インタフェース周辺機能を 1器内蔵- 内蔵PLLで最低 48 MHz駆動。約3V以上投入時に動作可能。
- 外付けの LDO を追加すれば、CPU動作電圧は独立して 1.8V〜5.5V で自由に設定できる。異なる電圧の GPIO と混在接続ができるのは大きなメリットだ。
- 16 個のエンドポイントアドレス、1つの入力エンドポイントと 1つの出力エンドポイントがあり、最大 31エンドポイントに対応
- 割込負荷とソフトウェア介入を軽減するマルチパケット転送。
- 内蔵PLLで最低 48 MHz駆動。約3V以上投入時に動作可能。
- 製造予定外囲器
- 32-pin VQFN 5x5 mm and TQFP 7x7 mm
- 28-pin VQFN 4x4 mm, SPDIP and SSOP
- 20-pin SOIC
- 14-pin SOIC
- なんと 14ピンと 20ピンの SOICパッケージ(Flash 32KiB以下)の製造予定(当時)がある。これは旧 ATMEL時代にも無かったトピックで、12年以上昔の PIC18F14K50 と競合する。残念ながら超小型の TSSOP/VQFN が予定されていないものの「C/C++言語でUSB変換器を自作できる」パッケージ選択肢が拡大する。
これだけだとまだちょっとそこまで便利だとは思わないだろう。だが AVR-Dx 譲りの周辺機能も備えているのがミソで;
- 周辺機能間通知のための EVSYS。
- 4組の LUT を備えた CCL。
- 2組の USART
- 動作モード: 同期、非同期、単線駆動、RS-485、LIN従装置、SPI主装置、および IrDA
- 分周比発生器、自動ボーレート、フレーム開始検出
※ USART1は(USB周辺機能で GPIO数が減らされたため)TxD:RxD ペア線のみ使用可能。
EVSYS!CCL!同期!RS-485! これがあるから良いのだよ。全4本の信号線を使う 同期全二重 RS-485 をソフトウェア記述介在なしで駆動できる強力な MCUは、modernAVR の他にないからだ。このニッチなニーズと USB-IF が同時使用できる MCUを探すと、AVR-DU 一択なのである。
ヘッダファイルから USB 周辺機能を読み解く
新たに追加された USB周辺機能だが、当然まだ世に出てない製品なので LUFA Library のサポートなども下手したら数年先だ。MPLAB X のサンプルコード追加もまだ先かもしれない。従ってこれを使おうと思ったら結構低階層レベルから USBドライバーを自力で書き起こせってことになる。まあ予習ということで、ioavr64du32.h
から関係情報を紐解いてみよう。
割り込みベクターテーブル周辺
割り込みベクターテーブルには、二つのUSB周辺機能割り込みが設けられた。名称からして前者は「フレーム開始(SOF)、休止、再開、バス リセット、CRC、下溢れ、上溢れ不能応答、異常割り込み」を、後者は「転送単位処理完了割り込み」に使われるはずだ。
/* USB0 interrupt vectors */
#define USB0_BUSEVENT_vect_num 7
#define USB0_BUSEVENT_vect _VECTOR(7) /* */
#define USB0_TRNCOMPL_vect_num 8
#define USB0_TRNCOMPL_vect _VECTOR(8) /* */
FUSEビット周辺
FUSE_SYSCFG1
にFUSE_USBSINK
ビットが存在する。USB周辺機能用の内蔵レギュレータ起動設定だ。このビットは AVR_DB/DD ではFUSE_MVSYSCFG
であった位置にある。従って従来の複電圧対応機能と排他的に USB周辺機能が実装されたことが推測できる。
/* Fuse Byte 6 (SYSCFG1) */
#define FUSE_SUT0 (unsigned char)_BV(0) /* Startup Time Bit 0 */
#define FUSE_SUT1 (unsigned char)_BV(1) /* Startup Time Bit 1 */
#define FUSE_SUT2 (unsigned char)_BV(2) /* Startup Time Bit 2 */
#define FUSE_USBSINK (unsigned char)_BV(3) /* USB Voltage Regulator Current Sink Enable */
#define FUSE6_DEFAULT (0x8)
#define FUSE_SYSCFG1_DEFAULT (0x8)
SYSCFG 周辺
REVID
の近くに、VUSBCTRL
IOレジスターが見つかる。これはFUSE_USBSINK
ビットと対応する、内蔵レギュレーターの制御設定に違いない。
/* System Configuration Registers */
// typedef struct SYSCFG_struct
register8_t VUSBCTRL; /* USB Voltage System Control */
/* SYSCFG - System Configuration Registers */
#define SYSCFG_VUSBCTRL _SFR_MEM8(0x0F06)
/* SYSCFG - System Configuration Registers */
/* SYSCFG.VUSBCTRL bit masks and bit positions */
#define SYSCFG_USBVREG_bm 0x01 /* USB Voltage Regulator bit mask. */
#define SYSCFG_USBVREG_bp 0 /* USB Voltage Regulator bit position. */
CLKCTRL 周辺
CLKCTRL
にはUSBPLLSTATUS
レジスタが追加されている。PLL
でファイル内検索すると全部で以下の情報しか見つからないので、PLL位相同期回路は USB周辺機能からの自動制御だろう。
/* Clock controller */
// typedef struct CLKCTRL_struct
register8_t USBPLLSTATUS; /* PLL Status */
/* CLKCTRL - Clock controller */
#define CLKCTRL_USBPLLSTATUS _SFR_MEM8(0x0085)
/* CLKCTRL.USBPLLSTATUS bit masks and bit positions */
#define CLKCTRL_PLLS_bm 0x01 /* PLL Stable bit mask. */
#define CLKCTRL_PLLS_bp 0 /* PLL Stable bit position. */
EVSYS ジェネレーター周辺
EVSYSチャネルジェネレーターに二つのイベントが設けられている。これはコメントにある通り USB周辺機能でバイト入出力が発生すると イベント発火させられることを示している。従って単純な応用として、EVSYS を介して直接 RX/TX インジケーター用 LED を明滅させることが出来ると理解できる。
/* Channel generator select */
// typedef struct EVSYS_struct
EVSYS_CHANNEL_USB0_RX_gc = (0xC4<<0), /* USB0 Data Byte Received */
EVSYS_CHANNEL_USB0_TX_gc = (0xC5<<0) /* USB0 Data Byte Transmitted */
USB 周辺機能レジスタ
流石に、USB 周辺機能レジスターは大量にある。コメントもインデントが整形されておらず読みづらかったから多少整形した。ATmega32U2 などが 4エンドポイント対応だったのに比べると、ステータスレジスタの数も4倍!
#define USB_MAX_ENDPOINTS 16
/* USB Device Controller EP */
typedef struct USB_EP_struct
{
register8_t STATUS; /* Endpoint Status */
register8_t CTRL; /* Endpoint Control */
_WORDREGISTER(CNT); /* Endpoint Byte Count */
_WORDREGISTER(DATAPTR); /* Endpoint Data Pointer */
_WORDREGISTER(MCNT); /* Endpoint Multi-packet Byte Count */
} USB_EP_t;
/* USB Device Controller EP_PAIR */
typedef struct USB_EP_PAIR_struct
{
USB_EP_t OUT; /* USB Device Controller OUT */
USB_EP_t IN; /* USB Device Controller IN */
} USB_EP_PAIR_t;
/* USB Device Controller EP_TABLE */
typedef struct USB_EP_TABLE_struct
{
register8_t FIFO[32]; /* FIFO Pointer Table */
USB_EP_PAIR_t EP[16]; /* USB Device Controller EP */
_WORDREGISTER(FRAMENUM); /* FRAMENUM count */
} USB_EP_TABLE_t;
/* USB Device Controller STATUS */
typedef struct USB_STATUS_struct
{
register8_t OUTCLR; /* Endpoint n OUT Status Clear */
register8_t OUTSET; /* Endpoint n OUT Status Set */
register8_t INCLR; /* Endpoint n IN Status Clear */
register8_t INSET; /* Endpoint n IN Status Set */
} USB_STATUS_t;
/* USB Device Controller */
typedef struct USB_struct
{
register8_t CTRLA; /* Control A */
register8_t CTRLB; /* Control B */
register8_t BUSSTATE; /* Bus State */
register8_t ADDR; /* Address */
register8_t FIFOWP; /* FIFO Write Pointer */
register8_t FIFORP; /* FIFO Read Pointer */
_WORDREGISTER(EPPTR); /* Endpoint Configuration Table Pointer */
register8_t INTCTRLA; /* Interrupt Control A */
register8_t INTCTRLB; /* Interrupt Control B */
register8_t INTFLAGSA; /* Interrupt Flags A */
register8_t INTFLAGSB; /* Interrupt Flags B */
register8_t reserved_1[52];
USB_STATUS_t STATUS[16]; /* USB Device Controller STATUS */
} USB_t;
#define USB0 (*(USB_t *) 0x0C00) /* USB Device Controller */
/* USB (USB0) - USB Device Controller */
#define USB0_CTRLA _SFR_MEM8(0x0C00)
#define USB0_CTRLB _SFR_MEM8(0x0C01)
#define USB0_BUSSTATE _SFR_MEM8(0x0C02)
#define USB0_ADDR _SFR_MEM8(0x0C03)
#define USB0_FIFOWP _SFR_MEM8(0x0C04)
#define USB0_FIFORP _SFR_MEM8(0x0C05)
#define USB0_EPPTR _SFR_MEM16(0x0C06)
#define USB0_EPPTRL _SFR_MEM8(0x0C06)
#define USB0_EPPTRH _SFR_MEM8(0x0C07)
#define USB0_INTCTRLA _SFR_MEM8(0x0C08)
#define USB0_INTCTRLB _SFR_MEM8(0x0C09)
#define USB0_INTFLAGSA _SFR_MEM8(0x0C0A)
#define USB0_INTFLAGSB _SFR_MEM8(0x0C0B)
#define USB0_STATUS0_OUTCLR _SFR_MEM8(0x0C40)
#define USB0_STATUS0_OUTSET _SFR_MEM8(0x0C41)
#define USB0_STATUS0_INCLR _SFR_MEM8(0x0C42)
#define USB0_STATUS0_INSET _SFR_MEM8(0x0C43)
// Omission //
#define USB0_STATUS15_OUTCLR _SFR_MEM8(0x0C7C)
#define USB0_STATUS15_OUTSET _SFR_MEM8(0x0C7D)
#define USB0_STATUS15_INCLR _SFR_MEM8(0x0C7E)
#define USB0_STATUS15_INSET _SFR_MEM8(0x0C7F)
続けて各レジスターの定義ビットを眺めるが、#define
ショートカットは膨大なので一部要約して引用する。
/* Data Size default select */
typedef enum USB_BUFSIZE_DEFAULT_enum
{
USB_BUFSIZE_DEFAULT_BUF8_gc = (0x00<<0), /* 8 bytes buffer size */
USB_BUFSIZE_DEFAULT_BUF16_gc = (0x01<<0), /* 16 bytes buffer size */
USB_BUFSIZE_DEFAULT_BUF32_gc = (0x02<<0), /* 32 bytes buffer size */
USB_BUFSIZE_DEFAULT_BUF64_gc = (0x03<<0) /* 64 bytes buffer size */
} USB_BUFSIZE_DEFAULT_t;
/* Data Size isochronous select */
typedef enum USB_BUFSIZE_ISO_enum
{
USB_BUFSIZE_ISO_BUF8_gc = (0x00<<0), /* 8 bytes buffer size */
USB_BUFSIZE_ISO_BUF16_gc = (0x01<<0), /* 16 bytes buffer size */
USB_BUFSIZE_ISO_BUF32_gc = (0x02<<0), /* 32 bytes buffer size */
USB_BUFSIZE_ISO_BUF64_gc = (0x03<<0), /* 64 bytes buffer size */
USB_BUFSIZE_ISO_BUF128_gc = (0x04<<0), /* 128 bytes buffer size */
USB_BUFSIZE_ISO_BUF256_gc = (0x05<<0), /* 256 bytes buffer size */
USB_BUFSIZE_ISO_BUF512_gc = (0x06<<0), /* 512 bytes buffer size */
USB_BUFSIZE_ISO_BUF1023_gc = (0x07<<0) /* 1023 bytes buffer size */
} USB_BUFSIZE_ISO_t;
/* Data Toggle select */
typedef enum USB_TOGGLE_enum
{
USB_TOGGLE_DATA0_gc = (0x00<<0), /* DATA0 PID in next transaction */
USB_TOGGLE_DATA1_gc = (0x01<<0) /* DATA1 PID in next transaction */
} USB_TOGGLE_t;
/* Endpoint type select */
typedef enum USB_TYPE_enum
{
USB_TYPE_DISABLE_gc = (0x00<<6), /* Endpoint Disabled */
USB_TYPE_CONTROL_gc = (0x01<<6), /* Control */
USB_TYPE_BULKINT_gc = (0x02<<6), /* Bulk or Interrupt */
USB_TYPE_ISO_gc = (0x03<<6) /* Isochronous */
} USB_TYPE_t;
/* Endpoint Direction select */
typedef enum USB_DIR_enum
{
USB_DIR_OUT_gc = (0x00<<3), /* OUT Endpoint */
USB_DIR_IN_gc = (0x01<<3) /* In Endpoint */
} USB_DIR_t;
/* USB - USB Device Controller */
/* USB.STATUS bit masks and bit positions */
#define USB_TOGGLE_bm 0x01 /* Data Toggle bit mask. */
#define USB_BUSNAK_bm 0x02 /* Data Buffer NAK bit mask. */
#define USB_STALLED_bm 0x08 /* EP Stalled bit mask. */
#define USB_EPSETUP_bm 0x10 /* EP Setup Complete bit mask. */
#define USB_TRNCOMPL_bm 0x20 /* Transaction Complete bit mask. */
#define USB_UNFOVF_bm 0x40 /* Underflow/Overflow EP bit mask. */
#define USB_CRC_bm 0x80 /* CRC Error bit mask. */
/* USB.CTRL bit masks and bit positions */
#define USB_BUFSIZE_DEFAULT_gm 0x03 /* Data Size default group mask. */
#define USB_DOSTALL_bm 0x04 /* Endpoint will respond with STALL bit mask. */
#define USB_BUFSIZE_ISO_gm 0x07 /* Data Size isochronous group mask. */
#define USB_TCDSBL_bm 0x08 /* TRNCOMPL Interrupt Disable bit mask. */
#define USB_AZLP_bm 0x10 /* Automatic zero length packet bit mask. */
#define USB_MULTIPKT_bm 0x20 /* Multipacket transfer enable bit mask. */
#define USB_TYPE_gm 0xC0 /* Endpoint type group mask. */
/* USB.CNT bit masks and bit positions */
#define USB_CNT_gm 0xFFFF /* Endpoint Byte Count group mask. */
#define USB_CNT_0_bm (1<<0) /* Endpoint Byte Count bit 0 mask. */
// Omission //
#define USB_CNT_15_bm (1<<15) /* Endpoint Byte Count bit 15 mask. */
/* USB.DATAPTR bit masks and bit positions */
#define USB_DATAPTR_gm 0xFFFF /* Endpoint data pointer group mask. */
/* USB.MCNT bit masks and bit positions */
#define USB_MCNT_gm 0xFFFF /* Multi-packet byte count group mask. */
/* USB.FIFO bit masks and bit positions */
#define USB_DIR_bm 0x08 /* Endpoint Direction bit mask. */
#define USB_EPNUM_gm 0xF0 /* Endpoint Number group mask. */
/* USB.FRAMENUM bit masks and bit positions */
#define USB_FRAMENUM_gm 0x7FF /* Frame Number group mask. */
#define USB_FRAMENUM_0_bm (1<<0) /* Frame Number bit 0 mask. */
// Omission //
#define USB_FRAMENUM_10_bm (1<<10) /* Frame Number bit 10 mask. */
#define USB_FRAMEERR_bm 0x8000 /* Frame Error bit mask. */
/* USB.OUTCLR bit masks and bit positions */
#define USB_RMWSTATUS_gm 0xFF /* Read-Modify-Write Endpoint STATUS group mask. */
/* USB.OUTSET bit masks and bit positions */
/* USB_RMWSTATUS is already defined. */
/* USB.INCLR bit masks and bit positions */
/* USB_RMWSTATUS is already defined. */
/* USB.INSET bit masks and bit positions */
/* USB_RMWSTATUS is already defined. */
/* USB.CTRLA bit masks and bit positions */
#define USB_MAXEP_gm 0x0F /* Maximum Endpoint Address group mask. */
#define USB_STFRNUM_bm 0x10 /* Store Frame Number Enable bit mask. */
#define USB_FIFOEN_bm 0x20 /* Transaction Complete FIFO Enable bit mask. */
#define USB_ENABLE_bm 0x80 /* USB Enable bit mask. */
/* USB.CTRLB bit masks and bit positions */
#define USB_ATTACH_bm 0x01 /* Attach bit mask. */
#define USB_GNAK_bm 0x02 /* Respond with NAK on all Endpoints bit mask. */
#define USB_GNAUTO_bm 0x04 /* Set GNAK Automatically after SETUP bit mask. */
#define USB_URESUME_bm 0x08 /* Send Upstream Resume bit mask. */
/* USB.BUSSTATE bit masks and bit positions */
#define USB_BUSRST_bm 0x01 /* Bus Reset bit mask. */
#define USB_SUSPENDED_bm 0x02 /* Bus Suspended bit mask. */
#define USB_DRESUME_bm 0x04 /* Downstram Resume bit mask. */
/* USB_URESUME is already defined. */
#define USB_WTRSM_bm 0x10 /* Wait Time Resume bit mask. */
/* USB.ADDR bit masks and bit positions */
#define USB_ADDR_gm 0x7F /* Device Address group mask. */
/* USB.FIFOWP bit masks and bit positions */
#define USB_FIFOWP_gm 0x1F /* FIFO Write Pointer group mask. */
/* USB.FIFORP bit masks and bit positions */
#define USB_FIFORP_gm 0x1F /* FIFO Read Pointer group mask. */
/* USB.EPPTR bit masks and bit positions */
#define USB_EPPTR_gm 0xFFFF /* Endpoint Configuration Table Pointer group mask. */
/* USB.INTCTRLA bit masks and bit positions */
#define USB_OVF_bm 0x02 /* Overflow Interrupt Enable bit mask. */
#define USB_UNF_bm 0x04 /* Underflow Interrupt Enable bit mask. */
/* USB_STALLED is already defined. */
#define USB_RESET_bm 0x10 /* Reset Interrupt Enable bit mask. */
#define USB_RESUME_bm 0x20 /* Resume Interrupt Enable bit mask. */
#define USB_SUSPEND_bm 0x40 /* Suspend Interrupt Enable bit mask. */
#define USB_SOF_bm 0x80 /* Start Of Frame Interrupt Enable bit mask. */
/* USB.INTCTRLB bit masks and bit positions */
#define USB_SETUP_bm 0x01 /* SETUP Transaction Complete Interrupt Enable bit mask. */
#define USB_GNDONE_bm 0x02 /* GNAK Operation Done Interrupt Enable bit mask. */
/* USB_TRNCOMPL is already defined. */
/* USB.INTFLAGSA bit masks and bit positions */
/* USB_OVF is already defined. */
/* USB_UNF is already defined. */
/* USB_STALLED is already defined. */
/* USB_RESET is already defined. */
/* USB_RESUME is already defined. */
/* USB_SUSPEND is already defined. */
/* USB_SOF is already defined. */
/* USB.INTFLAGSB bit masks and bit positions */
/* USB_SETUP is already defined. */
/* USB_GNDONE is already defined. */
#define USB_RMWBUSY_bm 0x04 /* RMW Busy Flag bit mask. */
/* USB_TRNCOMPL is already defined. */
USBCTRL レジスターマップ
パッと見て簡単にわかるわけないので、レジスタービット定義を表にして整理する。
$0C00 USB0 (BASE) USB_struct
7 6 5 4 3 2 1 0
+------+-------+--------+-------+-------+-------+---------+------+
$00 CTRLA |ENABLE| - | FIFOEN |STFRNUM| MWXEP 3-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$01 CTRLB | - | - | - | - |URESUME|GNAUTO | GNCAK |ATTACH|
+------+-------+--------+-------+-------+-------+---------+------+
$02 BUSSTATE | - | - | - | - | WTRSM |DRESUME|SUSPENDED|BUSRST|
+------+-------+--------+-------+-------+-------+---------+------+
$03 ADDR | - | ADDR 6-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$04 FIFOWP | - | - | - | FIFOWP 4-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$05 FIFORP | - | - | - | FIFORP 4-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$06 EPPTRL | EPPTR 7-0 |
(EPPTR) +------+-------+--------+-------+-------+-------+---------+------+
$07 EPPTRH | EPPTR 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
$08 INTCTRLA | SOF |SUSPEND| RESUME | RESET |STALLED| UNF | OVF | - |
+------+-------+--------+-------+-------+-------+---------+------+
$09 INTCTRLB | - | - |TRNCOMPL| - | - | - | GNDONE |SETUP |
+------+-------+--------+-------+-------+-------+---------+------+
$0A INTFLAGSA | SOF |SUSPEND| RESUME | RESET |STALLED| UNF | OVF | - |
+------+-------+--------+-------+-------+-------+---------+------+
$0B INTFLAGSB | | |TRNCOMPL| | |RMWBUSY| GNDONE |SETUP |
+------+-------+--------+-------+-------+-------+---------+------+
$0C40 USB0_STATUS0 (BASE) USB_STATUS_struct[16]
7 6 5 4 3 2 1 0
+------+-------+--------+-------+-------+-------+---------+------+
$00 OUTCLR | RMWSTATUS 7-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$01 OUTSET | RMWSTATUS 7-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$02 INCLR | RMWSTATUS 7-0 |
+------+-------+--------+-------+-------+-------+---------+------+
$03 INSET | RMWSTATUS 7-0 |
+------+-------+--------+-------+-------+-------+---------+------+
INTCTRLA[AB]
とINTFLAGS[AB]
については、割り込みベクターがUSB0_BUSEVENT
とUSB0_TRNCOMPL
の2本なので、まあなんとなくわかる。
OVF
は Isochronous エンドポイントのオーバーフロー、UNF
は同アンダーフローだろう。STALLED
は "Stalled"(停止中)の意味で、LED制御とは関係ない。
USB0_STATUS[0-15]
は GPIOで使われる "Read-Modify-Write" レジスター構成そのまんまだが、、、これはちょっと用途がわからない。いや、エンドポイントテーブルの SRAMは USBCTRLが常に握ってるからアトミックなのか。STATUS バイトは直接 ST命令で書き換えたりせず、これを使ってビット操作しろってことだ。だから名称がUSB0_STATUS[0-15]
なのね。
USB エンドポイント設定テーブル
USB_EP_TABLE_t
構造体は内部レジスターに直接紐付いていない、エンドポイント構造体を表す。USB_EP_t
とUSB_EP_PAIR_t
とが入れ子になっており、全長は 290 byte(32 + (8 x 2) x 16 + 2
) ある。SRAM内で確保してUSB0_EPPTR
ワードレジスタにその構造体アドレスを渡すはずだ。
この種の実装での 静的 SRAM領域確保は
".initN"
で SP を変更し、C/C++言語の管理範囲外に置くと楽。
USB_EP_TABLE_t
7 6 5 4 3 2 1 0
+------+-------+--------+-------+-------+-------+---------+------+
$0000 FIFO[32] | EPNUM 3-0 | DIR | - | - | - |
+------+-------+--------+-------+-------+-------+---------+------+
USB_EP_PAIR_t[16]
EP_t OUT0 +------+-------+--------+-------+-------+-------+---------+------+
$0020 STATUS | CRC |UNFPVF |TRNCOMPL|EPSETUP|STALLED| - | BUSNAK |TOGGLE|
+------+-------+--------+-------+-------+-------+---------+------+
| | | | | USB_BUFSIZE_ISO 3-0 |
CTRL | TYPE 1-0 |MULTIPKT| AZLP |TCDSBL +-------+---------+------+
| | | | |DOSTALL|BUFSIZE_DEFAULT |
+------+-------+--------+-------+-------+-------+---------+------+
| CNT 7-0 |
CNT[HL] +------+-------+--------+-------+-------+-------+---------+------+
| CNT 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
| DATAPTR 7-0 |
DATAPTR[HL] +------+-------+--------+-------+-------+-------+---------+------+
| DATAPTR 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
| MCNT 7-0 |
MCNT[HL] +------+-------+--------+-------+-------+-------+---------+------+
| MCNT 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
EP_t IN0 +------+-------+--------+-------+-------+-------+---------+------+
$0028 STATUS | CRC |UNFPVF |TRNCOMPL|EPSETUP|STALLED| - | BUSNAK |TOGGLE|
+------+-------+--------+-------+-------+-------+---------+------+
| | | | | USB_BUFSIZE_ISO 3-0 |
CTRL | TYPE 1-0 |MULTIPKT| AZLP |TCDSBL +-------+---------+------+
| | | | |DOSTALL|BUFSIZE_DEFAULT |
+------+-------+--------+-------+-------+-------+---------+------+
| CNT 7-0 |
CNT[HL] +------+-------+--------+-------+-------+-------+---------+------+
| CNT 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
| DATAPTR 7-0 |
DATAPTR[HL] +------+-------+--------+-------+-------+-------+---------+------+
| DATAPTR 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
| MCNT 7-0 |
MCNT[HL] +------+-------+--------+-------+-------+-------+---------+------+
| MCNT 15-8 |
+------+-------+--------+-------+-------+-------+---------+------+
$0030 OUT1 + IN1 |
: |
$0110 OUT15 + IN15 |
+--------+-----+--------+-------+-------+-------+---------+------+
$0120 | FRAMENUM 7-0 |
FRAMENUM[HL]+--------+-----+--------+-------+-------+-------+---------+------+
$0121 |FRAMEERR| - | - | - | - | FRAMENUM 10-8 |
+--------+-----+--------+-------+-------+-------+---------+------+
FIFO
はFIFOWP
とFIFORP
の各 5ビットのインデックスで管理される 32バイトの リングバッファだね。完了エンドポイントの番号と入出力方向を記憶しておいてくれるものだ。その実体がUSB_EP_PAIR_t[16]
にある。FIFO
のビットマスクは詰まるところそのテーブル番地の意味を説明しているだけで、下位 3bitがゼロで埋まってるなら単純なインデックスオフセットだと解釈できる。
普通のDATA
レジスターが見当たらないと思ったら、ここにDATAPTR
ワード定義がある。あれ、っていうことはこれ DMA転送やってくれるの?と思って XMEGA AU手引書 を確認したら、かなりの部分が似ているように見える。なるほど、これはこの時の実装がベースなのかな。だがLow-Speed
切り替えフラグっぽいのやキャリブレーションレジスタがないので互換性があるようでもない・・・そういやブリーフノートにLow-Speed
の言及がないな。え、これはFull-Speed
専用なのか! 時代だなあ・・・
まとめ
- XMEGA AU手引書 が重要な参考になりそう。
- USB 1.1
Low-Speed
が必要なら不適。 - MPLAB X で応用実装サンプルコードが公開されるまでは、USB 実装は手が出ないかも(^^;
けど試験用基板の設計はできる。
関連リンク
リンク先は全て AVR.jp の オンライン PDF。
- XMEGA AU手引書
- AVR4900 : ASF - USB装置階層
- AVR4901 : ASF - USB供給者クラス応用
- AVR4902 : ASF - USB複合装置
- AVR4903 : ASF - USB装置HIDマウス応用
- AVR4904 : ASF - USB装置HIDキーボード応用
- AVR4905 : ASF - USB標準HID装置
- AVR4907 : ASF - USB装置CDC応用
- AVR4920 : ASF - USB装置階層 - 適合と性能係数
- AVR4921 : ASF - USB装置階層 - ASF V1とV2間の違い
- AVR4950 : ASF - USBホスト階層 -- 残りの AVR495x : ASF V2 シリーズは未出/未訳。
Copyright and Contact
Twitter(X): @askn37
BlueSky Social: @multix.jp
GitHub: https://github.com/askn37/
Product: https://askn37.github.io/
Copyright (c) askn (K.Sato) multix.jp
Released under the MIT license
https://opensource.org/licenses/mit-license.php
https://www.oshwa.org/