Device-AVR-UPDI

 view release on metacpan or  search on metacpan

bin/avr-updi  view on Meta::CPAN

      printf STDERR "\rRead %d (%.2f%%)", $addr, 100 * $addr / $size;
   }
   print STDERR "\n";
   print STDERR "Done\n";

   return $data;
}

sub _generic_write
{
   my ( $type, $data, $pagesize, $size, $baseaddr ) = @_;
   $baseaddr //= 0;

   my $writemethod = "write_${type}_page";
   my $readmethod  = "read_${type}_page";

   die "Too much data to write in $size bytes\n"
      if $size < length $data;

   $size = length $data;

   printf STDERR "Need to write %d bytes to %06X\n", $size, $baseaddr;

   my $addr = 0;
   while( $addr < $size ) {
      my $page = substr $data, $addr, $pagesize;

      $updi->$writemethod( $baseaddr + $addr, $page )->get;

      $addr += length $page;
      printf STDERR "\rWritten %d (%.2f%%)", $addr, 100 * $addr / $size;
   }
   print STDERR "\n";

   # Verify
   $addr = 0;
   while( $addr < $size ) {
      my $page = substr $data, $addr, $pagesize;

      my $readback = $updi->$readmethod( $baseaddr + $addr, length $page )->get;
      if( $readback ne $page ) {
         my $offset = 0;
         $offset++ while substr( $readback, $offset, 1 ) eq substr( $page, $offset, 1 );

         printf STDERR "\n";
         printf STDERR "Read: %v02X\n", $readback;
         printf STDERR "Exp : %v02X\n", $page;
         die sprintf "Verify failed at addr=0x%04X\n", $baseaddr + $addr + $offset;
      }

      $addr += length $page;
      printf STDERR "\rVerified %d (%.2f%%)", $addr, 100 * $addr / $size;
   }
   print STDERR "\n";

   $RESET_REQUIRED++;

   print STDERR "Done\n";
}

sub _print_decoded_fields
{
   my ( $reg, @fields ) = @_;

   while( @fields ) {
      my $name = shift @fields;
      my $mask = shift @fields;
      my $val = $reg & $mask;

      # shift down
      $mask >>= 1, $val >>= 1 while !( $mask & 1 );

      if( $mask > 1 ) {
         printf " %s=%X", $name, $val;
      }
      elsif( $val ) {
         printf " %s", $name;
      }
      else {
         printf " !%s", lc $name;
      }
   }
   print "\n";
}

# Debugging; undocumented
sub run_show_updi_regs
{
   make_updi;

   my @regs = map { $updi->ldcs( $_ )->get } 0 .. 0x0C;

   printf "UPDI.STATUSA        = %02X", $regs[0];
   _print_decoded_fields $regs[0], UPDIREV => 0xF0;
   printf "     STATUSB        = %02X", $regs[1];
   _print_decoded_fields $regs[1], PSIG => 0x0F;
   printf "     CTRLA          = %02X", $regs[2];
   _print_decoded_fields $regs[2], IBDLY => (1<<7), PARD => (1<<5), DTD => (1<<4), RSD => (1<<3), GTVAL => 0x07;
   printf "     CTRLB          = %02X", $regs[3];
   _print_decoded_fields $regs[3], NACKDIS => (1<<4), CCDETDIS => (1<<3), UPDIDIS => (1<<2);

   # [4] to [6] reserved
   #
   printf "     ASI_KEY_STATUS = %02X", $regs[7];
   _print_decoded_fields $regs[7], UROWWRITE => (1<<5), NVMPROG => (1<<4), CHIPERASE => (1<<3);
   printf "     ASI_RESET_REQ  = %02X\n", $regs[8];

   printf "     ASI_CTRLA      = %02X", $regs[9];
   _print_decoded_fields $regs[9], UPDICLKDIV => 0x03;
   printf "     ASI_SYS_CTRLA  = %02X", $regs[10];
   _print_decoded_fields $regs[10], UROWDONE => (1<<1), CLKREQ => (1<<0);
   printf "     ASI_SYS_STATUS = %02X", $regs[11];
   _print_decoded_fields $regs[11], ERASE_FAILED => (1<<6), SYSRST => (1<<5), INSLEEP => (1<<4),
      NVMPROG => (1<<3), UROWPROG => (1<<2), LOCKSTATUS => (1<<0);
   printf "     ASI_CRC_STATUS = %02X", $regs[12];
   _print_decoded_fields $regs[12], CRC_STATUS => 0x07;
}

=head2 reset

Sends a reset request.

   $ avr-updi reset

Note that this command does not need the C<--part> to be specified.

=cut

sub command_reset
   :Command_description("Sends a reset request")
{
   $PART //= "ATtiny814"; # part doesn't matter just for reset
   make_updi;

   print STDERR "Issuing Reset over UPDI\n";
   reset_chip;
}

=head2 read-sib

Reads the System Information Block

   $ avr-updi read-sib

Note that this command does not need the C<--part> to be specified.

=cut

sub command_read_sib
   :Command_description("Reads the System Information Block")
{
   $PART //= "ATtiny814"; # part doesn't matter
   make_updi;

   my $sib = $updi->read_sib->get;

   foreach my $key ( sort keys %$sib ) {
      printf "%12s: %s\n", uc $key, $sib->{$key};
   }
}

=head2 read-signature

Reads the 3-byte signature from the chip and prints it.

   $ avr-updi read-signature -p t814

=cut

sub command_read_signature
   :Command_description("Reads the 3-byte signature from the chip and prints it")
{
   make_updi;

   unless( $updi->read_asi_sys_status->get & (1<<3) ) {
      $updi->enable_nvmprog->get;



( run in 1.432 second using v1.01-cache-2.11-cpan-39bf76dae61 )