Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
// Special format for the ESP family of chips (parsed by the ROM
// bootloader).
result.Binary = filepath.Join(tmpdir, "main"+outext)
err := makeESPFirmwareImage(result.Executable, result.Binary, outputBinaryFormat)
err := makeESPFirmwareImage(result.Executable, result.Binary, outputBinaryFormat, config.Target)
if err != nil {
return result, err
}
Expand Down
31 changes: 30 additions & 1 deletion builder/esp.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,38 @@ import (
"os"
"sort"
"strings"

"github.com/tinygo-org/tinygo/compileopts"
)

type espImageSegment struct {
addr uint32
data []byte
}

var espFlashSizes = map[string]uint8{
"1MB": 0x00,
"2MB": 0x10,
"4MB": 0x20,
"8MB": 0x30,
"16MB": 0x40,
"32MB": 0x50,
"64MB": 0x60,
"128MB": 0x70,
}

func setESPFlashSize(spiSpeedSize uint8, target *compileopts.TargetSpec) (uint8, error) {
if target == nil || target.ESPFlashSize == "" {
return spiSpeedSize, nil
}
size := strings.ToUpper(target.ESPFlashSize)
spiSize, ok := espFlashSizes[size]
if !ok {
return 0, fmt.Errorf("invalid esp-flash-size %q", size)
}
return spiSize | (spiSpeedSize & 0x0f), nil
}

// makeESPFirmwareImage converts an input ELF file to an image file for an ESP32 or
// ESP8266 chip. This is a special purpose image format just for the ESP chip
// family, and is parsed by the on-chip mask ROM bootloader.
Expand All @@ -31,7 +56,7 @@ type espImageSegment struct {
// https://github.com/espressif/esptool/wiki/Firmware-Image-Format
// https://github.com/espressif/esp-idf/blob/8fbb63c2a701c22ccf4ce249f43aded73e134a34/components/bootloader_support/include/esp_image_format.h#L58
// https://github.com/espressif/esptool/blob/master/esptool.py
func makeESPFirmwareImage(infile, outfile, format string) error {
func makeESPFirmwareImage(infile, outfile, format string, target *compileopts.TargetSpec) error {
inf, err := elf.Open(infile)
if err != nil {
return err
Expand Down Expand Up @@ -118,6 +143,10 @@ func makeESPFirmwareImage(infile, outfile, format string) error {
// Image header.
switch chip {
case "esp32", "esp32c3", "esp32s3", "esp32c6":
spiSpeedSize, err = setESPFlashSize(spiSpeedSize, target)
if err != nil {
return err
}
// Header format:
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
// Note: not adding a SHA256 hash as the binary is modified by
Expand Down
70 changes: 70 additions & 0 deletions builder/esp_test.go

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these tests? From the looks of it, they mostly just list the contents of the array above, so don't really add any value? There is barely any logic here being tested.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package builder

import (
"strings"
"testing"

"github.com/tinygo-org/tinygo/compileopts"
)

func TestESPFlashSize(t *testing.T) {
tests := []struct {
name string
defaultSpeedSize uint8
target *compileopts.TargetSpec
wantSpeedSize uint8
}{
{
name: "keeps esp32c3 default",
defaultSpeedSize: 0x1f,
target: &compileopts.TargetSpec{},
wantSpeedSize: 0x1f,
},
{
name: "sets esp32c3 4MB size nibble",
defaultSpeedSize: 0x1f,
target: &compileopts.TargetSpec{ESPFlashSize: "4MB"},
wantSpeedSize: 0x2f,
},
{
name: "keeps esp32c6 default frequency nibble",
defaultSpeedSize: 0x10,
target: &compileopts.TargetSpec{ESPFlashSize: "4MB"},
wantSpeedSize: 0x20,
},
{
name: "normalizes lowercase size",
defaultSpeedSize: 0x1f,
target: &compileopts.TargetSpec{ESPFlashSize: "8mb"},
wantSpeedSize: 0x3f,
},
{
name: "allows nil target",
defaultSpeedSize: 0x1f,
target: nil,
wantSpeedSize: 0x1f,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
spiSpeedSize, err := setESPFlashSize(test.defaultSpeedSize, test.target)
if err != nil {
t.Fatal(err)
}
if spiSpeedSize != test.wantSpeedSize {
t.Fatalf("unexpected spi speed/size: got %#x, want %#x", spiSpeedSize, test.wantSpeedSize)
}
})
}
}

func TestESPFlashSizeInvalid(t *testing.T) {
_, err := setESPFlashSize(0x1f, &compileopts.TargetSpec{ESPFlashSize: "6MB"})
if err == nil {
t.Fatal("expected error, got nil")
}
if !strings.Contains(err.Error(), "esp-flash-size") {
t.Fatalf("unexpected error: got %q, want it to contain %q", err, "esp-flash-size")
}
}
1 change: 1 addition & 0 deletions compileopts/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type TargetSpec struct {
FlashFilename string `json:"msd-firmware-name,omitempty"`
UF2FamilyID string `json:"uf2-family-id,omitempty"`
BinaryFormat string `json:"binary-format,omitempty"`
ESPFlashSize string `json:"esp-flash-size,omitempty"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment.

Suggested change
ESPFlashSize string `json:"esp-flash-size,omitempty"`

OpenOCDInterface string `json:"openocd-interface,omitempty"`
OpenOCDTarget string `json:"openocd-target,omitempty"`
OpenOCDTransport string `json:"openocd-transport,omitempty"`
Expand Down