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
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
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.
https://www.tindie.com/products/16571/
AUTHOR
Paul Evans <
[email protected]>