Device-AVR-UPDI
view release on metacpan or search on metacpan
lib/Device/AVR/UPDI.pm view on Meta::CPAN
=head2 read_asi_sys_status
$status = await $updi->read_asi_sys_status;
Reads the C<ASI_SYS_STATUS> register.
=cut
async method read_asi_sys_status ()
{
return await $self->ldcs( REG_ASI_SYS_STATUS );
}
=head2 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,
}
=cut
async method read_sib ()
{
my $bytes = await
$self->_op_writeread( SYNC . pack( "C", OP_KEY_READSIB ), 16 );
printf STDERR ">> READSIB -> %v02X\n", $bytes if DEBUG;
my ( $family, $nvm, $ocd, $dbgosc ) = unpack "A7 x A3 A3 x A1", $bytes;
return {
family => $family,
nvm_version => $nvm,
ocd_version => $ocd,
dbg_osc_freq => $dbgosc,
};
}
=head2 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.
=cut
async method read_signature ()
{
# The ATtiny814 datasheet says
# All Atmel microcontrollers have a three-byte signature code which
# identifies the device. This code can be read in both serial and parallel
# mode, also when the device is locked. The three bytes reside in a
# separate address space.
# So far no attempt at reading signature over UPDI from a locked device has
# been successful. :(
return await $self->ld( $_partinfo->baseaddr_sigrow, 3 );
}
=head2 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 );
=cut
async method request_reset ( $reset )
{
await $self->stcs( REG_ASI_RESET_REQ, $reset ? ASI_RESET_REQ_SIGNATURE : 0 );
}
=head2 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:
=over 4
=item 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 C<SYSCFG0> fuse setting.
await $updi->erase_chip( no_reset => 1 );
await $updi->enable_nvmprog;
=back
=cut
async method erase_chip ( :$no_reset = 0 )
{
await $self->key( KEY_CHIPERASE );
die "Failed to set CHIPERASE key\n" unless ASI_KEY_CHIPERASE & await $self->ldcs( REG_ASI_KEY_STATUS );
return if $no_reset;
await $self->request_reset( 1 );
await $self->request_reset( 0 );
my $timeout = 50;
while( --$timeout ) {
last if not ASI_SYS_STATUS_LOCKSTATUS & await $self->ldcs( REG_ASI_SYS_STATUS );
await Future::IO->sleep( 0.05 );
}
die "Failed to unlock chip\n" if !$timeout;
}
=head2 enable_nvmprog
await $updi->enable_nvmprog;
Requests the chip to enter NVM programming mode.
=cut
async method enable_nvmprog ()
{
await $self->key( KEY_NVMPROG );
die "Failed to set NVMPROG key\n" unless ASI_KEY_NVMPROG & await $self->ldcs( REG_ASI_KEY_STATUS );
await $self->request_reset( 1 );
await $self->request_reset( 0 );
my $timeout = 50;
while( --$timeout ) {
last if ASI_SYS_STATUS_NVMPROG & await $self->ldcs( REG_ASI_SYS_STATUS );
await Future::IO->sleep( 0.05 );
( run in 0.503 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )