Hi everyone,
i've built my own nixie clock with Atmega1284p, programming in Bascom. Everything is working fine. I also have on the same board ESP8266 and using it to get time and making a webserver for the clock (displaying some information).
I tried to upload a *.hex file to ESP8266 a write it to Atmega over serial using Optiboot (optiboot_flash_atmega1284p_UART0_115200_16000000L_B0_BIGBOOT)
As i've found in documentation i use these procedures to write it:
void handleFileUpload() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
String filename = "/" + upload.filename;
if (!filename.startsWith("/")) filename = "/" + filename;
fsUploadFile = LittleFS.open(filename, "w");
uploadStatus = "Uploading file: " + filename;
} else if (upload.status == UPLOAD_FILE_WRITE) {
if (fsUploadFile) fsUploadFile.write(upload.buf, upload.currentSize);
} else if (upload.status == UPLOAD_FILE_END) {
if (fsUploadFile) fsUploadFile.close();
uploadStatus += "File Uploaded: " + upload.filename;
uploadToBootloader(upload.filename); // Spustíme nahrávání do bootloaderu
server.send(200, "text/plain", uploadStatus);
} else {
server.send(500, "text/plain", "File upload failed");
}
}
void uploadToBootloader(String filename) {
File file = LittleFS.open("/" + filename, "r");
if (!file) {
uploadStatus = "Failed to open file for reading";
return;
}
resetATmega();
if (!syncWithBootloader()) {
uploadStatus += "Failed to sync with bootloader";
return;
}
// Enter programming mode
sendByte(0x50); // STK_ENTER_PROGMODE
sendByte(0x20); // CRC_EOP
if (!waitForAck()) {
uploadStatus = "Failed to enter programming mode";
return;
}
uploadStatus += "\nUploading to bootloader...";
int baseAddress = 0;
int segmentAddress = 0;
while (file.available()) {
String line = file.readStringUntil('\n');
if (line[0] != ':') continue;
int byteCount = strtol(line.substring(1, 3).c_str(), nullptr, 16);
int address = strtol(line.substring(3, 7).c_str(), nullptr, 16);
int recordType = strtol(line.substring(7, 9).c_str(), nullptr, 16);
String data = line.substring(9, 9 + byteCount * 2);
int checksum = strtol(line.substring(9 + byteCount * 2, 9 + byteCount * 2 + 2).c_str(), nullptr, 16);
if (!validateChecksum(line)) {
uploadStatus += "\nChecksum validation failed";
return;
}
switch (recordType) {
case 0x00: { // Data record
int fullAddress = (segmentAddress << 4) + address;
if (!setAddress(fullAddress)) {
uploadStatus += "\nFailed to set address at: 0x" + String(fullAddress, HEX);
return;
}
uint8_t page[byteCount];
for (int i = 0; i < byteCount; i++) {
page[i] = strtol(data.substring(i * 2, i * 2 + 2).c_str(), nullptr, 16);
}
if (!writePage(page, byteCount)) {
uploadStatus += "\nFailed to write page at: 0x" + String(fullAddress, HEX);
return;
}
break;
}
case 0x02: { // Extended Segment Address Record
segmentAddress = strtol(data.c_str(), nullptr, 16);
break;
}
case 0x04: { // Extended Linear Address Record
baseAddress = strtol(data.c_str(), nullptr, 16) << 16;
break;
}
case 0x01: { // End Of File record
leaveProgramMode();
uploadStatus += "\nUpload complete";
file.close();
return;
}
}
}
// leaveProgramMode();
// uploadStatus += "\nUpload complete";
// file.close();
}
bool validateChecksum(const String &line) {
int sum = 0;
for (int i = 1; i < line.length() - 1; i += 2) {
sum += strtol(line.substring(i, i + 2).c_str(), nullptr, 16);
}
return (sum & 0xFF) == 0;
}
void resetATmega() {
digitalWrite(ATMEGA_RESET_PIN, LOW);
delay(1000);
digitalWrite(ATMEGA_RESET_PIN, HIGH);
uploadStatus += "\nATMega reset";
}
bool syncWithBootloader() {
// Pošle několik synchronizačních bajtů a čeká na odpověď
uploadStatus += "\nSynchronizing with bootloader...";
for (int i = 0; i < 5; i++) {
sendByte(0x30); // STK_GET_SYNC
sendByte(0x20); // Sync command
if (waitForAck()) {
uploadStatus += "\nSync successful";
return true;
}
delay(100);
}
uploadStatus += "\nSync failed";
return false;
}
bool setAddress(int address) {
//uploadStatus += "\nSetting address to: 0x" + String(address, HEX);
sendByte(0x55); // STK_LOAD_ADDRESS
sendByte(address & 0xFF); // Address LSB
sendByte((address >> 8) & 0xFF); // Address MSB
sendByte(0x20); // CRC_EOP
// Podrobnější kontrola odezvy
if (waitForAck()) {
//uploadStatus += " Addr set to 0x" + String(address, HEX);
return true;
} else {
uploadStatus += "\nFailed to set address to 0x" + String(address, HEX);
return false;
}
}
bool writePage(uint8_t* page, int size) {
sendByte(0x64); // STK_PROG_PAGE
sendByte((size >> 8) & 0xFF); // Size high byte
sendByte(size & 0xFF); // Size low byte
sendByte(0x46); // Flash memory type
for (int i = 0; i < size; i++) {
sendByte(page[i]);
}
sendByte(0x20); // CRC_EOP
return waitForAck();
}
void leaveProgramMode() {
sendByte(0x51); // STK_LEAVE_PROGMODE
sendByte(0x20); // CRC_EOP
waitForAck();
}
void sendByte(uint8_t data) {
Serial.write(data); // Použití Serial.write k odeslání surového bajtu
//uploadStatus += "\nSent: 0x" + String(data, HEX); // Tiskne hexadecimální reprezentaci bajtu pro ladění
}
bool waitForAck() {
unsigned long startTime = millis();
bool gotInSync = false;
while (millis() - startTime < 1000) {
if (Serial.available()) {
uint8_t response = Serial.read();
//uploadStatus += "\nReceived: 0x" + String(response, HEX);
if (response == 0x14) { // STK_INSYNC
gotInSync = true;
} else if (gotInSync && response == 0x10) { // STK_OK
return true;
} else {
gotInSync = false; // Reset if unexpected byte is received
}
}
}
return false;
}
And i can't get it to work.
The output says it's ok and completed, but if i try to read Atmega using USBASP programmer, theres notihing there, only the bootloader.
Output after upload looks likde this.:
Uploading file: /hodiny.hexFile Uploaded: hodiny.hex
ATMega reset
Synchronizing with bootloader...
Sync successful
Uploading to bootloader...
Upload complete
Am I missing something?
Thanks for your answers a advice.
Vojta B.