1
1
// UPDI_Programmer.c
2
2
// STK500 compatible UPDI programmer firmware for Arduino
3
- // Version 1.2
3
+ // Version 1.4
4
4
5
5
#include <avr/io.h>
6
6
#include <util/delay.h>
57
57
// Buffer sizes
58
58
#define MAX_BUFFER_SIZE 275
59
59
60
+ // Error handling constants
61
+ #define MAX_RETRIES 3
62
+ #define RETRY_DELAY_MS 100
63
+
60
64
// Function prototypes
61
65
void uart_init (void );
62
66
void uart_send_byte (uint8_t data );
@@ -74,6 +78,9 @@ void updi_write_cs(uint8_t address, uint8_t value);
74
78
uint8_t updi_read_cs (uint8_t address );
75
79
void updi_write_data (uint32_t address , uint8_t * data , uint16_t len );
76
80
void updi_read_data (uint32_t address , uint8_t * data , uint16_t len );
81
+ uint8_t updi_write_data_with_retry (uint32_t address , uint8_t * data , uint16_t len );
82
+ uint8_t updi_read_data_with_retry (uint32_t address , uint8_t * data , uint16_t len );
83
+ void log_error (const char * message );
77
84
78
85
// Global variables
79
86
uint8_t rx_buffer [MAX_BUFFER_SIZE ];
@@ -231,7 +238,7 @@ void handle_sync_error(uint8_t attempt) {
231
238
uint16_t backoff_time = (1 << attempt ) * 100 ; // Exponential backoff in milliseconds
232
239
if (backoff_time > 5000 ) backoff_time = 5000 ; // Cap at 5 seconds
233
240
234
- // TODO: Implement error logging or reporting mechanism
241
+ log_error ( "UPDI synchronization failed" );
235
242
236
243
_delay_ms (backoff_time );
237
244
}
@@ -253,7 +260,7 @@ void process_stk500_command(void) {
253
260
254
261
// Receive token
255
262
if (uart_receive_byte () != TOKEN ) {
256
- // Invalid token, discard message
263
+ log_error ( " Invalid STK500 token received" );
257
264
return ;
258
265
}
259
266
@@ -288,6 +295,7 @@ void process_stk500_command(void) {
288
295
if (updi_sync ()) {
289
296
stk500_send_response (STATUS_CMD_OK , NULL , 0 );
290
297
} else {
298
+ log_error ("Failed to enter programming mode" );
291
299
stk500_send_response (STATUS_CMD_FAILED , NULL , 0 );
292
300
}
293
301
break ;
@@ -305,22 +313,31 @@ void process_stk500_command(void) {
305
313
case CMD_READ_FLASH :
306
314
{
307
315
uint16_t num_bytes = (rx_buffer [0 ] << 8 ) | rx_buffer [1 ];
308
- updi_read_data (current_address , tx_buffer , num_bytes );
309
- stk500_send_response (STATUS_CMD_OK , tx_buffer , num_bytes );
310
- current_address += num_bytes ;
316
+ if (updi_read_data_with_retry (current_address , tx_buffer , num_bytes )) {
317
+ stk500_send_response (STATUS_CMD_OK , tx_buffer , num_bytes );
318
+ current_address += num_bytes ;
319
+ } else {
320
+ log_error ("Failed to read flash memory" );
321
+ stk500_send_response (STATUS_CMD_FAILED , NULL , 0 );
322
+ }
311
323
}
312
324
break ;
313
325
314
326
case CMD_WRITE_FLASH :
315
327
{
316
328
uint16_t num_bytes = (rx_buffer [0 ] << 8 ) | rx_buffer [1 ];
317
- updi_write_data (current_address , & rx_buffer [2 ], num_bytes );
318
- stk500_send_response (STATUS_CMD_OK , NULL , 0 );
319
- current_address += num_bytes ;
329
+ if (updi_write_data_with_retry (current_address , & rx_buffer [2 ], num_bytes )) {
330
+ stk500_send_response (STATUS_CMD_OK , NULL , 0 );
331
+ current_address += num_bytes ;
332
+ } else {
333
+ log_error ("Failed to write flash memory" );
334
+ stk500_send_response (STATUS_CMD_FAILED , NULL , 0 );
335
+ }
320
336
}
321
337
break ;
322
338
323
339
default :
340
+ log_error ("Unknown STK500 command received" );
324
341
stk500_send_response (STATUS_CMD_FAILED , NULL , 0 );
325
342
break ;
326
343
}
@@ -387,3 +404,96 @@ void updi_read_data(uint32_t address, uint8_t *data, uint16_t len) {
387
404
data [i ] = updi_receive_byte ();
388
405
}
389
406
}
407
+
408
+ // Write data to UPDI with retry mechanism
409
+ uint8_t updi_write_data_with_retry (uint32_t address , uint8_t * data , uint16_t len ) {
410
+ uint8_t retries = 0 ;
411
+ uint8_t success = 0 ;
412
+
413
+ while (retries < MAX_RETRIES && !success ) {
414
+ updi_write_data (address , data , len );
415
+
416
+ // Verify written data
417
+ uint8_t verify_buffer [len ];
418
+ updi_read_data (address , verify_buffer , len );
419
+
420
+ if (memcmp (data , verify_buffer , len ) == 0 ) {
421
+ success = 1 ;
422
+ } else {
423
+ retries ++ ;
424
+ log_error ("UPDI write verification failed, retrying..." );
425
+ _delay_ms (RETRY_DELAY_MS );
426
+ }
427
+ }
428
+
429
+ return success ;
430
+ }
431
+
432
+ // Read data from UPDI with retry mechanism
433
+ uint8_t updi_read_data_with_retry (uint32_t address , uint8_t * data , uint16_t len ) {
434
+ uint8_t retries = 0 ;
435
+ uint8_t success = 0 ;
436
+
437
+ while (retries < MAX_RETRIES && !success ) {
438
+ updi_read_data (address , data , len );
439
+
440
+ // Verify read data (read twice and compare)
441
+ uint8_t verify_buffer [len ];
442
+ updi_read_data (address , verify_buffer , len );
443
+
444
+ if (memcmp (data , verify_buffer , len ) == 0 ) {
445
+ success = 1 ;
446
+ } else {
447
+ retries ++ ;
448
+ log_error ("UPDI read verification failed, retrying..." );
449
+ _delay_ms (RETRY_DELAY_MS );
450
+ }
451
+ }
452
+
453
+ return success ;
454
+ }
455
+
456
+ // Log error message (placeholder implementation)
457
+ void log_error (const char * message ) {
458
+ // For now, we'll just send it over UART for debugging purposes.
459
+ while (* message ) {
460
+ uart_send_byte (* message ++ );
461
+ }
462
+ uart_send_byte ('\r' );
463
+ uart_send_byte ('\n' );
464
+ }
465
+
466
+ // CRC16 calculation for error checking
467
+ uint16_t calculate_crc16 (uint8_t * data , uint16_t length ) {
468
+ uint16_t crc = 0xFFFF ;
469
+ for (uint16_t i = 0 ; i < length ; i ++ ) {
470
+ crc ^= (uint16_t )data [i ];
471
+ for (uint8_t j = 0 ; j < 8 ; j ++ ) {
472
+ if (crc & 0x0001 ) {
473
+ crc = (crc >> 1 ) ^ 0xA001 ;
474
+ } else {
475
+ crc >>= 1 ;
476
+ }
477
+ }
478
+ }
479
+ return crc ;
480
+ }
481
+
482
+ // Advanced error recovery function
483
+ void perform_error_recovery (void ) {
484
+ log_error ("Performing error recovery..." );
485
+
486
+ // Reset UPDI interface
487
+ updi_send_break ();
488
+
489
+ // Re-synchronize
490
+ if (!updi_sync ()) {
491
+ log_error ("Error recovery failed: unable to re-synchronize UPDI" );
492
+ return ;
493
+ }
494
+
495
+ // Reset device (if applicable)
496
+ // TODO: Implement device-specific reset procedure
497
+
498
+ log_error ("Error recovery complete" );
499
+ }
0 commit comments