AVR DU: native USB support - CDC serial, Pluggable USB, and USB CDC bootloader - #652
Open
ws-asahi wants to merge 29 commits into
Open
AVR DU: native USB support - CDC serial, Pluggable USB, and USB CDC bootloader#652ws-asahi wants to merge 29 commits into
ws-asahi wants to merge 29 commits into
Conversation
`!ADC0.CTRLA & 0x01` evaluates as `(!ADC0.CTRLA) & 0x01`, so the early return for a disabled ADC never fired as intended. Parenthesize the mask. The same expression appears twice (analogRead paths for the two ADC generations); the other checks in this file already had the parentheses right.
`(chan + 1) < 3` promotes chan to int, so the documented auto-select value chan = 255 evaluated as 256 < 3 and could never take this path. Compare explicitly instead.
…ost data pointer Three bugs in the unaligned/odd-length paths: - the unaligned leading byte was written without advancing the data pointer, so the rest of the buffer was written shifted by one - writeWords was called without afterwards advancing tAddress/data/ length, so the odd-byte epilogue used stale values - the trailing byte was written to tAddress + length - 2 with a recomputed data offset, landing on the wrong address and corrupting the neighbouring byte while dropping the intended one Rewrite the function to advance state explicitly at each stage. Also return early on a zero-length request (FLASHWRITE_0LENGTH).
avrdu.build.highestcb was B2, and avr64du32 repeated that override. The
32/28-pin DU chip rows have no override of their own, so they inherited
B2 as well. No DU part has a TCB2.
Per DS40002548A (AVR64DU28/32):
- Features: "Two 16-bit Timer/Counter type B (TCB)".
- Product family overview table: the TCB row reads 2 for all four pin
counts (14/20/28/32). Unlike the DD-series, pin count does not add a
third TCB on the DU.
- Table 9-1 peripheral address map: TCB0 (0x0B00) and TCB1 (0x0B10)
only, marked present at every pin count; no TCB2 row.
- Interrupt vector table: TCB0_INT (15) and TCB1_INT (29) only.
- PORTMUX.TCBROUTEA defines bit 0 (TCB0) and bit 1 (TCB1) only.
The ATPACK headers agree - ioavr64du32.h defines TCB0/TCB1 and no
TCB2_INT_vect. Ref_Timers.md already states it in prose: "Some parts
(the smaller pincount DD and all of the future DU and EB parts) do not
have a TCB2." The B2 value looks like a leftover from the avrdd block
this section was modelled on.
No behavioural change today: the DU millis menu sets
avrdu.menu.millis.tcbhighest.build.millistimer=B1 directly rather than
expanding {build.highestcb} (only the avrdd/avrddopti sections expand
it), so nothing currently reads these keys. They are still worth
correcting - if the DU menu is ever made consistent with the DD one,
B2 would emit -DMILLIS_USE_TIMERB2 and every 32/28-pin DU build would
stop at timers.h with "TCB2, selected for millis, does not exist on
this part".
The avr64du32 override and the four existing B1 chip overrides are all
redundant with the family default now; left in place to keep the diff
to the incorrect values.
…SCFG0
The generic avrdu SYSCFG0 template expands {bootloader.resetpinbits}
and {bootloader.eesavebit}, but neither key was defined for the DU
section, and no avrdudefuse5 template existed so fuse 5 (SYSCFG0) was
never written at all. Add the missing resetpinbits indirection, the
eesave menu (parity with avrda/avrdb/avrdd), and the fuse-5 write
templates.
SYSCFG.VUSBCTRL resets to regulator-off, and on the DU the PC3 input buffer sits in the VUSB power domain - so a plain no-bootloader board cannot even read PC3 until VUSB is powered, USB or not. Add a 'VUSB Power Source' menu to the generic avrdu board (internal regulator from VDD, the common case, or external 3.3 V on VUSB) and have init() enable the regulator when USB_VREG_INTERNAL is defined.
The 10-bit compatibility path always did temp >>= 2, assuming a 12-bit native ADC. The DU's ADC is natively 10-bit (SINGLE_8BIT/SINGLE_10BIT only, DS40002548A section 32), so the extra shift squashed readings into an 8-bit range. Shift by (ADC_NATIVE_RESOLUTION - 10) instead, which is 2 on 12-bit parts (unchanged) and 0 on the DU. The same pattern appears in both analogRead paths; both are fixed.
On the DU, the EVGENnSEL fields of PORTx.EVGENCTRLA are 3 bits wide and bits 3/7 read as zero (DS40002548A 18.5.10), so the trick of using them as allocation flags does not work - automatic channel selection (chan = 255) is not possible there. Return 255 (failure) on the DU and document the limitation; explicit channel numbers and the Event library's software tracking work as before.
On the DU, USART1's only pin position is ALT2 (PD6/PD7) - its DEFAULT mux value means 'no pin connection' (DS40002548A, USARTROUTEA). And USART0's DEFAULT (PA0/PA1) collides with the main-clock crystal pins, while PD4/PD5 (ALT3) is the one position present on every DU pincount (PORTA options thin out on the 14-pin part). Define HWSERIAL0_MUX_DEFAULT = ALT3 and HWSERIAL1_MUX_DEFAULT = ALT2 in the DU variants, so Serial0 is PD4/PD5 and Serial1 is PD6/PD7 out of the box with no swap() call - the core's UART_swap.h already honours these overrides. Add NOT_A_PIN placeholder rows for the absent ALT1 positions so the pinswap tables keep their row indexing, and correct the 14-pin LED_BUILTIN comment (Serial1's TxD on PD6 is what collides, not PD4).
The example assumed peripherals the DU does not have (TCD0 was consumed by USB, and the pin/timer lists did not cover the DU mux options). Adjust the timer/pin handling so the example builds and runs on DU parts while behaving as before elsewhere; verified on an AVR64DU32.
Hardware testing showed PC3's digital I/O is powered from VDD and is independent of VUSB and the regulator (the pinout legend is easy to misread). Drop that claim from the menu and init() comments; the menu's purpose stands - anything using the USB peripheral needs VUSB powered. No functional change.
Clean-room USB device stack for the DU's USB peripheral, written from the USB 2.0 specification and DS40002548A: - usb_core / usb_standard / usb_descriptors: device controller driver, standard request handling, descriptor assembly (IAD-capable for composite devices such as USB MIDI) - usb_cdc + USBSerial: CDC-ACM with an Arduino Serial-compatible interface (ring buffers, BREAK/1200bps-touch reset into bootloader) - USBCore_DU + PluggableUSB bridge: the standard Arduino Pluggable USB API on top of the DU stack, so existing libraries (HID, MIDIUSB) work unmodified - Fully interrupt-driven (USB0_BUSEVENT / USB0_TRNCOMPL); usbPoll() is a no-op kept for source compatibility - main.cpp / Arduino.h / HardwareSerial.h: hook the stack into the core when USBCON is defined (USB boards only; no effect elsewhere)
The standard Arduino HID module (keyboard/mouse-class descriptors over Pluggable USB), so HID sketches work out of the box on the DU. Extended HID (NicoHood's HID-Project) also works once NicoHood/HID#472 lands.
Polled (interrupt-free) CDC-ACM bootloader speaking optiboot-compatible STK500v1, written from the USB 2.0 spec and DS40002548A - no Microchip sample code or third-party USB stack. 4 KB boot section including an app-callable SPM stub in the last page (used by the Flash library). Sources, Makefile, per-part build scripts, and design/provenance notes (DESIGN.md, PROVENANCE.md). Entry: 1200 bps touch (magic word + WDT reset), external reset, or a blank application; LED indicator while resident.
usbcdcboot_{16,32,64}du[14][_novreg].hex - one per flash size, with
14-pin LED variants, and _novreg builds for boards feeding external
3.3 V into VUSB (matches the VUSB Power Source menu).
New avrduusb board entry: uploads through the CDC bootloader (1200 bps touch, optiboot-style avrdude), registers both the bootloader (0x1209:0x0001) and application (0x1209:0x0002) VID/PID for Board Info, per-chip bootloader hex selection, and the same menu set as the generic DU board. pid.codes test IDs - to be replaced before release builds. Variants gain the USB identity block (VID/PID/manufacturer/product) and the Serial -> USBSerial redirect, active only when USBCON is defined - the generic avrdu board is unaffected.
Parameterize the boot-section geometry (REQUIRED_BOOTSIZE / BOOTLOADER_END) instead of hard-coding optiboot's 512 bytes, and call the CDC bootloader's SPM stub (last page of the 4 KB boot section) when USING_AVRDU_CDC_BOOTLOADER is defined. Optiboot and SPM-from-app configurations are unchanged; FlashDemo gets the DU addresses.
The DU part pages said USB support did not exist and that writing a USB library was the only thing one could do with a DU; the README still asked whether anyone knew how to make USB work. Update both to describe what the core now provides (CDC Serial, Pluggable USB with HID/MIDI, and the USB CDC bootloader board).
Add the same section-divider comments the other board entries use (bootloading, upload, per-menu banners), so the avrduusb section reads like the rest of the file. Comments only - no functional change.
…y', ADC label - README: the Analog Comparator and ZCD availability lists had no DU entry (1 AC on all DU; no ZCD on the DU). - AboutDxSeries: the DU was still described as 'on the way' with support 'planned'; it is shipping and supported. - Ref_Timers: the DU is no longer a 'future' part. - DU part pages: the spec tables said '12-bit ADC input pins'; the DU ADC is 10-bit (DS40002548A).
- Ref_Timers: the timer availability table had DA/DB, DD, EA and EB columns but no DU. Add it: TCA0/TCB0/TCB1 present, no TCD (the USB peripheral took its place), no TCB2 at any pincount, no TCE/TCF. - Ref_Serial: the per-series USART pin-mapping list skipped the DU. Documented from DS40002548A (USARTROUTEA): USART0 has the DD options minus PORTC; USART1's only pin position is PD6/PD7 and its reset default is no-pin-connection, which is why the core defaults Serial1 there.
…oader The counterpart of Ref_Optiboot for the USB CDC bootloader: what it is, burning it, the entry conditions (1200 bps touch / reset button / empty app), the LED, writing to flash from the app, and how it differs from Optiboot in practice. Linked from the README's documentation index alongside the Optiboot reference.
- The deprecated pincount-macro list had DA/DB/DD/DX/EA entries but not the DU ones, which core_devices.h does define. - Document USBCON under peripheral detection: it is how a sketch or library detects that Serial is the native USB CDC port and the Pluggable USB API is present (defined by the USB board variants, not on the generic DU board).
- CORE_PART_ID: add the DU column (ID_AVR_DU = 0x48; 16/32/64k = 0x48/0x58/0x68, parallel to the DD) and list ID_AVR_DU. - Ref_Analog: the DU has no DAC either (only the comparator's DACREF). - Ref_Digital: document PC3's split power domain - the input buffer is in the VUSB domain and needs VUSB powered, but the output driver runs from VDD (confirmed on hardware: full-VDD output with the regulator off and VUSB floating). - Ref_Serial: on the DU USB boards, Serial wraps the native USB CDC port (USBSerial) instead of USART0; USART0/1 stay available as Serial0/Serial1.
… MUXNEG - Ref_Digital: the earlier wording claimed PC3's input buffer needs VUSB powered; hardware testing shows PC3's digital I/O is powered from VDD and is entirely independent of VUSB and the regulator. The datasheet pinout legend is easy to misread here. Rewritten. - Ref_Analog: state why the DU is absent from the MUXNEG table - its ADC is single-ended only, so there is no MUXNEG at all.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Native USB support for the AVR DU-series.
Based on #651, the new commits start at "AVR DU: native USB stack".
Together, #650 + #651 + this PR supersede draft #637.
What this adds
CDC-ACM
Serial, plus the standard Pluggable USB API so existing libraries work unmodified.usbcdcboot: a polled, clean-room USB CDC bootloader (STK500v1, 4 KB boot section with an app-callable SPM stub),with sources, build scripts, DESIGN/PROVENANCE notes,
and prebuilt hex for every DU part - bit-for-bit reproducible from the included sources with the DxCore toolchain.
and application VID/PID. The generic no-bootloader board is unaffected.
(parameterized boot geometry; optiboot paths unchanged).
(Ref_Timers, Ref_Serial, Ref_Defines, Ref_Digital, Ref_Analog, CORE_PART_ID, README, part pages)
including hardware-verified corrections such as PC3 being a plain VDD-domain GPIO.
Testing (AVR64DU32 Curiosity Nano + Windows 11)
Open questions
pid.codes(0x1209:0x0001/0x0002).These are IDs intended for functional testing, and you are not permitted to use them as-is in commercial products.
Manufacturers must obtain and modify the VID/PID as necessary before manufacturing and shipping the hardware.