• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dfu-programmer / dfu-programmer / #1

pending completion
#1

push

travis-ci

GitHub
Merge pull request #72 from dfu-programmer/libdfu

29 of 29 new or added lines in 3 files covered. (100.0%)

576 of 2904 relevant lines covered (19.83%)

7.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.31
/src/commands.c
1
/*
2
 * dfu-programmer
3
 *
4
 * $Id$
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19
 */
20

21
#include <stdio.h>
22
#include <stdint.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <stdbool.h>
26

27
#include "config.h"
28
#include "commands.h"
29
#include "arguments.h"
30
#include "intel_hex.h"
31
#include "stm32.h"
32
#include "atmel.h"
33
#include "util.h"
34

35
#define COMMAND_DEBUG_THRESHOLD 40
36

37
#define DEBUG(...)  dfu_debug( __FILE__, __FUNCTION__, __LINE__, \
38
                               COMMAND_DEBUG_THRESHOLD, __VA_ARGS__ )
39

40
// ________  P R O T O T Y P E S  _______________________________
41
static int32_t execute_validate( dfu_device_t *device,
42
                                 intel_buffer_out_t *bout,
43
                                 uint8_t mem_segment,
44
                                 bool quiet,
45
                                 bool ignore_outside);
46
/* provide an out buffer to validate and whether this is from
47
 * flash or eeprom data sections, also wether you want it quiet
48
 */
49

50
// ________  F U N C T I O N S  _______________________________
51
static void security_check( dfu_device_t *device ) {
1✔
52
    if( ADC_AVR32 == device->type ) {
1✔
53
        // Get security bit state for AVR32.
54
        device->security_bit_state = atmel_getsecure( device );
×
55
        DEBUG( "Security bit check returned %d.\n", device->security_bit_state );
×
56
    } else {
57
        // Security bit not present or not testable.
58
        device->security_bit_state = ATMEL_SECURE_OFF;
1✔
59
    }
60
}
1✔
61

62
static void security_message( dfu_device_t *device ) {
63
    if( device->security_bit_state > ATMEL_SECURE_OFF ) {
×
64
        fprintf( stderr, "The security bit %s set.\n"
×
65
                         "Erase the device to clear temporarily.\n",
66
                         (ATMEL_SECURE_ON == device->security_bit_state) ? "is" : "may be" );
×
67
    }
68
}
69

70
static int32_t execute_erase( dfu_device_t *device,
1✔
71
                              struct programmer_arguments *args ) {
72
    int32_t result = SUCCESS;
1✔
73

74
    if( !(GRP_STM32 & args->device_type) && !args->com_erase_data.force ) {
1✔
75
        if( 0 == atmel_blank_check( device, args->flash_address_bottom,
×
76
                                             args->flash_address_top,
77
                                             args->quiet ) ) {
×
78
            if ( !args->quiet ) {
×
79
                fprintf( stderr, "Chip already blank, to force erase use --force.\n");
×
80
            }
81
            return SUCCESS;
×
82
        }
83
    }
84

85
    DEBUG( "erase 0x%X bytes.\n",
1✔
86
           (args->flash_address_top - args->flash_address_bottom) );
87

88
    if( GRP_STM32 & args->device_type ) {
1✔
89
        result = stm32_erase_flash( device, args->quiet );
×
90
    } else {
91
        result = atmel_erase_flash( device, ATMEL_ERASE_ALL, args->quiet );
1✔
92
    }
93

94
    if( 0 != result ) {
1✔
95
        return result;
×
96
    }
97

98
    if( !(GRP_STM32 & args->device_type) &&
1✔
99
            !args->com_erase_data.suppress_validation ) {
1✔
100
        result = atmel_blank_check( device, args->flash_address_bottom,
1✔
101
                                            args->flash_address_top,
102
                                            args->quiet );
1✔
103
    }
104
    return result;
1✔
105
}
106

107
static int32_t execute_setsecure( dfu_device_t *device,
108
                                  struct programmer_arguments *args ) {
109
    int32_t result;
110

111
    if( ADC_AVR32 != args->device_type ) {
×
112
        DEBUG( "target doesn't support security bit set.\n" );
×
113
        fprintf( stderr,  "Operation not supported on %s\n",
×
114
                args->device_type_string );
×
115
        return ARGUMENT_ERROR;
×
116
    }
117

118
    result = atmel_secure( device );
×
119

120
    if( result < 0 ) {
×
121
        DEBUG( "Error while setting security bit. (%d)\n", result );
×
122
        fprintf( stderr, "Error setting security bit.\n" );
×
123
        return UNSPECIFIED_ERROR;
×
124
    }
125

126
    return SUCCESS;
×
127
}
128

129
// TODO : split this into a new command (no file is needed) - also general
130
// format of this program is that only 1 command is run at a time.. caveat is
131
// that if program sets a section in memory to '\0' and serialize sets it
132
// otherwise, the section will end up '\0' unless a page erase is used.. so may
133
// need to keep this part of the flash command, but specify that serialize data
134
// 'wins' over data from the hex file
135
static int32_t serialize_memory_image( intel_buffer_out_t *bout,
136
                                     struct programmer_arguments *args ) {
137
    uint32_t target_offset = 0;
×
138
    if( args->command == com_user )
×
139
        target_offset = ATMEL_USER_PAGE_OFFSET;
×
140
    else if( args->device_type & GRP_STM32 )
×
141
        target_offset = STM32_FLASH_OFFSET;
×
142

143
    if ( NULL != args->com_flash_data.serial_data ) {
×
144
        int16_t *serial_data = args->com_flash_data.serial_data;
×
145
        uint32_t length = args->com_flash_data.serial_length;
×
146
        uint32_t offset = args->com_flash_data.serial_offset;
×
147
        uint32_t i;
148

149
        for( i=0; i < length; ++i ) {
×
150
            if ( 0 != intel_process_data(bout, serial_data[i],
×
151
                        target_offset, offset + i) ) {
152
                return BUFFER_INIT_ERROR;
×
153
            }
154
        }
155
    }
156
    return SUCCESS;
×
157
}
158

159
static int32_t execute_validate( dfu_device_t *device,
160
                                 intel_buffer_out_t *bout,
161
                                 uint8_t mem_segment,
162
                                 const bool quiet,
163
                                 const bool ignore_outside) {
164
    int32_t retval = UNSPECIFIED_ERROR;
×
165
    int32_t result;             // result of fcn calls
166
    intel_buffer_in_t buin;     // buffer in for storing read mem
167

168
    if( 0 != intel_init_buffer_in(&buin, bout->info.total_size,
×
169
                                            bout->info.page_size ) ) {
170
        DEBUG("ERROR initializing a buffer.\n");
×
171
        retval = BUFFER_INIT_ERROR;
×
172
        goto error;
×
173
    }
174
    buin.info.data_start = bout->info.valid_start;
×
175
    buin.info.data_end = bout->info.valid_end;
×
176

177
    if( device->type & GRP_STM32 ) {
×
178
        result = stm32_read_flash( device, &buin, mem_segment, quiet );
×
179
    } else {
180
        result = atmel_read_flash( device, &buin, mem_segment, quiet );
×
181
    }
182

183
    if( 0 != result ) {
×
184
        DEBUG("ERROR: could not read memory, err %d.\n", result);
×
185
        retval = FLASH_READ_ERROR;
×
186
        goto error;
×
187
    }
188

189
    if( 0 != (result = intel_validate_buffer( &buin, bout, quiet )) ) {
×
190
        if( result < 0 ) {
×
191
            retval = VALIDATION_ERROR_IN_REGION;
×
192
        } else {
193
            if (ignore_outside) {
×
194
                retval = SUCCESS;
×
195
            } else {
196
                retval = VALIDATION_ERROR_OUTSIDE_REGION;
×
197
            }
198
        }
199
        goto error;
×
200
    }
201

202
    retval = SUCCESS;
×
203

204
error:
×
205
    if( !quiet && SUCCESS != retval ) fprintf( stderr, "FAIL\n" );
×
206

207
    if( NULL != buin.data ) {
×
208
        free( buin.data );
×
209
        buin.data = NULL;
×
210
    }
211

212
    return retval;
×
213
}
214

215
static void print_flash_usage( intel_buffer_info_t *info ) {
216
    fprintf( stderr,
×
217
            "0x%X bytes written into 0x%X bytes memory (%.02f%%).\n",
218
            info->data_end - info->data_start + 1,
×
219
            info->valid_end - info->valid_start + 1,
×
220
            ((float) (100 * (info->data_end - info->data_start + 1)) /
×
221
                (float) (info->valid_end - info->valid_start + 1)) ) ;
×
222
}
223

224
static int32_t execute_flash( dfu_device_t *device,
225
                                struct programmer_arguments *args ) {
226
    int32_t  retval = UNSPECIFIED_ERROR;
×
227
    int32_t  result;
228
    uint32_t  i;
229
    intel_buffer_out_t bout;
230
    size_t   memory_size;
231
    size_t   page_size;
232
    enum atmel_memory_unit_enum mem_type = args->com_flash_data.segment;
×
233
    uint32_t target_offset = 0;
×
234

235
    /* assign the correct memory size */
236
    switch ( mem_type ) {
×
237
        case mem_flash:
×
238
            if( args->device_type & GRP_STM32 ) {
×
239
                target_offset = STM32_FLASH_OFFSET;
×
240
            }
241
            memory_size = args->memory_address_top + 1;
×
242
            page_size = args->flash_page_size;
×
243
            break;
×
244
        case mem_eeprom:
×
245
            if( 0 == args->eeprom_memory_size ) {
×
246
                fprintf( stderr, "This device has no eeprom.\n" );
×
247
                return ARGUMENT_ERROR;
×
248
            }
249
            memory_size = args->eeprom_memory_size;
×
250
            page_size = args->eeprom_page_size;
×
251
            break;
×
252
        case mem_user:
×
253
            memory_size = args->flash_page_size;
×
254
            page_size = args->flash_page_size;
×
255
            mem_type = mem_user;
×
256
            target_offset = ATMEL_USER_PAGE_OFFSET;
×
257
            if( args->device_type != ADC_AVR32 ){
×
258
                fprintf(stderr, "Flash User only implemented for ADC_AVR32 devices.\n");
×
259
                retval = ARGUMENT_ERROR;
×
260
                goto error;
×
261
            }
262
            break;
×
263
        default:
×
264
            DEBUG("Unknown memory type %d\n", mem_type);
×
265
            return ARGUMENT_ERROR;
×
266
    }
267

268
    // ----------------- CONVERT HEX FILE TO BINARY -------------------------
269
    if( 0 != intel_init_buffer_out(&bout, memory_size, page_size) ) {
×
270
        DEBUG("ERROR initializing a buffer.\n");
×
271
        retval = BUFFER_INIT_ERROR;
×
272
        goto error;
×
273
    }
274

275
    result = intel_hex_to_buffer( args->com_flash_data.file, &bout,
×
276
            target_offset, args->quiet );
×
277

278
    if ( result < 0 ) {
×
279
        DEBUG( "Something went wrong with creating the memory image.\n" );
×
280
        retval = BUFFER_INIT_ERROR;
×
281
        goto error;
×
282
    } else if ( result > 0 ) {
×
283
        DEBUG( "WARNING: File contains 0x%X bytes outside target memory.\n",
×
284
                result );
285
        if( mem_type == mem_flash ) {
×
286
            DEBUG( "There may be data in the user page (offset %#X).\n",
×
287
                    ATMEL_USER_PAGE_OFFSET );
288
            DEBUG( "Inspect the hex file or try flash-user.\n" );
×
289
        }
290
        if( !args->quiet ) {
×
291
            fprintf( stderr,
×
292
                    "WARNING: 0x%X bytes are outside target memory,\n", result );
293
            fprintf( stderr, " and will not be written.\n" );
×
294
        }
295
    }
296
// TODO : consider accepting a string to flash to the user page as well as a hex
297
// file.. this would be easier than using serialize and could return the address
298
// location of the start of the string (to be used in the program file)
299

300
    if (0 != serialize_memory_image( &bout, args )) {
×
301
        retval = BUFFER_INIT_ERROR;
×
302
        goto error;
×
303
    }
304

305
    if( mem_type == mem_flash ) {
×
306
        bout.info.valid_start = args->flash_address_bottom;
×
307
        bout.info.valid_end = args->flash_address_top;
×
308

309
        // check that there isn't anything overlapping the bootloader
310
        for( i = args->bootloader_bottom; i <= args->bootloader_top; i++) {
×
311
            if( bout.data[i] <= UINT8_MAX ) {
×
312
                if( true == args->suppressBootloader ) {
×
313
                    //If we're ignoring the bootloader, don't write to it
314
                    bout.data[i] = UINT16_MAX;
×
315
                } else {
316
                    fprintf( stderr, "Bootloader and code overlap.\n" );
×
317
                    fprintf( stderr, "Use --suppress-bootloader-mem to ignore\n" );
×
318
                    retval = BUFFER_INIT_ERROR;
×
319
                    goto error;
×
320
                }
321
            }
322
        }
323
    } else if ( mem_type == mem_user ) {
×
324
        // check here about overwriting?
325

326
        if ( bout.info.data_start == UINT32_MAX ) {
×
327
            fprintf( stderr,
×
328
                    "ERROR: No data to write into the user page.\n" );
329
            retval = BUFFER_INIT_ERROR;
×
330
            goto error;
×
331
        } else {
332
            DEBUG("Hex file contains %u bytes to write.\n",
×
333
                    bout.info.data_end - bout.info.data_start + 1 );
334
        }
335

336
        if ( !(args->com_flash_data.force) ) {
×
337
            /* depending on the version of the bootloader, there could be
338
            * configuration values in the last word or last two words of the
339
            * user page.  If these are overwritten the device may not start.
340
            * A warning should be issued before these values can be changed. */
341
            fprintf( stderr,
×
342
                    "ERROR: --force flag is required to write user page.\n" );
343
            fprintf( stderr,
×
344
                    " Last word(s) in user page contain configuration data.\n");
345
            fprintf( stderr,
×
346
                    " The user page is erased whenever any data is written.\n");
347
            fprintf( stderr,
×
348
                    " Without valid config. device always resets in bootloader.\n");
349
            fprintf( stderr,
×
350
                    " Use dump-user to obtain valid configuration words.\n");
351
            retval = ARGUMENT_ERROR;
×
352
            goto error;
×
353
            // TODO : implement so this error only appears when data overlaps the
354
            // bootloader configuration words.  This would require reading the user
355
            // page to add that data to the buffer, and also should include
356
            // checking the bootloader version to make sure the right number of
357
            // words are blocked / written.
358
            //  ----------- the below for loop is not currently in use -----------
359
            for ( i = bout.info.total_size - 8; i < bout.info.total_size; i++ ) {
360
                if ( -1 != bout.data[i] ) {
361
                    fprintf( stderr,
362
                            "ERROR: data overlap with bootloader configuration word(s).\n" );
363
                    DEBUG( "At position %d, value is %d.\n", i, bout.data[i] );
364
                    fprintf( stderr,
365
                            "ERROR: use the --force-config flag to write the data.\n" );
366
                    retval = ARGUMENT_ERROR;
367
                    goto error;
368
                }
369
            }
370
        }
371
    }
372

373
    // ------------------ INITIAL VALIDATE (if required) -------------------
374
    if ( 1 == args->com_flash_data.validate_first ) {
×
375
        if( 0 == ( retval = execute_validate(device, &bout, mem_type, args->quiet,
×
376
                                             args->com_flash_data.ignore_outside)) ) {
377
            goto success;
×
378
        }
379
        // Else, continue to flash
380
    }
381

382
    // ------------------ WRITE PROGRAM DATA -------------------------------
383
    if( mem_type == mem_user ) {
×
384
        result = atmel_user( device, &bout );
×
385
    } else {
386
        if( args->device_type & GRP_STM32 ) {
×
387
            result = stm32_write_flash( device, &bout,
×
388
                    mem_type == mem_eeprom ? true : false,
389
                    args->com_flash_data.force, args->quiet );
×
390
        } else {
391
            result = atmel_flash(device, &bout,
×
392
                    mem_type == mem_eeprom ? true : false,
393
                    args->com_flash_data.force, args->quiet);
×
394
        }
395
    }
396
    if( 0 != result ) {
×
397
        DEBUG( "Error writing %s data. (err %d)\n", "memory", result );
×
398
        retval = FLASH_WRITE_ERROR;
×
399
        goto error;
×
400
    }
401

402
    // ------------------  VALIDATE PROGRAM ------------------------------
403
    if( 0 == args->com_flash_data.suppress_validation ) {
×
404
        if( 0 != ( retval = execute_validate(device, &bout, mem_type, args->quiet,
×
405
                                             args->com_flash_data.ignore_outside)) ) {
406
            fprintf( stderr, "Memory did not validate. Did you erase?\n" );
×
407
            goto error;
×
408
        } else if ( 0 == args->quiet ) {
×
409
            print_flash_usage( &bout.info );
×
410
        }
411
    } else if( 0 == args->quiet ) {
×
412
        print_flash_usage( &bout.info );
×
413
    }
414

415
success:
×
416
    retval = SUCCESS;
×
417

418
error:
×
419
    if( NULL != bout.data ) {
×
420
        free( bout.data );
×
421
        bout.data = NULL;
×
422
    }
423

424
    return retval;
×
425
}
426

427
static int32_t execute_getfuse( dfu_device_t *device,
428
                            struct programmer_arguments *args ) {
429
    atmel_avr32_fuses_t info;
430
    char *message = NULL;
×
431
    int32_t value = 0;
×
432
    int32_t status;
433

434
    /* only ADC_AVR32 seems to support fuse operation */
435
    if( !(ADC_AVR32 & args->device_type) ) {
×
436
        DEBUG( "target doesn't support fuse set operation.\n" );
×
437
        fprintf( stderr, "target doesn't support fuse set operation.\n" );
×
438
        return ARGUMENT_ERROR;
×
439
    }
440

441
    /* Check AVR32 security bit in order to provide a better error message. */
442
    security_check( device );
×
443

444
    if( args->device_type & GRP_STM32 ) {
×
445
        fprintf( stderr, "Operation not supported on %s.\n",
×
446
                args->device_type_string );
×
447
        return ARGUMENT_ERROR;
×
448
    } else {
449
        status = atmel_read_fuses( device, &info );
×
450
    }
451

452
    if( 0 != status ) {
×
453
        DEBUG( "Error reading %s config information.\n",
×
454
               args->device_type_string );
455
        fprintf( stderr, "Error reading %s config information.\n",
×
456
                         args->device_type_string );
×
457
        security_message( device );
×
458
        return status;
×
459
    }
460

461
    switch( args->com_getfuse_data.name ) {
×
462
        case get_lock:
×
463
            value = info.lock;
×
464
            message = "Locked regions";
×
465
            break;
×
466
        case get_epfl:
×
467
            value = info.epfl;
×
468
            message = "External Privileged Fetch Lock";
×
469
            break;
×
470
        case get_bootprot:
×
471
            value = info.bootprot;
×
472
            message = "Bootloader protected area";
×
473
            break;
×
474
        case get_bodlevel:
×
475
            value = info.bodlevel;
×
476
            message = "Brown-out detector trigger level";
×
477
            break;
×
478
        case get_bodhyst:
×
479
            value = info.bodhyst;
×
480
            message = "BOD Hysteresis enable";
×
481
            break;
×
482
        case get_boden:
×
483
            value = info.boden;
×
484
            message = "BOD Enable";
×
485
            break;
×
486
        case get_isp_bod_en:
×
487
            value = info.isp_bod_en;
×
488
            message = "ISP BOD enable";
×
489
            break;
×
490
        case get_isp_io_cond_en:
×
491
            value = info.isp_io_cond_en;
×
492
            message = "ISP IO condition enable";
×
493
            break;
×
494
        case get_isp_force:
×
495
            value = info.isp_force;
×
496
            message = "ISP Force";
×
497
            break;
×
498
    }
499
    fprintf( stdout, "%s%s0x%02x (%d)\n",
×
500
             ((0 == args->quiet) ? message : ""),
×
501
             ((0 == args->quiet) ? ": " : ""),
×
502
             value, value );
503
    return 0;
×
504
}
505

506
static int32_t execute_get( dfu_device_t *device,
507
                            struct programmer_arguments *args ) {
508
    atmel_device_info_t info;
509
    char *message = NULL;
×
510
    int16_t value = 0;
×
511
    int32_t status;
512
    int32_t controller_error = 0;
×
513

514
    /* Check AVR32 security bit in order to provide a better error message. */
515
    security_check( device );
×
516

517
    if( args->device_type & GRP_STM32 ) {
×
518
        fprintf( stderr, "Operation not supported on %s.\n",
×
519
                args->device_type_string );
×
520
        return -1;
×
521
    } else {
522
        status = atmel_read_config( device, &info );
×
523
    }
524

525
    if( 0 != status ) {
×
526
        DEBUG( "Error reading %s config information.\n",
×
527
               args->device_type_string );
528
        fprintf( stderr, "Error reading %s config information.\n",
×
529
                         args->device_type_string );
×
530
        security_message( device );
×
531
        return status;
×
532
    }
533

534
    switch( args->com_get_data.name ) {
×
535
        case get_bootloader:
×
536
            value = info.bootloaderVersion;
×
537
            message = "Bootloader Version";
×
538
            break;
×
539
        case get_ID1:
×
540
            value = info.bootID1;
×
541
            message = "Device boot ID 1";
×
542
            break;
×
543
        case get_ID2:
×
544
            value = info.bootID2;
×
545
            message = "Device boot ID 2";
×
546
            break;
×
547
        case get_BSB:
×
548
            value = info.bsb;
×
549
            message = "Boot Status Byte";
×
550
            if( ADC_8051 != args->device_type ) {
×
551
                controller_error = 1;
×
552
            }
553
            break;
×
554
        case get_SBV:
×
555
            value = info.sbv;
×
556
            message = "Software Boot Vector";
×
557
            if( ADC_8051 != args->device_type ) {
×
558
                controller_error = 1;
×
559
            }
560
            break;
×
561
        case get_SSB:
×
562
            value = info.ssb;
×
563
            message = "Software Security Byte";
×
564
            if( ADC_8051 != args->device_type ) {
×
565
                controller_error = 1;
×
566
            }
567
            break;
×
568
        case get_EB:
×
569
            value = info.eb;
×
570
            message = "Extra Byte";
×
571
            if( ADC_8051 != args->device_type ) {
×
572
                controller_error = 1;
×
573
            }
574
            break;
×
575
        case get_manufacturer:
×
576
            value = info.manufacturerCode;
×
577
            message = "Manufacturer Code";
×
578
            break;
×
579
        case get_family:
×
580
            value = info.familyCode;
×
581
            message = "Family Code";
×
582
            break;
×
583
        case get_product_name:
×
584
            value = info.productName;
×
585
            message = "Product Name";
×
586
            break;
×
587
        case get_product_rev:
×
588
            value = info.productRevision;
×
589
            message = "Product Revision";
×
590
            break;
×
591
        case get_HSB:
×
592
            value = info.hsb;
×
593
            message = "Hardware Security Byte";
×
594
            if( ADC_8051 != args->device_type ) {
×
595
                controller_error = 1;
×
596
            }
597
            break;
×
598
    }
599

600
    if( 0 != controller_error ) {
×
601
        DEBUG( "%s requires 8051 based controller\n", message );
×
602
        fprintf( stderr, "%s requires 8051 based controller\n",
×
603
                         message );
604
        return -1;
×
605
    }
606

607
    if( value < 0 ) {
×
608
        fprintf( stderr, "The requested device info is unavailable.\n" );
×
609
        return -2;
×
610
    }
611

612
    fprintf( stdout, "%s%s0x%02x (%d)\n",
×
613
             ((0 == args->quiet) ? message : ""),
×
614
             ((0 == args->quiet) ? ": " : ""),
×
615
             value, value );
616
    return 0;
×
617
}
618

619
static int32_t execute_dump( dfu_device_t *device,
1✔
620
                             struct programmer_arguments *args ) {
621
    int32_t i = 0;
1✔
622
    int32_t retval = UNSPECIFIED_ERROR;
1✔
623
    int32_t result;             // result of fcn calls
624
    intel_buffer_in_t buin;     // buffer in for storing read mem
625
    enum atmel_memory_unit_enum mem_segment = args->com_read_data.segment;
1✔
626
    size_t mem_size = 0;
1✔
627
    size_t page_size = 0;
1✔
628
    uint32_t target_offset = 0; // address offset on the target device
1✔
629
        // NOTE: target_offset may not be set appropriately for device
630
        // classes other than ADC_AVR32
631

632
    switch( mem_segment ) {
1✔
633
        case mem_flash:
1✔
634
            mem_size = args->memory_address_top + 1;
1✔
635
            page_size = args->flash_page_size;
1✔
636
            if( ADC_AVR32 == args->device_type ) {
1✔
637
                target_offset = 0x80000000;
×
638
            } else if( GRP_STM32 & args->device_type ) {
1✔
639
                target_offset = STM32_FLASH_OFFSET;
×
640
            }
641
            break;
1✔
642
        case mem_eeprom:
×
643
            mem_size = args->eeprom_memory_size;
×
644
            page_size = args->eeprom_page_size;
×
645
            break;
×
646
        case mem_user:
×
647
            mem_size = args->flash_page_size;
×
648
            page_size = args->flash_page_size;
×
649
            target_offset = 0x80800000;
×
650
            break;
×
651
        default:
×
652
            fprintf( stderr, "Dump not currently supported for this memory.\n" );
×
653
            retval = ARGUMENT_ERROR;
×
654
            goto error;
×
655
    }
656

657
    if( 0 != intel_init_buffer_in(&buin, mem_size, page_size) ) {
1✔
658
        DEBUG("ERROR initializing a buffer.\n");
×
659
        retval = BUFFER_INIT_ERROR;
×
660
        goto error;
×
661
    }
662

663
    if( mem_segment == mem_flash ) {
1✔
664
        buin.info.data_start = args->flash_address_bottom;
1✔
665
        buin.info.data_end = args->flash_address_top;
1✔
666
    }
667

668
    if( args->device_type & GRP_STM32 ) {
1✔
669
        result = stm32_read_flash(device, &buin, mem_segment, args->quiet);
×
670
    } else {
671
        /* Check AVR32 security bit in order to provide a better error message */
672
        security_check( device );   // avr32 has no eeprom, but OK
1✔
673
        result = atmel_read_flash(device, &buin, mem_segment, args->quiet);
1✔
674
    }
675

676
    if( 0 != result ) {
1✔
677
        DEBUG("ERROR: could not read memory, err %d.\n", result);
×
678
        security_message( device );
×
679
        retval = FLASH_READ_ERROR;
×
680
        goto error;
×
681
    }
682

683
    // determine first & last page with non-blank data
684
    if( args->com_read_data.force ) {
1✔
685
        buin.info.data_start = 0;
×
686
    } else {
687
        // find first page with data
688
        for( i = buin.info.data_start; i < buin.info.data_end; i++ ) {
4,096✔
689
            if( buin.data[i] != 0xFF ) break;
4,095✔
690
            if( i / buin.info.page_size >
4,095✔
691
                    buin.info.data_start / buin.info.page_size ) {
4,095✔
692
                // i has just jumped to a different page than buin.data_start
693
                buin.info.data_start = i;
31✔
694
            }
695
        }
696
        if( i == buin.info.data_end ) {
1✔
697
            if( !args->quiet )
1✔
698
                fprintf( stderr,
1✔
699
                        "Memory is blank, returning a single blank page.\n"
700
                        "Use --force to return the entire memory regardless.\n");
701
            buin.info.data_start = 0;
1✔
702
            buin.info.data_end = buin.info.page_size - 1;
1✔
703
        } else {        // find last page with data
704
            for( i = buin.info.data_end; i > buin.info.data_start; i-- ) {
×
705
                if( buin.data[i] !=0xFF ) break;
×
706
                if( i / buin.info.page_size <
×
707
                        buin.info.data_end / buin.info.page_size ) {
×
708
                    buin.info.data_end = i;
×
709
                }
710
            }
711
        }
712
    }
713

714
    if( args->com_read_data.bin ) {
1✔
715
        if( !args->quiet )
×
716
            fprintf( stderr, "Dumping 0x%X bytes from address offset 0x%X.\n",
×
717
                    buin.info.data_end + 1, target_offset );
×
718
        for( i = 0; i <= buin.info.data_end; i++ ) {
×
719
            fprintf( stdout, "%c", buin.data[i] );
×
720
        }
721
    } else {
722
        if( !args->quiet )
1✔
723
            fprintf( stderr, "Dumping 0x%X bytes from address offset 0x%X.\n",
1✔
724
                    buin.info.data_end - buin.info.data_start + 1,
1✔
725
                    target_offset + buin.info.data_start );
1✔
726
        intel_hex_from_buffer( &buin,
1✔
727
                args->com_read_data.force, target_offset );
728
    }
729

730
    fflush( stdout );
1✔
731

732
    retval = SUCCESS;
1✔
733

734
error:
1✔
735
    if( NULL != buin.data ) {
1✔
736
        free( buin.data );
1✔
737
        buin.data = NULL;
1✔
738
    }
739

740
    return retval;
1✔
741
}
742

743
static int32_t execute_setfuse( dfu_device_t *device,
744
                                  struct programmer_arguments *args ) {
745
    int32_t value = args->com_setfuse_data.value;
×
746
    int32_t name = args->com_setfuse_data.name;
×
747

748
    /* only ADC_AVR32 seems to support fuse operation */
749
    if( !(ADC_AVR32 & args->device_type) || (GRP_STM32 & args->device_type) ) {
×
750
        fprintf( stderr,  "Operation not supported on %s\n",
×
751
                args->device_type_string );
×
752
        DEBUG( "target doesn't support fuse set operation.\n" );
×
753
        return -1;
×
754
    }
755

756
    /* Check AVR32 security bit in order to provide a better error message. */
757
    security_check( device );
×
758

759
    if( 0 != atmel_set_fuse(device, name, value) ) {
×
760
        DEBUG( "Fuse set failed.\n" );
×
761
        fprintf( stderr, "Fuse set failed.\n" );
×
762
        security_message( device );
×
763
        return -1;
×
764
    }
765

766
    return 0;
×
767
}
768

769
static int32_t execute_configure( dfu_device_t *device,
770
                                  struct programmer_arguments *args ) {
771
    int32_t value = args->com_configure_data.value;
×
772
    int32_t name = args->com_configure_data.name;
×
773

774
    if( ADC_8051 != args->device_type ) {
×
775
        fprintf( stderr, "Operation not supported on %s\n",
×
776
                args->device_type_string );
×
777
        DEBUG( "target doesn't support configure operation.\n" );
×
778
        return -1;
×
779
    }
780

781
    if( (0xff & value) != value ) {
×
782
        DEBUG( "Value to configure must be in range 0-255.\n" );
×
783
        fprintf( stderr, "Value to configure must be in range 0-255.\n" );
×
784
        return -1;
×
785
    }
786

787
    if( 0 != atmel_set_config(device, name, value) )
×
788
    {
789
        DEBUG( "Configuration set failed.\n" );
×
790
        fprintf( stderr, "Configuration set failed.\n" );
×
791
        return -1;
×
792
    }
793

794
    return 0;
×
795
}
796

797
static int32_t execute_launch( dfu_device_t *device,
3✔
798
                                  struct programmer_arguments *args ) {
799
    if( args->device_type & GRP_STM32 ) {
3✔
800
        return stm32_start_app( device, args->quiet );
×
801
    } else if( args->com_launch_config.noreset ) {
3✔
802
        return atmel_start_app_noreset( device );
×
803
    } else {
804
        return atmel_start_app_reset( device );
3✔
805
    }
806
}
807

808
int32_t execute_command( dfu_device_t *device,
5✔
809
                         struct programmer_arguments *args ) {
810
    device->type = args->device_type;
5✔
811
    switch( args->command ) {
5✔
812
        case com_erase:
1✔
813
            return execute_erase( device, args );
1✔
814
        case com_flash:
×
815
            return execute_flash( device, args );
×
816
        case com_eflash:
×
817
            args->com_flash_data.segment = mem_eeprom;
×
818
            args->command = com_launch;
×
819
            return execute_flash( device, args );
×
820
        case com_user:
×
821
            args->com_flash_data.segment = mem_user;
×
822
            args->command = com_launch;
×
823
            return execute_flash( device, args );
×
824
        case com_start_app:
×
825
            args->com_launch_config.noreset = true;
×
826
        case com_reset:
2✔
827
            args->command = com_launch;
2✔
828
        case com_launch:
3✔
829
            return execute_launch( device, args );
3✔
830
        case com_get:
×
831
            return execute_get( device, args );
×
832
        case com_getfuse:
×
833
            return execute_getfuse( device, args );
×
834
        case com_dump:
×
835
            args->command = com_read;
×
836
            args->com_read_data.force = true;
×
837
            args->com_read_data.bin = 1;
×
838
            return execute_dump( device, args );
×
839
        case com_edump:
×
840
            args->com_read_data.segment = mem_eeprom;
×
841
            args->com_read_data.force = true;
×
842
            args->command = com_read;
×
843
            args->com_read_data.bin = 1;
×
844
            return execute_dump( device, args );
×
845
        case com_udump:
×
846
            args->com_read_data.segment = mem_eeprom;
×
847
            args->com_read_data.force = true;
×
848
            args->command = com_read;
×
849
            args->com_read_data.bin = 1;
×
850
            return execute_dump( device, args );
×
851
        case com_read:
1✔
852
            return execute_dump( device, args );
1✔
853
        case com_configure:
×
854
            return execute_configure( device, args );
×
855
        case com_setfuse:
×
856
            return execute_setfuse( device, args );
×
857
        case com_setsecure:
×
858
            return execute_setsecure( device, args );
×
859
        default:
×
860
            fprintf( stderr, "Not supported at this time.\n" );
×
861
    }
862

863
    return ARGUMENT_ERROR;
×
864
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc