compileopts: add support for custom binary formats
Some chips (like the ESP family) have a particular image format that is more complex than simply dumping everything in a raw image.
Этот коммит содержится в:
родитель
3ee47a9c1b
коммит
9a17698d6a
4 изменённых файлов: 49 добавлений и 16 удалений
|
@ -260,19 +260,27 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an Intel .hex file or .bin file from the .elf file.
|
// Get an Intel .hex file or .bin file from the .elf file.
|
||||||
if outext == ".hex" || outext == ".bin" || outext == ".gba" {
|
outputBinaryFormat := config.BinaryFormat(outext)
|
||||||
|
switch outputBinaryFormat {
|
||||||
|
case "elf":
|
||||||
|
// do nothing, file is already in ELF format
|
||||||
|
case "hex", "bin":
|
||||||
|
// Extract raw binary, either encoding it as a hex file or as a raw
|
||||||
|
// firmware file.
|
||||||
tmppath = filepath.Join(dir, "main"+outext)
|
tmppath = filepath.Join(dir, "main"+outext)
|
||||||
err := objcopy(executable, tmppath)
|
err := objcopy(executable, tmppath, outputBinaryFormat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if outext == ".uf2" {
|
case "uf2":
|
||||||
// Get UF2 from the .elf file.
|
// Get UF2 from the .elf file.
|
||||||
tmppath = filepath.Join(dir, "main"+outext)
|
tmppath = filepath.Join(dir, "main"+outext)
|
||||||
err := convertELFFileToUF2File(executable, tmppath, config.Target.UF2FamilyID)
|
err := convertELFFileToUF2File(executable, tmppath, config.Target.UF2FamilyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown output binary format: %s", outputBinaryFormat)
|
||||||
}
|
}
|
||||||
return action(tmppath)
|
return action(tmppath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/marcinbor85/gohex"
|
"github.com/marcinbor85/gohex"
|
||||||
|
@ -93,7 +92,7 @@ func extractROM(path string) (uint64, []byte, error) {
|
||||||
|
|
||||||
// objcopy converts an ELF file to a different (simpler) output file format:
|
// objcopy converts an ELF file to a different (simpler) output file format:
|
||||||
// .bin or .hex. It extracts only the .text section.
|
// .bin or .hex. It extracts only the .text section.
|
||||||
func objcopy(infile, outfile string) error {
|
func objcopy(infile, outfile, binaryFormat string) error {
|
||||||
f, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
|
f, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -107,23 +106,20 @@ func objcopy(infile, outfile string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to the file, in the correct format.
|
// Write to the file, in the correct format.
|
||||||
switch filepath.Ext(outfile) {
|
switch binaryFormat {
|
||||||
case ".gba":
|
case "hex":
|
||||||
// The address is not stored in a .gba file.
|
// Intel hex file, includes the firmware start address.
|
||||||
_, err := f.Write(data)
|
|
||||||
return err
|
|
||||||
case ".bin":
|
|
||||||
// The address is not stored in a .bin file (therefore you
|
|
||||||
// should use .hex files in most cases).
|
|
||||||
_, err := f.Write(data)
|
|
||||||
return err
|
|
||||||
case ".hex":
|
|
||||||
mem := gohex.NewMemory()
|
mem := gohex.NewMemory()
|
||||||
err := mem.AddBinary(uint32(addr), data)
|
err := mem.AddBinary(uint32(addr), data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return objcopyError{"failed to create .hex file", err}
|
return objcopyError{"failed to create .hex file", err}
|
||||||
}
|
}
|
||||||
return mem.DumpIntelHex(f, 16)
|
return mem.DumpIntelHex(f, 16)
|
||||||
|
case "bin":
|
||||||
|
// The start address is not stored in raw firmware files (therefore you
|
||||||
|
// should use .hex files in most cases).
|
||||||
|
_, err := f.Write(data)
|
||||||
|
return err
|
||||||
default:
|
default:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,31 @@ func (c *Config) Debug() bool {
|
||||||
return c.Options.Debug
|
return c.Options.Debug
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BinaryFormat returns an appropriate binary format, based on the file
|
||||||
|
// extension and the configured binary format in the target JSON file.
|
||||||
|
func (c *Config) BinaryFormat(ext string) string {
|
||||||
|
switch ext {
|
||||||
|
case ".bin", ".gba":
|
||||||
|
// The simplest format possible: dump everything in a raw binary file.
|
||||||
|
if c.Target.BinaryFormat != "" {
|
||||||
|
return c.Target.BinaryFormat
|
||||||
|
}
|
||||||
|
return "bin"
|
||||||
|
case ".hex":
|
||||||
|
// Similar to bin, but includes the start address and is thus usually a
|
||||||
|
// better format.
|
||||||
|
return "hex"
|
||||||
|
case ".uf2":
|
||||||
|
// Special purpose firmware format, mainly used on Adafruit boards.
|
||||||
|
// More information:
|
||||||
|
// https://github.com/Microsoft/uf2
|
||||||
|
return "uf2"
|
||||||
|
default:
|
||||||
|
// Use the ELF format for unrecognized file formats.
|
||||||
|
return "elf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Programmer returns the flash method and OpenOCD interface name given a
|
// Programmer returns the flash method and OpenOCD interface name given a
|
||||||
// particular configuration. It may either be all configured in the target JSON
|
// particular configuration. It may either be all configured in the target JSON
|
||||||
// file or be modified using the -programmmer command-line option.
|
// file or be modified using the -programmmer command-line option.
|
||||||
|
|
|
@ -47,6 +47,7 @@ type TargetSpec struct {
|
||||||
FlashVolume string `json:"msd-volume-name"`
|
FlashVolume string `json:"msd-volume-name"`
|
||||||
FlashFilename string `json:"msd-firmware-name"`
|
FlashFilename string `json:"msd-firmware-name"`
|
||||||
UF2FamilyID string `json:"uf2-family-id"`
|
UF2FamilyID string `json:"uf2-family-id"`
|
||||||
|
BinaryFormat string `json:"binary-format"`
|
||||||
OpenOCDInterface string `json:"openocd-interface"`
|
OpenOCDInterface string `json:"openocd-interface"`
|
||||||
OpenOCDTarget string `json:"openocd-target"`
|
OpenOCDTarget string `json:"openocd-target"`
|
||||||
OpenOCDTransport string `json:"openocd-transport"`
|
OpenOCDTransport string `json:"openocd-transport"`
|
||||||
|
@ -128,6 +129,9 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
|
||||||
if spec2.UF2FamilyID != "" {
|
if spec2.UF2FamilyID != "" {
|
||||||
spec.UF2FamilyID = spec2.UF2FamilyID
|
spec.UF2FamilyID = spec2.UF2FamilyID
|
||||||
}
|
}
|
||||||
|
if spec2.BinaryFormat != "" {
|
||||||
|
spec.BinaryFormat = spec2.BinaryFormat
|
||||||
|
}
|
||||||
if spec2.OpenOCDInterface != "" {
|
if spec2.OpenOCDInterface != "" {
|
||||||
spec.OpenOCDInterface = spec2.OpenOCDInterface
|
spec.OpenOCDInterface = spec2.OpenOCDInterface
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче