NAME
Device::AVR::UPDI
- interact with an AVR microcontroller over UPDI
DESCRIPTION
This module provides a class for interacting with an AVR microcontroller over the UPDI programming and debug interface. This is used by chips in the newer ATmega 0-series, or ATtiny 0-series or 1-series, or AVR DA or AVR DB families.
Hardware Interface
This code expects to find a serial port connected to the UPDI pin of the microcontroller as a shared single-wire interface. Suitable hardware to provide this can be created using a USB-UART adapter, connecting the RX
line directly to the MCU's UPDI
pin, and connecting TX
via a current-limiting resistor of 1kohm.
+------------+ +-------------------+
| RX-|-------------+ | |
| USB-UART | +------|-UPDI |
| TX-|---[ 1k ]---+ | ATmega or ATtiny |
+------------+ +-------------------|
CONSTRUCTORS
new
$updi = Device::AVR::UPDI->new( ... );
Constructs and returns a new Device::AVR::UPDI
instance.
Takes the following named arguments:
- dev => STRING
-
Path to the device node representing the serial port connection.
- fh => IO
-
Alternative to
dev
, provides an IO handle directly. This should be an instance of IO::Termios, or at least, provide the same interface. - part => STRING
-
Name of the AVR chip to interact with. This is used to define parameters like memory size and location of internal peripherals.
Any of the following forms are accepted
part => "ATtiny814" | "attiny814" | "t814" part => "ATmega4809" | "atmega4809" | "m4809" part => "AVR64DA48" | "avr64da48"
- baud => INT
-
Optional. Overrides the baud rate for communications. Defaults to 115200.
Lower numbers may be useful if communication is unreliable, for example over a long cable or with high capacitance or noise.
After construction, the link must be initialised by calling "init_link" before any of the command methods are used.
ACCESSORS
partinfo
$partinfo = $updi->partinfo;
Returns the Part Info structure containing base addresses and other parameters which may be useful for interacting with the chip.
The returned structure provides the following fields
$name = $partinfo->name;
$sig = $partinfo->signature;
$addr = $partinfo->baseaddr_nvmctrl;
$addr = $partinfo->baseaddr_fuse;
$addr = $partinfo->baseaddr_flash;
$addr = $partinfo->baseaddr_eeprom;
$addr = $partinfo->baseaddr_sigrow;
$bytes = $partinfo->pagesize_flash;
$bytes = $partinfo->pagesize_eeprom;
$bytes = $partinfo->size_flash;
$bytes = $partinfo->size_eeprom;
$fusenames = $partinfo->fusenames;
fuseinfo
Returns a data structure containing information about the individual fuse fields defined by this device.
This is parsed directly from a shipped YAML file; see the files in the share/ directory for more details.
METHODS
The following methods documented in an await
expression return Future instances.
init_link
await $updi->init_link;
Initialise the UPDI link for proper communication.
This method must be invoked after the object is constructed, before using any of the other commands.
read_updirev
$rev = await $updi->read_updirev;
Reads the UPDIREV
field of the STATUSA
register.
read_asi_sys_status
$status = await $updi->read_asi_sys_status;
Reads the ASI_SYS_STATUS
register.
read_sib
$sib = await $updi->read_sib;
Reads the System Information Block.
This is returned in a HASH reference, containing four keys:
{
family => "tinyAVR",
nvm_version => "P:0",
ocd_version => "D:0",
dbg_osc_freq => 3,
}
read_signature
$signature = await $updi->read_signature;
Reads the three signature bytes from the Signature Row of the device. This is returned as a plain byte string of length 3.
request_reset
await $updi->request_reset( $reset );
Sets or clears the system reset request. Typically used to issue a system reset by momentarilly toggling the request on and off again:
await $updi->request_reset( 1 );
await $updi->request_reset( 0 );
erase_chip
await $updi->erase_chip;
Requests a full chip erase, waiting until the erase is complete.
After this, the chip will be unlocked.
Takes an optional named argument:
- no_reset => BOOL
-
If true, does not issue a system reset request after loading the key. This allows you to load multiple keys at once before sending the reset, which may be required e.g. to recover from a bad
SYSCFG0
fuse setting.await $updi->erase_chip( no_reset => 1 ); await $updi->enable_nvmprog;
enable_nvmprog
await $updi->enable_nvmprog;
Requests the chip to enter NVM programming mode.
read_flash_page
$data = await $updi->read_flash_page( $addr, $len );
Reads a single flash page and returns the data. $addr
is within the flash address space.
write_flash_page
await $updi->write_flash_page( $addr, $data );
Writes a single flash page into the NVM controller in 16-bit word transfers. $addr
is within the flash address space.
read_eeprom_page
$data = await $updi->read_eeprom_page( $addr, $len );
Reads a single EEPROM page and returns the data. $addr
is within the EEPROM address space.
write_eeprom_page
await $updi->write_eeprom_page( $addr, $data );
Similar to "write_flash_page" but issues a combined erase-and-write command and $addr
is within the EEPROM address space.
write_fuse
await $updi->write_fuse( $idx, $value );
Writes a fuse value. $idx
is the index of the fuse within the FUSES memory segment, from 0 onwards.
read_fuse
$value = await $updi->read_fuse( $idx );
Reads a fuse value. $idx
is the index of the fuse within the FUSES memory segment, from 0 onwards.
SEE ALSO
"AVR UPDI Programming Cable"
An adapter cable to flash firmware onto an AVR microcontroller chip via UPDI, compatible with this module.
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>