Skip to content

Commit

Permalink
Fix flash write size using stub on esp8266
Browse files Browse the repository at this point in the history
  • Loading branch information
loucass003 committed Oct 8, 2023
1 parent e4fd25e commit 937ed90
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 48 deletions.
12 changes: 10 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@ dependencies {
testImplementation("com.fazecast:jSerialComm:2.10.2")
}

tasks.named<Test>("test") {
useJUnitPlatform()
gradle.taskGraph.whenReady {
tasks.named<Test>("test") {
onlyIf {
// Run tests only if the 'test' task is invoked directly
this@whenReady.hasTask(":test") && !this@whenReady.hasTask(":build") && !this@whenReady.hasTask(":assemble")
}
useJUnitPlatform()
}
}



tasks {
compileKotlin {
kotlinOptions.jvmTarget = "17"
Expand Down
31 changes: 24 additions & 7 deletions src/main/kotlin/Flasher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import dev.llelievr.espflashkotlin.targets.Esp32c3Target
import dev.llelievr.espflashkotlin.targets.Esp8266Target
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*
import java.util.logging.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.math.floor
import kotlin.math.max

Expand Down Expand Up @@ -153,6 +156,8 @@ class Flasher(
if (binsToFlash.isEmpty())
error("No binary added to the flasher")

// TODO check files fit in flash

binsToFlash.sortedBy { it.first }.forEach { pair ->
writeBinToFlash(pair.second, pair.first);
}
Expand Down Expand Up @@ -258,17 +263,29 @@ class Flasher(
return true;
}

fun padTo(data: ByteArray, alignment: Int, padCharacter: Byte = 0xFF.toByte()): ByteArray {
var paddedData = data.copyOf()
val padMod = data.size % alignment
if (padMod != 0) {
val padding = ByteArray(alignment - padMod) { padCharacter }
paddedData += padding
}
return paddedData
}

private fun writeBinToFlash(bin: ByteArray, offset: Int) {
val flasherTarget = currentTarget ?: error("target not set")
val writeSize = flasherTarget.getFlashWriteSize()

val binMd5 = bytesToMd5(bin);

flashBegin(bin.size, offset)
val image = padTo(bin, 4);
val binMd5 = bytesToMd5(image);

flashBegin(image.size, offset)

val chunks = bin.asSequence().chunked(writeSize)
val chunks = image.asSequence().chunked(writeSize)
chunks.forEachIndexed { index, chunk ->
progressListeners.forEach { it.progress((index * writeSize).toFloat() / bin.size) }
progressListeners.forEach { it.progress((index * writeSize).toFloat() / image.size) }

var block = chunk.toByteArray();

Expand Down Expand Up @@ -297,18 +314,18 @@ class Flasher(

val command = FlashMD5(
offset,
bin.size,
image.size,
)

if (command.isPacketSupported(flasherTarget)) {
val res = writeWait(
command,
timeoutPerMb(bin.size, MD5_TIMEOUT_MILLIS_PER_MB)
timeoutPerMb(image.size, MD5_TIMEOUT_MILLIS_PER_MB)
)
val md5Data = res.optionalData() ?: error("could not read md5 from response");
val md5Str = when (md5Data.size) {
32 -> md5Data.toString().lowercase(Locale.getDefault())
16 -> md5Data.toHexString()
8 -> TODO("Unimplemented, cant test it")
else -> error("Invalid md5 format")
}

Expand Down
53 changes: 29 additions & 24 deletions src/main/kotlin/Stub.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,33 @@ data class FlasherStubData(

data class FlasherStub(val entry: Int, val text: ByteArray, val text_start: Int, val data: ByteArray, val data_start: Int)

private fun fromData(data: FlasherStubData): FlasherStub {
return FlasherStub(
data.entry,
Base64.getDecoder().decode(data.text),
data.text_start,
Base64.getDecoder().decode(data.data),
data.data_start
)
}

fun loadStubFromResource(resource: String): FlasherStub? {
val stubJson = {}.javaClass.getResource(resource)?.readText() ?: return null;
val decodedStub = Json.decodeFromString<FlasherStubData>(stubJson)

return fromData(decodedStub)
}

fun loadStubFromFile(resource: File): FlasherStub? {
if (!resource.exists())
return null;
val stubJson = resource.readText()
val decodedStub = Json.decodeFromString<FlasherStubData>(stubJson);

return fromData(decodedStub);
class StubLoader {
companion object {
private fun fromData(data: FlasherStubData): FlasherStub {
return FlasherStub(
data.entry,
Base64.getDecoder().decode(data.text),
data.text_start,
Base64.getDecoder().decode(data.data),
data.data_start
)
}


fun loadStubFromResource(resource: String): FlasherStub? {
val stubJson = this::class.java.getResource(resource)?.readText() ?: return null;
val decodedStub = Json.decodeFromString<FlasherStubData>(stubJson)

return fromData(decodedStub)
}

fun loadStubFromFile(resource: File): FlasherStub? {
if (!resource.exists())
return null;
val stubJson = resource.readText()
val decodedStub = Json.decodeFromString<FlasherStubData>(stubJson);

return fromData(decodedStub);
}
}
}
6 changes: 4 additions & 2 deletions src/main/kotlin/targets/ESP32Target.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ package dev.llelievr.espflashkotlin.targets
import dev.llelievr.espflashkotlin.Command
import dev.llelievr.espflashkotlin.FlasherStub
import dev.llelievr.espflashkotlin.FlasherTarget
import dev.llelievr.espflashkotlin.loadStubFromResource
import dev.llelievr.espflashkotlin.StubLoader
import kotlin.experimental.or



open class ESP32Target : FlasherTarget {
internal var stub: FlasherStub? = null;

override fun init() {
stub = loadStubFromResource("/stubs/stub_flasher_32.json")
stub = StubLoader.loadStubFromResource("/stubs/stub_flasher_32.json")
}

override fun getEraseSize(offset: Int, size: Int): Int {
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/targets/Esp32c3Target.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package dev.llelievr.espflashkotlin.targets

import dev.llelievr.espflashkotlin.loadStubFromResource
import dev.llelievr.espflashkotlin.StubLoader


class Esp32c3Target : ESP32Target() {
override fun init() {
stub = loadStubFromResource("/stubs/stub_flasher_32c3.json")
stub = StubLoader.loadStubFromResource("/stubs/stub_flasher_32c3.json")
}
}
21 changes: 17 additions & 4 deletions src/main/kotlin/targets/Esp8266Target.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,26 @@ package dev.llelievr.espflashkotlin.targets
import dev.llelievr.espflashkotlin.Command
import dev.llelievr.espflashkotlin.FlasherStub
import dev.llelievr.espflashkotlin.FlasherTarget
import dev.llelievr.espflashkotlin.loadStubFromResource
import dev.llelievr.espflashkotlin.StubLoader
import kotlin.experimental.or
import kotlin.math.min

class Esp8266Target : FlasherTarget {

private var stub: FlasherStub? = null;

override fun getEraseSize(offset: Int, size: Int): Int {
if (stub !== null) {
// stub doesn't have same size bug as ROM loader
return size;
}

//Calculate an erase size given a specific size in bytes.
//Provides a workaround for the bootloader erase bug.
val sectorCount = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE
val startSector = offset / FLASH_SECTOR_SIZE

val headSectors = kotlin.math.min(
val headSectors = min(
FLASH_SECTORS_PER_BLOCK - (startSector % FLASH_SECTORS_PER_BLOCK),
sectorCount
)
Expand All @@ -27,11 +35,15 @@ class Esp8266Target : FlasherTarget {
}

override fun getFlashWriteSize(): Int {
return FLASH_WRITE_SIZE;
return if (stub != null) {
FLASH_WRITE_SIZE_STUB
} else {
FLASH_WRITE_SIZE
}
}

override fun init() {
stub = loadStubFromResource("/stubs/stub_flasher_8266.json")
stub = StubLoader.loadStubFromResource("/stubs/stub_flasher_8266.json")
}

override fun stub(): FlasherStub? {
Expand Down Expand Up @@ -64,6 +76,7 @@ class Esp8266Target : FlasherTarget {
companion object {
private const val FLASH_SECTOR_SIZE = 0x1000;
private const val FLASH_WRITE_SIZE = 0x400;
private const val FLASH_WRITE_SIZE_STUB = 0x4000;
private const val FLASH_BLOCK_SIZE = 0x100;
private const val FLASH_SECTORS_PER_BLOCK = FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE;
private const val UPLOAD_SPEED = 921600;
Expand Down
16 changes: 9 additions & 7 deletions src/test/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import com.fazecast.jSerialComm.SerialPort
import dev.llelievr.espflashkotlin.Flasher
import dev.llelievr.espflashkotlin.FlasherSerialInterface
import dev.llelievr.espflashkotlin.FlashingProgressListener
import org.junit.jupiter.api.Test
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.IOException
Expand All @@ -13,17 +13,19 @@ class LibraryTest: FlasherSerialInterface, FlashingProgressListener {

private var port: SerialPort? = null

@Test()
fun flash() {
val ports = SerialPort.getCommPorts()
val firstPort = ports.first() ?: error("unable to find port")

Flasher(this, false)
Flasher(this, true)
.addProgressListener(this)
.addBin(File("C:\\Users\\louca\\Documents\\SlimeVR\\SlimeVR-Tracker-ESP\\.pio\\build\\esp32c3\\bootloader.bin").readBytes(), 0x0000)
.addBin(File("C:\\Users\\louca\\Documents\\SlimeVR\\SlimeVR-Tracker-ESP\\.pio\\build\\esp32c3\\partitions.bin").readBytes(), 0x8000)
.addBin(File("C:\\Users\\louca\\.platformio\\packages\\[email protected]\\tools\\partitions\\boot_app0.bin").readBytes(), 0xe000)
.addBin(File("C:\\Users\\louca\\Documents\\SlimeVR\\SlimeVR-Tracker-ESP\\.pio\\build\\esp32c3\\firmware.bin").readBytes(), 0x10000)
// .addBin(downloadFirmware("http://127.0.0.1:9099/slimevr-firmware-builds/7e3c6081-0adb-4b12-9382-69c6174dcbd0/firmware-part-0.bin") ?: error("unable to download"), 0)
// .addBin(File("C:\\Users\\louca\\Documents\\SlimeVR\\SlimeVR-Tracker-ESP\\.pio\\build\\esp32c3\\bootloader.bin").readBytes(), 0x0000)
// .addBin(File("C:\\Users\\louca\\Documents\\SlimeVR\\SlimeVR-Tracker-ESP\\.pio\\build\\esp32c3\\partitions.bin").readBytes(), 0x8000)
// .addBin(File("C:\\Users\\louca\\.platformio\\packages\\[email protected]\\tools\\partitions\\boot_app0.bin").readBytes(), 0xe000)
// .addBin(File("C:\\Users\\louca\\Documents\\SlimeVR\\SlimeVR-Tracker-ESP\\.pio\\build\\esp32c3\\firmware.bin").readBytes(), 0x10000)
// .addBin(downloadFirmware("http://localhost:9099/slimevr-firmware-builds/f3f9aa01-0088-40d0-882f-3b865d94e4bb/firmware-part-0.bin") ?: error("unable to download"), 0)
.addBin(File("C:\\Users\\louca\\Downloads\\firmware-part-0 (2).bin").readBytes(), 0)
.flash(firstPort)
}

Expand Down
7 changes: 7 additions & 0 deletions src/test/resources/stubs/stub_flasher_32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"entry": 1074521560,
"text": "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",
"text_start": 1074520064,
"data": "DMD8P9jnC0Br6AtAA+0LQPLoC0CL6AtA8ugLQFHpC0Ae6gtAkOoLQDnqC0CB5wtAtukLQBDqC0B06QtAtOoLQJ7pC0C06gtAWegLQLboC0Dy6AtAUekLQHHoC0Bk6wtAxewLQKTmC0Dn7AtApOYLQKTmC0Ck5gtApOYLQKTmC0Ck5gtApOYLQKTmC0AL6wtApOYLQOXrC0DF7AtA",
"data_start": 1073605544
}
Loading

0 comments on commit 937ed90

Please sign in to comment.