File Coverage

blib/lib/Device/Chip/AVR_HVSP.pm
Criterion Covered Total %
statement 293 319 91.8
branch 27 48 56.2
condition 8 21 38.1
subroutine 32 38 84.2
pod 21 21 100.0
total 381 447 85.2


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2014-2022 -- leonerd@leonerd.org.uk
5              
6 3     3   256021 use v5.26;
  3         30  
7 3     3   594 use Object::Pad 0.66;
  3         10800  
  3         14  
8              
9             package Device::Chip::AVR_HVSP 0.06;
10             class Device::Chip::AVR_HVSP
11 1     1   665 :isa(Device::Chip);
  1         18140  
  1         33  
12              
13 3     3   828 use Carp;
  3         6  
  3         178  
14              
15 3     3   17 use Future::AsyncAwait;
  3         7  
  3         16  
16 3     3   660 use Struct::Dumb qw( readonly_struct );
  3         2749  
  3         16  
17              
18 3     3   235 use constant PROTOCOL => "GPIO";
  3         7  
  3         9352  
19              
20             readonly_struct PartInfo => [qw( signature flash_words flash_pagesize eeprom_words eeprom_pagesize has_efuse )];
21             readonly_struct MemoryInfo => [qw( wordsize pagesize words can_write )];
22              
23             =head1 NAME
24              
25             C - high-voltage serial programming for F chips
26              
27             =head1 DESCRIPTION
28              
29             This L subclass allows interaction with an F
30             microcontroller of the F family in high-voltage serial programming
31             (HVSP) mode. It is particularly useful for configuring fuses or working with a
32             chip with the C fuse programmed, because in such cases a regular ISP
33             programmer cannot be used.
34              
35             =head2 CONNECTIONS
36              
37             To use this module you will need to make connections to the pins of the
38             F chip:
39              
40             ATtiny | tiny84 | tiny85
41             -------+--------+-------
42             SDO | 9 | 7
43             SII | 8 | 6
44             SDI | 7 | 5
45             SCI | 2 | 2
46             RESET | 4 | 1
47             Vcc | 1 | 8
48             GND | 14 | 4
49              
50             This module recognises the following kinds of adapter and automatically
51             assigns default pin connections for likely configurations:
52              
53             Bus Pirate | Sparkfun | Seeed |:| ATtiny
54             | cable | cable |:|
55             -----------+----------+----------+-+-------
56             MISO | brown | black |:| SDO
57             CS | red | white |:| SII
58             MOSI | orange | grey |:| SDI
59             CLK | yellow | purple |:| SCI
60             AUX | green | blue |:| HV control
61             +5V | grey | orange |:| Vcc
62             GND | black | brown |:| GND
63              
64             Z<>
65              
66             FTDI |:| ATtiny
67             -----+-+-------
68             D0 |:| SCI
69             D1 |:| SDI
70             D2 |:| SDO
71             D3 |:| SII
72             D4 |:| HV control
73              
74             For other kinds of adapter, use the named parameters to the L method
75             to tell the chip driver which F pin is connected to what GPIO line.
76              
77             The C line from the adapter will need to be able to control a +12V
78             supply to the C pin of the F chip. It should be active-high,
79             and can be achieved by a two-stage NPN-then-PNP transistor arrangement.
80              
81             Additionally, the C pin and the C to C pins of 14-pin devices
82             will need a pull-down to ground of around 100Ohm to 1kOhm.
83              
84             =cut
85              
86             =head1 MOUNT PARAMETERS
87              
88             =head2 sdi, sii, sci, sdo
89              
90             The names of GPIO lines on the adapter that are connected to the HVSP signal
91             pins of the F chip.
92              
93             =head2 hv
94              
95             The name of the GPIO line on the adapter that is connected to the 12V power
96             supply control.
97              
98             =head1 METHODS
99              
100             The following methods documented in an C expression return L
101             instances.
102              
103             =cut
104              
105             my %DEFAULT_PINS = (
106             'Device::Chip::Adapter::BusPirate' => {
107             sdi => "MOSI",
108             sii => "CS",
109             sci => "CLK",
110             sdo => "MISO",
111             hv => "AUX",
112             },
113              
114             'Device::Chip::Adapter::FTDI' => {
115             sdi => "D1",
116             sii => "D3",
117             sci => "D0",
118             sdo => "D2",
119             hv => "D4",
120             },
121              
122             # For unit testing this is convenient
123             'Test::Device::Chip::Adapter' => {
124             map { $_ => $_ } qw( sdi sii sci sdo hv )
125             },
126             );
127              
128             field %_pins;
129              
130 2         6 async method mount ( $adapter, %params )
  2         7  
  2         4  
  2         4  
131 2         7 {
132 2 50       11 if( my $pins = $DEFAULT_PINS{ref $adapter} ) {
133 2         16 %params = ( %$pins, %params );
134             }
135              
136 2         9 foreach my $pin (qw( sdi sii sci sdo hv )) {
137 10 50       22 defined $params{$pin} or croak "Require a pin assignment for '$pin'" ;
138              
139 10         23 $_pins{$pin} = $params{$pin};
140             }
141              
142 2         17 await $self->SUPER::mount( $adapter, %params );
143              
144             await $self->protocol->write_gpios( {
145             $_pins{sdi} => 0,
146             $_pins{sii} => 0,
147 2         945 $_pins{sci} => 0,
148             });
149              
150             # Set input
151 2         18424 await $self->protocol->tris_gpios( [ $_pins{sdo} ] );
152 2     2 1 472 }
153              
154             =head2 start
155              
156             await $chip->start;
157              
158             Powers up the device, reads and checks the signature, ensuring it is a
159             recognised chip.
160              
161             This method leaves the chip powered up with +5V on Vcc and +12V on RESET. Use
162             the C, C or C methods to turn these off if it is
163             not required again immediately.
164              
165             =cut
166              
167             my %PARTS;
168             {
169 1     1 1 71 local $_;
170             while( ) {
171             my ( $name, $data ) = m/^(\S+)\s*=\s*(.*?)\s*$/ or next;
172             $PARTS{$name} = PartInfo( split /\s+/, $data );
173             }
174             }
175              
176 1         7 field $_partname :reader;
177             field $_partinfo;
178             field @_memories;
179              
180 1         3 async method start ()
  1         2  
181 1         5 {
182 1         4 await $self->all_power(1);
183              
184 1         1524 my $sig = uc unpack "H*", await $self->read_signature;
185              
186 1         82 my $partinfo;
187             my $part;
188             ( $partinfo = $PARTS{$_} )->signature eq $sig and $part = $_, last
189 1   66     14 for keys %PARTS;
190              
191 1 50       30 defined $part or die "Unrecognised signature $sig\n";
192              
193 1         3 $_partname = $part;
194 1         2 $_partinfo = $partinfo;
195              
196 1 50       4 @_memories = (
197             # ws ps nw wr
198             signature => MemoryInfo( 8, 3, 3, 0 ),
199             calibration => MemoryInfo( 8, 1, 1, 0 ),
200             lock => MemoryInfo( 8, 1, 1, 1 ),
201             lfuse => MemoryInfo( 8, 1, 1, 1 ),
202             hfuse => MemoryInfo( 8, 1, 1, 1 ),
203             ( $partinfo->has_efuse ?
204             ( efuse => MemoryInfo( 8, 1, 1, 1 ) ) :
205             () ),
206             flash => MemoryInfo( 16, $partinfo->flash_pagesize, $partinfo->flash_words, 1 ),
207             eeprom => MemoryInfo( 8, $partinfo->eeprom_pagesize, $partinfo->eeprom_words, 1 ),
208             );
209              
210 1         79 return $self;
211 1     1 1 4235 }
212              
213             =head2 stop
214              
215             await $chip->stop;
216              
217             Shut down power to the device.
218              
219             =cut
220              
221 0         0 async method stop ()
  0         0  
222 0         0 {
223 0         0 await $self->all_power(0);
224 0     0 1 0 }
225              
226             =head2 power
227              
228             await $chip->power( $on );
229              
230             Controls +5V to the Vcc pin of the F chip.
231              
232             =cut
233              
234 1         2 async method power ( $on )
  1         5  
  1         2  
235 1         3 {
236 1         3 await $self->protocol->power( $on );
237 1     1 1 2 }
238              
239             =head2 hv_power
240              
241             await $chip->hv_power( $on );
242              
243             Controls +12V to the RESET pin of the F chip.
244              
245             =cut
246              
247 1         2 async method hv_power ( $on )
  1         2  
  1         2  
248 1         6 {
249 1         5 await $self->protocol->write_gpios( { $_pins{hv} => $on } );
250 1     1 1 12 }
251              
252             =head2 all_power
253              
254             await $chip->all_power( $on );
255              
256             Controls both +5V and +12V supplies at once. The +12V supply is turned on last
257             but off first, ensuring the correct HVSP-RESET sequence is applied to the
258             chip.
259              
260             =cut
261              
262 1         2 async method all_power ( $on )
  1         2  
  1         2  
263 1         2 {
264             # Allow power to settle before turning on +12V on AUX
265             # Normal serial line overheads should allow enough time here
266              
267 1 50       4 if( $on ) {
268 1         5 await $self->power(1);
269 1         164 await $self->hv_power(1);
270             }
271             else {
272 0         0 await $self->hv_power(0);
273 0         0 await $self->power(0);
274             }
275 1     1 1 3 }
276              
277             =head2 $name = $chip->partname
278              
279             Returns the name of the chip whose signature was detected by the C
280             method.
281              
282             =cut
283              
284             # :reader
285              
286             =head2 $memory = $avr->memory_info( $name )
287              
288             Returns a memory info structure giving details about the named memory for the
289             attached part. The following memory names are recognised:
290              
291             signature calibration lock lfuse hfuse efuse flash eeprom
292              
293             (Note that the F has no C memory).
294              
295             The structure will respond to the following methods:
296              
297             =over 4
298              
299             =item * wordsize
300              
301             Returns number of bits per word. This will be 8 for the byte-oriented
302             memories, but 16 for the main program flash.
303              
304             =item * pagesize
305              
306             Returns the number of words per page; the smallest amount that can be
307             written in one go.
308              
309             =item * words
310              
311             Returns the total number of words that are available.
312              
313             =item * can_write
314              
315             Returns true if the memory type can be written (in general; this does not take
316             into account the lock bits that might futher restrict a particular chip).
317              
318             =back
319              
320             =cut
321              
322 0         0 method memory_info ( $name )
  0         0  
  0         0  
323 0     0 1 0 {
324             $_memories[$_*2] eq $name and return $_memories[$_*2 + 1]
325 0   0     0 for 0 .. $#_memories/2;
326              
327 0         0 die "$_partname does not have a $name memory";
328             }
329              
330             =head2 %memories = $avr->memory_infos
331              
332             Returns a key/value list of all the known device memories.
333              
334             =cut
335              
336 0         0 method memory_infos ()
  0         0  
337 0     0 1 0 {
338 0         0 return @_memories;
339             }
340              
341             =head2 $fuseinfo = $avr->fuseinfo
342              
343             Returns a L instance containing information
344             on the fuses in the attached device type.
345              
346             =cut
347              
348 0         0 method fuseinfo ()
  0         0  
349 0     0 1 0 {
350 0         0 require Device::Chip::AVR_HVSP::FuseInfo;
351 0         0 return Device::Chip::AVR_HVSP::FuseInfo->for_part( $self->partname );
352             }
353              
354 1         2 async method _transfer ( $sdi, $sii )
  1         2  
  1         11  
  1         3  
355 1         6 {
356 1         3 my $SCI = $_pins{sci};
357 1         3 my $SDI = $_pins{sdi};
358 1         3 my $SII = $_pins{sii};
359 1         2 my $SDO = $_pins{sdo};
360              
361 1         2 my $sdo = 0;
362 1         5 my $proto = $self->protocol;
363              
364             # A "byte" transfer consists of 11 clock transitions; idle low. Each bit is
365             # clocked in from SDO on the falling edge of clocks 0 to 7, but clocked out
366             # of SDI and SII on clocks 1 to 8.
367             # We'll therefore toggle the clock 11 times; on each of the first 8 clocks
368             # we raise it, then simultaneously lower it, writing out the next out bits
369             # and reading in the input.
370             # Serial transfer is MSB first in both directions
371             #
372             # We cheat massively here and rely on pipeline ordering of the actual
373             # ->write calls, by writing all 22 of the underlying bit transitions to the
374             # underlying device, then waiting on all 11 reads to come back.
375              
376 1         20 my @f;
377 1         7 foreach my $i ( 0 .. 10 ) {
378 11 100       18355 my $mask = $i < 8 ? (1 << 7-$i) : 0;
379              
380 11         44 push @f, $proto->write_gpios( { $SCI => 1 } );
381              
382 11 100       12891 if( !$mask ) {
383 3         12 push @f, $proto->write_gpios( { $SCI => 0 } );
384 3         3611 next;
385             }
386              
387             # TODO: this used to be
388             # $mode->writeread
389             # on the BusPirate version
390 8         13 push @f,
391             $proto->write_gpios( {
392             $SDI => ( $sdi & $mask ),
393             $SII => ( $sii & $mask ),
394             $SCI => 0
395             } ),
396              
397 8     8   2145 $proto->read_gpios( [ $SDO ] )->on_done( sub ( $v ) {
  8         11  
398 8 100       27 $sdo |= $mask if $v->{$SDO};
399 8         40 });
400             }
401              
402 1         19 await Future->needs_all( @f );
403              
404 1         449 return $sdo;
405 1     1   6245 }
406              
407 99         191 async method _await_SDO_high ()
  99         146  
408 99         533 {
409 99         251 my $SDO = $_pins{sdo};
410              
411 99         344 my $proto = $self->protocol;
412              
413 99         630 my $count = 50;
414 99         168 while(1) {
415 99 50       374 $count-- or die "Timeout waiting for device to ACK";
416              
417 99 50       454 last if ( await $proto->read_gpios( [ $SDO ] ) )->{$SDO};
418             }
419 99     99   304 }
420              
421             # The AVR datasheet on HVSP does not name any of these operations, only
422             # giving them bit patterns. We'll use the names invented by RikusW. See also
423             # https://sites.google.com/site/megau2s/
424              
425             use constant {
426             # SII values
427 3         1137 HVSP_CMD => 0x4C, # Command
428             HVSP_LLA => 0x0C, # Load Lo Address
429             HVSP_LHA => 0x1C, # Load Hi Address
430             HVSP_LLD => 0x2C, # Load Lo Data
431             HVSP_LHD => 0x3C, # Load Hi Data
432             HVSP_WLB => 0x64, # Write Lo Byte = WRL = WFU0
433             HVSP_WHB => 0x74, # Write Hi Byte = WRH = WFU1
434             HVSP_WFU2 => 0x66, # Write Extended Fuse
435             HVSP_RLB => 0x68, # Read Lo Byte
436             HVSP_RHB => 0x78, # Read Hi Byte
437             HVSP_RSIG => 0x68, # Read Signature
438             HVSP_RFU0 => 0x68, # Read Low Fuse
439             HVSP_RFU1 => 0x7A, # Read High Fuse
440             HVSP_RFU2 => 0x6A, # Read Extended Fuse
441             HVSP_REEP => 0x68, # Read EEPROM
442             HVSP_ROSC => 0x78, # Read Oscillator calibration
443             HVSP_RLCK => 0x78, # Read Lock
444             HVSP_PLH => 0x7D, # Page Latch Hi
445             HVSP_PLL => 0x6D, # Page Latch Lo
446             HVSP_ORM => 0x0C, # OR mask for SII to pulse actual read/write operation
447              
448             # HVSP_CMD Commands
449             CMD_CE => 0x80, # Chip Erase
450             CMD_WFUSE => 0x40, # Write Fuse
451             CMD_WLOCK => 0x20, # Write Lock
452             CMD_WFLASH => 0x10, # Write FLASH
453             CMD_WEEP => 0x11, # Write EEPROM
454             CMD_RSIG => 0x08, # Read Signature
455             CMD_RFUSE => 0x04, # Read Fuse
456             CMD_RFLASH => 0x02, # Read FLASH
457             CMD_REEP => 0x03, # Read EEPROM
458             CMD_ROSC => 0x08, # Read Oscillator calibration
459             CMD_RLOCK => 0x04, # Read Lock
460 3     3   27 };
  3         6  
461             # Some synonyms not found in the AVR ctrlstack software
462             use constant {
463 3         5538 HVSP_WLCK => HVSP_WLB, # Write Lock
464             HVSP_WFU0 => HVSP_WLB, # Write Low Fuse
465             HVSP_WFU1 => HVSP_WHB, # Write High Fuse
466 3     3   23 };
  3         6  
467              
468             =head2 chip_erase
469              
470             await $avr->chip_erase;
471              
472             Performs an entire chip erase. This will clear the flash and EEPROM memories,
473             before resetting the lock bits. It does not affect the fuses.
474              
475             =cut
476              
477 1         2 async method chip_erase ()
  1         2  
478 1         3 {
479 1         4 await $self->_transfer( CMD_CE, HVSP_CMD );
480              
481 1         478 await $self->_transfer( 0, HVSP_WLB );
482 1         434 await $self->_transfer( 0, HVSP_WLB|HVSP_ORM );
483              
484 1         429 await $self->_await_SDO_high;
485 1     1 1 4754 }
486              
487             =head2 read_signature
488              
489             $bytes = await $avr->read_signature;
490              
491             Reads the three device signature bytes and returns them in as a single binary
492             string.
493              
494             =cut
495              
496 2         4 async method read_signature ()
  2         4  
497 2         8 {
498 2         8 await $self->_transfer( CMD_RSIG, HVSP_CMD );
499              
500 2         967 my @sig;
501 2         8 foreach my $byte ( 0 .. 2 ) {
502 6         1774 await $self->_transfer( $byte, HVSP_LLA );
503 6         2646 await $self->_transfer( 0, HVSP_RSIG );
504 6         2613 push @sig, await $self->_transfer( 0, HVSP_RSIG|HVSP_ORM );
505             }
506              
507 2         865 return pack "C*", @sig;
508 2     2 1 4135 }
509              
510             =head2 read_calibration
511              
512             $byte = await $avr->read_calibration;
513              
514             Reads the calibration byte.
515              
516             =cut
517              
518 1         2 async method read_calibration ()
  1         2  
519 1         5 {
520 1         3 await $self->_transfer( CMD_ROSC, HVSP_CMD );
521              
522 1         444 await $self->_transfer( 0, HVSP_LLA );
523 1         434 await $self->_transfer( 0, HVSP_ROSC );
524 1         430 my $val = await $self->_transfer( 0, HVSP_ROSC|HVSP_ORM );
525              
526 1         428 return chr $val;
527 1     1 1 3185 }
528              
529             =head2 read_lock
530              
531             $byte = await $avr->read_lock;
532              
533             Reads the lock byte.
534              
535             =cut
536              
537 1         4 async method read_lock ()
  1         3  
538 1         5 {
539 1         4 await $self->_transfer( CMD_RLOCK, HVSP_CMD );
540              
541 1         444 await $self->_transfer( 0, HVSP_RLCK );
542 1         433 my $val = await $self->_transfer( 0, HVSP_RLCK|HVSP_ORM );
543              
544 1         457 return chr( $val & 3 );
545 1     1 1 3149 }
546              
547             =head2 write_lock
548              
549             await $avr->write_lock( $byte );
550              
551             Writes the lock byte.
552              
553             =cut
554              
555 1         2 async method write_lock ( $byte )
  1         2  
  1         3  
556 1         5 {
557 1         4 await $self->_transfer( CMD_WLOCK, HVSP_CMD );
558              
559 1         440 await $self->_transfer( ( ord $byte ) & 3, HVSP_LLD );
560 1         463 await $self->_transfer( 0, HVSP_WLCK );
561 1         425 await $self->_transfer( 0, HVSP_WLCK|HVSP_ORM );
562              
563 1         439 await $self->_await_SDO_high;
564 1     1 1 3166 }
565              
566             =head2 read_fuse_byte
567              
568             $int = await $avr->read_fuse_byte( $fuse );
569              
570             Reads one of the fuse bytes C, C, C, returning an
571             integer.
572              
573             =cut
574              
575             my %SII_FOR_FUSE_READ = (
576             lfuse => HVSP_RFU0,
577             hfuse => HVSP_RFU1,
578             efuse => HVSP_RFU2,
579             );
580              
581 1         2 async method read_fuse_byte ( $fuse )
  1         2  
  1         3  
582 1         5 {
583 1 50       7 my $sii = $SII_FOR_FUSE_READ{$fuse} or croak "Unrecognised fuse type '$fuse'";
584              
585 1 50 33     7 $fuse eq "efuse" and !$_partinfo->has_efuse and
586             croak "This part does not have an 'efuse'";
587              
588 1         3 await $self->_transfer( CMD_RFUSE, HVSP_CMD );
589              
590 1         465 await $self->_transfer( 0, $sii );
591 1         438 return await $self->_transfer( 0, $sii|HVSP_ORM );
592 1     1 1 4110 }
593              
594             =head2 write_fuse_byte
595              
596             await $avr->write_fuse_byte( $fuse, $byte );
597              
598             Writes one of the fuse bytes C, C, C from an integer.
599              
600             =cut
601              
602             my %SII_FOR_FUSE_WRITE = (
603             lfuse => HVSP_WFU0,
604             hfuse => HVSP_WFU1,
605             efuse => HVSP_WFU2,
606             );
607              
608 1         2 async method write_fuse_byte ( $fuse, $byte )
  1         4  
  1         21  
  1         23  
609 1         4 {
610 1 50       10 my $sii = $SII_FOR_FUSE_WRITE{$fuse} or croak "Unrecognised fuse type '$fuse'";
611              
612 1 50 33     6 $fuse eq "efuse" and !$_partinfo->has_efuse and
613             croak "This part does not have an 'efuse'";
614              
615 1         4 await $self->_transfer( CMD_WFUSE, HVSP_CMD );
616              
617 1         445 await $self->_transfer( $byte, HVSP_LLD );
618 1         432 await $self->_transfer( 0, $sii );
619 1         431 await $self->_transfer( 0, $sii|HVSP_ORM );
620              
621 1         425 await $self->_await_SDO_high;
622 1     1 1 3614 }
623              
624             =head2 read_lfuse
625              
626             =head2 read_hfuse
627              
628             =head2 read_efuse
629              
630             $byte = await $avr->read_lfuse;
631              
632             $byte = await $avr->read_hfuse;
633              
634             $byte = await $avr->read_efuse;
635              
636             Convenient shortcuts to reading the low, high and extended fuses directly,
637             returning a byte.
638              
639             =head2 write_lfuse
640              
641             =head2 write_hfuse
642              
643             =head2 write_efuse
644              
645             await $avr->write_lfuse( $byte );
646              
647             await $avr->write_hfuse( $byte );
648              
649             await $avr->write_efuse( $byte );
650              
651             Convenient shortcuts for writing the low, high and extended fuses directly,
652             from a byte.
653              
654             =cut
655              
656 1         3 foreach my $fuse (qw( lfuse hfuse efuse )) {
657 3     3   24 no strict 'refs';
  3         6  
  3         8688  
658 0     0   0 *{"read_$fuse"} = async sub {
659 0         0 return chr await $_[0]->read_fuse_byte( $fuse );
660             };
661 0     0   0 *{"write_$fuse"} = async sub {
662 0         0 await $_[0]->write_fuse_byte( $fuse, ord $_[1] );
663             };
664             }
665              
666             =head2 read_flash
667              
668             $bytes = await $avr->read_flash( %args );
669              
670             Reads a range of the flash memory and returns it as a binary string.
671              
672             Takes the following optional arguments:
673              
674             =over 4
675              
676             =item start => INT
677              
678             =item stop => INT
679              
680             Address range to read. If omitted, reads the entire memory.
681              
682             =item bytes => INT
683              
684             Alternative to C; gives the nubmer of bytes (i.e. not words of flash)
685             to read.
686              
687             =back
688              
689             =cut
690              
691 1         3 async method read_flash ( %opts )
  1         2  
692 1         4 {
693 1 50       38 my $partinfo = $_partinfo or croak "Cannot ->read_flash of an unrecognised part";
694              
695 1   50     13 my $start = $opts{start} // 0;
696             my $stop = $opts{stop} //
697 1 50 33     11 $opts{bytes} ? $start + ( $opts{bytes}/2 ) : $partinfo->flash_words;
698              
699 1         3 my $bytes = "";
700              
701 1         5 await $self->_transfer( CMD_RFLASH, HVSP_CMD );
702 1         447 my $cur_ahi = -1;
703              
704 1         5 foreach my $addr ( $start .. $stop - 1 ) {
705 1         3 my $alo = $addr & 0xff;
706 1         3 my $ahi = $addr >> 8;
707              
708 1         4 await $self->_transfer( $alo, HVSP_LLA );
709              
710 1 50       486 await $self->_transfer( $cur_ahi = $ahi, HVSP_LHA ) if $cur_ahi != $ahi;
711              
712 1         448 await $self->_transfer( 0, HVSP_RLB );
713 1         446 $bytes .= chr await $self->_transfer( 0, HVSP_RLB|HVSP_ORM );
714              
715 1         432 await $self->_transfer( 0, HVSP_RHB );
716 1         425 $bytes .= chr await $self->_transfer( 0, HVSP_RHB|HVSP_ORM );
717             }
718              
719 1         428 return $bytes;
720 1     1 1 622 }
721              
722             =head2 write_flash
723              
724             await $avr->write_flash( $bytes );
725              
726             Writes the flash memory from the binary string.
727              
728             =cut
729              
730 1         2 async method write_flash ( $bytes )
  1         3  
  1         2  
731 1         6 {
732 1 50       9 my $partinfo = $_partinfo or croak "Cannot ->write_flash of an unrecognised part";
733 1         23 my $nbytes_page = $partinfo->flash_pagesize * 2; # words are 2 bytes
734              
735 1 50       19 croak "Cannot write - too large" if length $bytes > $partinfo->flash_words * 2;
736              
737 1         14 await $self->_transfer( CMD_WFLASH, HVSP_CMD );
738              
739 1         943 my @chunks = $bytes =~ m/(.{1,$nbytes_page})/gs;
740 1         4 my $addr = 0;
741              
742 1         3 foreach my $chunk ( @chunks ) {
743 64         111408 my $thisaddr = $addr;
744 64         372 $addr += $partinfo->flash_pagesize;
745              
746 64         745 await $self->_write_flash_page( $chunk, $thisaddr );
747             }
748              
749 1         1794 await $self->_transfer( 0, HVSP_CMD );
750 1     1 1 52916 }
751              
752 64         105 async method _write_flash_page ( $bytes, $baseaddr )
  64         147  
  64         99  
  64         95  
753 64         228 {
754 64         265 foreach my $idx ( 0 .. length($bytes)/2 - 1 ) {
755 1024         419834 my $addr = $baseaddr + $idx;
756 1024         2491 my $byte_lo = substr $bytes, $idx*2, 1;
757 1024         1851 my $byte_hi = substr $bytes, $idx*2 + 1, 1;
758              
759             # Datasheet disagrees with the byte value written in the final
760             # instruction. Datasheet says 6C even though the OR mask would yield
761             # the value 6E. It turns out emperically that either value works fine
762             # so for neatness of following other code patterns, we use 6E here.
763              
764 1024         3274 await $self->_transfer( $addr & 0xff, HVSP_LLA );
765 1024         456222 await $self->_transfer( ord $byte_lo, HVSP_LLD );
766 1024         449178 await $self->_transfer( 0, HVSP_PLL );
767 1024         447897 await $self->_transfer( 0, HVSP_PLL|HVSP_ORM );
768 1024         450809 await $self->_transfer( ord $byte_hi, HVSP_LHD );
769 1024         447072 await $self->_transfer( 0, HVSP_PLH );
770 1024         448694 await $self->_transfer( 0, HVSP_PLH|HVSP_ORM );
771             }
772              
773 64         29396 await $self->_transfer( $baseaddr >> 8, HVSP_LHA );
774 64         27480 await $self->_transfer( 0, HVSP_WLB );
775 64         27467 await $self->_transfer( 0, HVSP_WLB|HVSP_ORM );
776 64         27487 await $self->_await_SDO_high;
777 64     64   137 }
778              
779             =head2 read_eeprom
780              
781             $bytes = await $avr->read_eeprom( %args );
782              
783             Reads a range of the EEPROM memory and returns it as a binary string.
784              
785             Takes the following optional arguments:
786              
787             =over 4
788              
789             =item start => INT
790              
791             =item stop => INT
792              
793             Address range to read. If omitted, reads the entire memory.
794              
795             =item bytes => INT
796              
797             Alternative to C; gives the nubmer of bytes to read.
798              
799             =back
800              
801             =cut
802              
803 1         2 async method read_eeprom ( %opts )
  1         4  
  1         2  
804 1         6 {
805 1 50       8 my $partinfo = $_partinfo or croak "Cannot ->read_eeprom of an unrecognised part";
806              
807 1   50     11 my $start = $opts{start} // 0;
808             my $stop = $opts{stop} //
809 1 50 33     14 $opts{bytes} ? $start + $opts{bytes} : $partinfo->eeprom_words;
810              
811 1         3 my $bytes = "";
812              
813 1         5 await $self->_transfer( CMD_REEP, HVSP_CMD );
814              
815 1         563 my $cur_ahi = -1;
816              
817 1         5 foreach my $addr ( $start .. $stop - 1 ) {
818 1         4 my $alo = $addr & 0xff;
819 1         3 my $ahi = $addr >> 8;
820              
821 1         5 await $self->_transfer( $alo, HVSP_LLA );
822              
823 1 50       459 await $self->_transfer( $cur_ahi = $ahi, HVSP_LHA ) if $cur_ahi != $ahi;
824              
825 1         454 await $self->_transfer( 0, HVSP_REEP );
826 1         438 $bytes .= chr await $self->_transfer( 0, HVSP_REEP|HVSP_ORM );
827             }
828              
829 1         442 return $bytes;
830 1     1 1 26279 }
831              
832             =head2 write_eeprom
833              
834             await $avr->write_eeprom( $bytes );
835              
836             Writes the EEPROM memory from the binary string.
837              
838             =cut
839              
840 1         2 async method write_eeprom ( $bytes )
  1         2  
  1         2  
841 1         4 {
842 1 50       5 my $partinfo = $_partinfo or croak "Cannot ->write_eeprom of an unrecognised part";
843              
844 1 50       12 croak "Cannot write - too large" if length $bytes > $partinfo->eeprom_words;
845              
846 1         14 my $nwords_page = $partinfo->eeprom_pagesize;
847              
848 1         8 await $self->_transfer( CMD_WEEP, HVSP_CMD );
849              
850 1         510 my @chunks = $bytes =~ m/(.{1,$nwords_page})/gs;
851 1         4 my $addr = 0;
852              
853 1         3 foreach my $chunk ( @chunks ) {
854 32         47489 my $thisaddr = $addr;
855 32         73 $addr += $nwords_page;
856              
857 32         80 await $self->_write_eeprom_page( $chunk, $thisaddr )
858             }
859              
860 1         1629 await $self->_transfer( 0, HVSP_CMD );
861 1     1 1 9114 }
862              
863 32         53 async method _write_eeprom_page ( $bytes, $baseaddr )
  32         61  
  32         52  
  32         43  
864 32         104 {
865 32         90 foreach my $idx ( 0 .. length($bytes) - 1 ) {
866 128         42084 my $addr = $baseaddr + $idx;
867 128         296 my $byte = substr $bytes, $idx, 1;
868              
869             # Datasheet disagrees with the byte value written in the final
870             # instruction. Datasheet says 6C even though the OR mask would yield
871             # the value 6E. It turns out emperically that either value works fine
872             # so for neatness of following other code patterns, we use 6E here.
873              
874 128         363 await $self->_transfer( $addr & 0xff, HVSP_LLA );
875 128         59816 await $self->_transfer( $addr >> 8, HVSP_LHA );
876 128         56645 await $self->_transfer( ord $byte, HVSP_LLD );
877 128         57299 await $self->_transfer( 0, HVSP_PLL );
878 128         56298 await $self->_transfer( 0, HVSP_PLL|HVSP_ORM );
879             }
880              
881 32         13857 await $self->_transfer( 0, HVSP_WLB );
882 32         13946 await $self->_transfer( 0, HVSP_WLB|HVSP_ORM );
883 32         13860 await $self->_await_SDO_high;
884 32     32   56 }
885              
886             =head1 SEE ALSO
887              
888             =over 4
889              
890             =item *
891              
892             L -
893             High voltage serial programming for AVR chips with the Bus Pirate.
894              
895             =back
896              
897             =head1 AUTHOR
898              
899             Paul Evans
900              
901             =cut
902              
903             0x55AA;
904              
905             __DATA__