/* * UARTBootloader.cpp * * Created: 18.08.2021 17:55:47 * Author : Julien */ #define F_CPU 8000000 #include #include #include #include #include #include #include "uart.h" #define BOOT_UART_BAUD_RATE 9600 /* Baudrate */ #define XON 17 /* XON Zeichen */ #define XOFF 19 /* XOFF Zeichen */ #define START_SIGN ':' /* Hex-Datei Zeilenstartzeichen */ /* Zustände des Bootloader-Programms */ #define BOOT_STATE_EXIT 0 #define BOOT_STATE_PARSER 1 /* Zustände des Hex-File-Parsers */ #define PARSER_STATE_START 0 #define PARSER_STATE_SIZE 1 #define PARSER_STATE_ADDRESS 2 #define PARSER_STATE_TYPE 3 #define PARSER_STATE_DATA 4 #define PARSER_STATE_CHECKSUM 5 #define PARSER_STATE_ERROR 6 # define InTriggerOn !(PINB & (1<= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'F') c -= 'A' - 10; else if (c >= 'a' && c <= 'f') c -= 'a' - 10; val = 16 * val + c; } return val; } void write_page(uint32_t page, uint8_t *buf) { uart_puts("P\n\r"); _delay_ms(100); program_page(page, buf); memset(buf, 0xFF, sizeof(SPM_PAGESIZE)); } int main() { DDRB &= ~(1 << PB7);//Trigger PORTB |= (1<> 8); uart_putc(XON); } break; /* Parse Zeilentyp */ case PARSER_STATE_TYPE: hex_buffer[hex_cnt++] = (uint8_t)c; if(hex_cnt == 2) { uart_putc(XOFF); hex_cnt = 0; hex_data_cnt = 0; hex_type = (uint8_t)hex2num(hex_buffer, 2); hex_check += hex_type; switch(hex_type) { case 1: parser_state = PARSER_STATE_CHECKSUM; break; case 0: case 2: case 4: parser_state = PARSER_STATE_DATA; /* Berechnen der neue Flash-Page (abhängig von hex_type) */ /* Liegen die Daten noch in der aktuellen Flash-Page? */ if(!flash_page_flag && (flash_page != (hex_addr - hex_addr % SPM_PAGESIZE)) ) { /* Wenn die Daten nicht in der aktuellen Flash-Page liegen, */ /* wird die aktuelle Page geschrieben und ein Flag */ /* zum berechnen der neuen Page-Startadresse gesetzt */ write_page(flash_page, flash_data); flash_cnt = 0; flash_page_flag = 1; } /* Muss die Page-Startadresse neu berechnet werden? */ if(flash_page_flag) { /* Berechnen der neuen Page-Startadresse */ flash_page = hex_addr - hex_addr % SPM_PAGESIZE; /* Füllen des Flash-Puffers mit dem "alten" Inhalt der Page */ memcpy_PF(flash_data, flash_page, SPM_PAGESIZE); /* Flag setzen um anzuzeigen das eine neue Adresse da ist */ flash_page_flag = 0; } break; default: parser_state = PARSER_STATE_DATA; break; } uart_putc(XON); } break; /* Parse Flash-Daten */ case PARSER_STATE_DATA: hex_buffer[hex_cnt++] = (uint8_t)c; switch(hex_type) { case 0: /* Record Typ 00 - Data Record auswerten */ if(hex_cnt == 2) { uart_putc(XOFF); uart_putc('.'); hex_cnt = 0; flash_data[flash_cnt] = (uint8_t)hex2num(hex_buffer, 2); hex_check += flash_data[flash_cnt]; flash_cnt++; hex_data_cnt++; if(hex_data_cnt == hex_size) { parser_state = PARSER_STATE_CHECKSUM; hex_data_cnt=0; hex_cnt = 0; } /* Puffer voll -> schreibe Page */ if(flash_cnt == SPM_PAGESIZE) { write_page(flash_page, flash_data); flash_cnt = 0; flash_page_flag = 1; } uart_putc(XON); } break; case 2: /* Record Typ 02 - Extended Segment Address auswerten */ case 4: /* Record Typ 04 - Extended Linear Address auswerten */ if(hex_cnt == 4) { uart_putc(XOFF); uart_putc('J'); hex_cnt = 0; /* Schreibe angfangene Flash-Page vor Segment-Sprung */ write_page(flash_page, flash_data); flash_cnt = 0; flash_page_flag = 1; /* Berechnen der Offsetadresse */ switch(hex_type) { case 2: hex_addr_offset = ((uint32_t)hex2num(hex_buffer, 4)) << 4; break; case 4: hex_addr_offset = ((uint32_t)hex2num(hex_buffer, 4)) << 16; break; } /* Addieren der empfangenen Werte für die Checksumme */ hex_check += (uint8_t) hex2num(hex_buffer, 2); hex_check += (uint8_t) hex2num(hex_buffer + 2, 2); parser_state = PARSER_STATE_CHECKSUM; hex_data_cnt=0; hex_cnt = 0; } break; default: break; } break; /* Parse Checksumme */ case PARSER_STATE_CHECKSUM: hex_buffer[hex_cnt++] = (uint8_t)c; if(hex_cnt == 2) { uart_putc(XOFF); hex_checksum = (uint8_t)hex2num(hex_buffer, 2); hex_check += hex_checksum; hex_check &= 0x00FF; /* Dateiende -> schreibe Restdaten */ if(hex_type == 1) { write_page(flash_page, flash_data); boot_state = BOOT_STATE_EXIT; } /* Überprüfe Checksumme -> muss '0' sein */ if(hex_check == 0) parser_state = PARSER_STATE_START; else parser_state = PARSER_STATE_ERROR; uart_putc(XON); } break; /* Parserfehler (falsche Checksumme) */ case PARSER_STATE_ERROR: uart_putc('#'); break; default: break; } } /* Programmzustand: UART Kommunikation */ else if(boot_state != BOOT_STATE_PARSER) { switch((uint8_t)c) { case 'p': boot_state = BOOT_STATE_PARSER; uart_puts("Erwarte HEX-Datei\n\r\n\r"); break; case 'q': boot_state = BOOT_STATE_EXIT; uart_puts("Verlasse den Bootloader!\n\r\n\r"); break; default: uart_putc((unsigned char)c); uart_puts("\n\r\n\r"); break; } } } } while(boot_state!=BOOT_STATE_EXIT); uart_puts("Reset AVR!\n\r\n\r"); _delay_ms(1000); /* Interrupt Vektoren wieder gerade biegen */ temp = MCUCR; MCUCR = temp | (1<