2025-04-24 2:54 AM
this was my hardware setup manually controlling the boot pin.
what my condition was I am initialized the bootloader receiving the ack 0x79 for that and also erasing the flash correctly i checked it with the cube programmer , but the write operation is not done. every time i checked with the cube programmer nothing is written in new. this was my current condition
this was my code written in arduino framework is attached below,
#include <WiFi.h>
#include <WebServer.h>
#include <LittleFS.h>
#define WIFI_SSID "Hotspot"
#define WIFI_PASSWORD "12341234"
#define UART_PORT Serial2
#define STM32_BAUDRATE 115200
#define STM32_RX 16
#define STM32_TX 17
#define STM32_ACK 0x79
#define STM32_NACK 0x1F
#define STM32_INIT 0x7F
WebServer server(80);
uint8_t packet[300];
uint32_t currentAddress = 0x08000000;
const char* serverIndex = R"rawliteral(
<!DOCTYPE HTML><html>
<head><title>STM32 FOTA</title><meta name="viewport" content="width=device-width, initial-scale=1"></head>
<body><h2>STM32 Firmware Upload</h2>
<form method='POST' action='/update' enctype='multipart/form-data' id='upload_form'>
<input type='file' name='update' accept='.bin'><input type='submit' value='Upload'></form>
<div id='prg'>Progress: 0%</div>
<script>
document.getElementById('upload_form').onsubmit = function(e) {
e.preventDefault();
var form = document.getElementById('upload_form');
var data = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/update', true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
document.getElementById('prg').innerHTML = 'Progress: ' + Math.round(percentComplete) + '%';
}
};
xhr.onload = function() {
alert(xhr.status === 200 ? 'Upload successful' : 'Upload failed');
};
xhr.send(data);
};
</script></body></html>
)rawliteral";
void setup() {
Serial.begin(115200);
UART_PORT.begin(STM32_BAUDRATE, SERIAL_8E1, STM32_RX, STM32_TX);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(300);
Serial.print(".");
}
Serial.println("\nConnected! IP: " + WiFi.localIP().toString());
LittleFS.begin();
server.on("/", HTTP_GET, []() {
server.send(200, "text/html", serverIndex);
});
server.on("/update", HTTP_POST, []() {
server.send(200, "text/plain", "Upload Complete");
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.println("[BOOT] Initializing bootloader...");
currentAddress = 0x08000000;
if (!stm32InitBootloader()) {
Serial.println("[BOOT] Failed to sync with STM32 bootloader");
return;
}
Send_CMD_Erase_Flash();
} else if (upload.status == UPLOAD_FILE_WRITE) {
Serial.printf("[UPLOAD] Chunk received: %d bytes\n", upload.currentSize);
SendBinaryToSTM32(upload.buf, upload.currentSize, currentAddress);
currentAddress += upload.currentSize;
} else if (upload.status == UPLOAD_FILE_END) {
Serial.println("[UPLOAD] Complete. Jumping to application.");
Send_CMD_Jump_To_Application();
}
});
server.begin();
}
void loop() {
server.handleClient();
}
bool waitForAck(uint32_t timeout = 1000) {
unsigned long start = millis();
while (millis() - start < timeout) {
if (UART_PORT.available()) {
uint8_t b = UART_PORT.read();
if (b == STM32_ACK) {
Serial.println("[ACK] Received");
return true;
} else if (b == STM32_NACK) {
Serial.println("[NACK] Received");
return false;
} else {
Serial.printf("[UART] Unknown byte: 0x%02X\n", b);
}
}
}
Serial.println("[TIMEOUT] No ACK/NACK received");
return false;
}
bool stm32InitBootloader() {
UART_PORT.write(STM32_INIT);
UART_PORT.flush();
return waitForAck();
}
void Send_CMD_Erase_Flash() {
Serial.println("[CMD] Sending Erase Flash");
packet[0] = 0x43;
packet[1] = ~packet[0];
UART_PORT.write(packet, 2);
UART_PORT.flush();
if (!waitForAck()) return;
packet[0] = 0xFF;
packet[1] = 0x00;
UART_PORT.write(packet, 2);
UART_PORT.flush();
waitForAck();
}
void Send_CMD_Jump_To_Application() {
Serial.println("[CMD] Jump to application");
packet[0] = 0x21;
packet[1] = ~packet[0];
UART_PORT.write(packet, 2);
UART_PORT.flush();
waitForAck();
}
void SendBinaryToSTM32(uint8_t* data, size_t len, uint32_t address) {
if (!data || len == 0 || len > 256) return;
Serial.printf("[WRITE] Sending %d bytes to 0x%08X\n", len, address);
packet[0] = 0x31;
packet[1] = ~packet[0];
UART_PORT.write(packet, 2);
UART_PORT.flush();
if (!waitForAck()) return;
// Address
uint8_t addr[5];
addr[0] = (address >> 24) & 0xFF;
addr[1] = (address >> 16) & 0xFF;
addr[2] = (address >> 8) & 0xFF;
addr[3] = address & 0xFF;
addr[4] = addr[0] ^ addr[1] ^ addr[2] ^ addr[3];
UART_PORT.write(addr, 5);
UART_PORT.flush();
if (!waitForAck()) return;
uint8_t lenByte = len - 1;
uint8_t checksum = lenByte;
UART_PORT.write(lenByte);
Serial.print("[DATA] ");
for (size_t i = 0; i < len; i++) {
UART_PORT.write(data[i]);
Serial.printf("%02X ", data[i]);
checksum ^= data[i];
}
UART_PORT.write(checksum);
UART_PORT.flush();
Serial.printf("\n[CHK] %02X\n", checksum);
waitForAck();
}
Solved! Go to Solution.
2025-04-24 3:57 AM
You are using a so-called Blue Pill, which uses illegally cloned STM32F103. ST resources are only dedicated to supporting genuine ST products. We are not committed to ensuring that clones/fakes products work properly with the firmware we provide.
We recommend to purchase genuine products from STMicroelectronics and purchase them from known and trusted distributors.
Thank you for your understanding.
Regards
/Peter
2025-04-24 3:57 AM
You are using a so-called Blue Pill, which uses illegally cloned STM32F103. ST resources are only dedicated to supporting genuine ST products. We are not committed to ensuring that clones/fakes products work properly with the firmware we provide.
We recommend to purchase genuine products from STMicroelectronics and purchase them from known and trusted distributors.
Thank you for your understanding.
Regards
/Peter