Missed for Previous Commit

This commit is contained in:
simon 2026-06-06 17:17:42 +02:00
parent f89ea3cbe3
commit 35ce1476d8
3 changed files with 92 additions and 51 deletions

View File

@ -20,6 +20,9 @@ const (
otaDistQueryInterval = 500 * time.Millisecond otaDistQueryInterval = 500 * time.Millisecond
otaDistQueryTimeout = 2 * time.Second otaDistQueryTimeout = 2 * time.Second
otaDistEmitMinInterval = 150 * time.Millisecond otaDistEmitMinInterval = 150 * time.Millisecond
// Pace host chunks so the master UART RX ring is not overrun (~20 frames/block).
otaHostChunkPace = 3 * time.Millisecond
otaBlockMaxRetries = 3
) )
const ( const (
@ -189,52 +192,83 @@ func runOTAOnPortUnlocked(sp *serialPort, firmware []byte, onProgress otaProgres
var seq uint32 var seq uint32
for offset := 0; offset < imageSize; { for offset := 0; offset < imageSize; {
bytesInBlock := 0 blockStart := offset
for bytesInBlock < otaFlashBlockSize && offset < imageSize { blockStartSeq := seq
n := otaHostChunkSize
room := otaFlashBlockSize - bytesInBlock
if n > room {
n = room
}
if offset+n > imageSize {
n = imageSize - offset
}
chunk := firmware[offset : offset+n]
if err := writeUartMessage(sp, &pb.UartMessage{ sendBlock := func() (fullBlock bool, err error) {
Type: pb.MessageType_OTA_PAYLOAD, bytesInBlock := 0
Payload: &pb.UartMessage_OtaPayload{ for bytesInBlock < otaFlashBlockSize && offset < imageSize {
OtaPayload: &pb.OtaPayload{Seq: seq, Data: chunk}, n := otaHostChunkSize
}, room := otaFlashBlockSize - bytesInBlock
}); err != nil { if n > room {
notify("error", "", 0, err.Error()) n = room
return err }
} if offset+n > imageSize {
seq++ n = imageSize - offset
offset += n }
bytesInBlock += n chunk := firmware[offset : offset+n]
pct := offset * 100 / imageSize if err := writeUartMessage(sp, &pb.UartMessage{
if pct > 99 { Type: pb.MessageType_OTA_PAYLOAD,
pct = 99 Payload: &pb.UartMessage_OtaPayload{
OtaPayload: &pb.OtaPayload{Seq: seq, Data: chunk},
},
}); err != nil {
return false, err
}
time.Sleep(otaHostChunkPace)
seq++
offset += n
bytesInBlock += n
pct := offset * 100 / imageSize
if pct > 99 {
pct = 99
}
notify("uploading", otaStepMaster, pct,
fmt.Sprintf("Master: %d / %d bytes", offset, imageSize))
} }
notify("uploading", otaStepMaster, pct, fmt.Sprintf("Master: %d / %d bytes", offset, imageSize)) return bytesInBlock == otaFlashBlockSize, nil
} }
if bytesInBlock == otaFlashBlockSize { fullBlock, err := sendBlock()
st, err := waitOtaStatus(sp, otaStBlockAck, otaDefaultTimeout, nil) if err != nil {
if err != nil { notify("error", "", 0, err.Error())
notify("error", "", 0, err.Error()) return err
return err
}
pct := offset * 100 / imageSize
if pct > 99 {
pct = 99
}
notify("uploading", otaStepMaster, pct,
fmt.Sprintf("Master: Block geschrieben (%d bytes)", st.GetBytesWritten()),
OTAProgress{Bytes: st.GetBytesWritten()})
} }
if !fullBlock {
continue
}
var st *pb.OtaStatusPayload
var ackErr error
for attempt := 0; attempt < otaBlockMaxRetries; attempt++ {
if attempt > 0 {
offset = blockStart
seq = blockStartSeq
if _, err := sendBlock(); err != nil {
notify("error", "", 0, err.Error())
return err
}
}
st, ackErr = waitOtaStatus(sp, otaStBlockAck, otaDefaultTimeout, nil)
if ackErr == nil {
break
}
}
if ackErr != nil {
notify("error", "", 0, ackErr.Error())
return ackErr
}
pct := offset * 100 / imageSize
if pct > 99 {
pct = 99
}
notify("uploading", otaStepMaster, pct,
fmt.Sprintf("Master: Block geschrieben (%d bytes)", st.GetBytesWritten()),
OTAProgress{Bytes: st.GetBytesWritten()})
} }
masterPct = 100 masterPct = 100

View File

@ -175,8 +175,18 @@ static void handle_ota_payload(const uint8_t *data, size_t len) {
return; return;
} }
ota_feed_result_t r = ota_feed_result_t r = ota_uart_feed_chunk(req_ptr->seq, req_ptr->data.bytes,
ota_uart_feed(req_ptr->data.bytes, req_ptr->data.size); req_ptr->data.size);
if (r == OTA_FEED_SEQ_GAP) {
send_ota_failed(16);
return;
}
if (r == OTA_FEED_SEQ_DUP) {
if (ota_uart_block_ready_for_reack()) {
send_ota_status(OTA_UART_ST_BLOCK_ACK, 0);
}
return;
}
if (r == OTA_FEED_ERROR) { if (r == OTA_FEED_ERROR) {
send_ota_failed( 13); send_ota_failed( 13);
return; return;
@ -189,15 +199,6 @@ static void handle_ota_payload(const uint8_t *data, size_t len) {
led_ring_show_ota_progress(done, total, OTA_LED_UART_R, OTA_LED_UART_G, led_ring_show_ota_progress(done, total, OTA_LED_UART_R, OTA_LED_UART_G,
OTA_LED_UART_B); OTA_LED_UART_B);
send_ota_status(OTA_UART_ST_BLOCK_ACK, 0); send_ota_status(OTA_UART_ST_BLOCK_ACK, 0);
return;
}
if (r == OTA_FEED_OK) {
uint32_t total = ota_uart_total_size();
if (total > 0) {
led_ring_show_ota_progress(ota_uart_bytes_received(), total,
OTA_LED_UART_R, OTA_LED_UART_G, OTA_LED_UART_B);
}
} }
} }

View File

@ -23,8 +23,14 @@ esp_err_t esp_now_core_ensure_broadcast_peer(void);
esp_err_t esp_now_core_send(const uint8_t *dest_mac, esp_err_t esp_now_core_send(const uint8_t *dest_mac,
const alox_EspNowMessage *msg); const alox_EspNowMessage *msg);
/** Like send but does not wait for esp_now send-done (lower latency). */
esp_err_t esp_now_core_send_fast(const uint8_t *dest_mac,
const alox_EspNowMessage *msg);
esp_err_t esp_now_core_send_wait(const uint8_t *dest_mac, esp_err_t esp_now_core_send_wait(const uint8_t *dest_mac,
const alox_EspNowMessage *msg); const alox_EspNowMessage *msg);
/** OTA payloads: wait for send-done with extra NO_MEM backoff (queue drain). */
esp_err_t esp_now_core_send_reliable(const uint8_t *dest_mac,
const alox_EspNowMessage *msg);
esp_err_t esp_now_core_init_radio(uint8_t channel); esp_err_t esp_now_core_init_radio(uint8_t channel);
void esp_now_core_init_send_done(void); void esp_now_core_init_send_done(void);