Closed blackketter closed 4 years ago
I was just looking in to this today. Assuming that the protocol hasn't changed, the changes are pretty minimal:
I think the only open question for this is what the block size is for the flash. https://github.com/PaulStoffregen/cores/blob/master/teensy4/bootdata.c#L191 seems to indicate it's 64KiB, but I'm unsure if the bootloader expects 64K blobs or if it takes them in smaller chunks over the USB.
It would probably take someone an hour or two to trial-and-error whether the protocol is the same and what the necessary block size is.
I was able to get it working with Teensy 4.0 after a rather big headache.
I changed the MAX_MEMORY_SIZE
definition to 0x200000 as well as edited this line of code to look like the following:
static const struct {
const char *name;
int code_size;
int block_size;
} MCUs[] = {
{"at90usb162", 15872, 128},
{"atmega32u4", 32256, 128},
{"at90usb646", 64512, 256},
{"at90usb1286", 130048, 256},
#if defined(USE_LIBUSB) || defined(USE_APPLE_IOKIT) || defined(USE_WIN32)
{"mkl26z64", 63488, 512},
{"mk20dx128", 131072, 1024},
{"mk20dx256", 262144, 1024},
{"mk66fx1m0", 1048576, 1024},
{"mk64fx512", 524288, 1024},
{"imxrt1062", 2097152, 1024},
// Add duplicates that match friendly Teensy Names
// Match board names in boards.txt
{"TEENSY2", 32256, 128},
{"TEENSY2PP", 130048, 256},
{"TEENSYLC", 63488, 512},
{"TEENSY30", 131072, 1024},
{"TEENSY31", 262144, 1024},
{"TEENSY35", 524288, 1024},
{"TEENSY36", 1048576, 1024},
{"TEENSY40", 2097152, 1024},
#endif
{NULL, 0, 0},
};
It looks like the Teensy 4.0 hex files have this fun little line added to the beginning:
:0200000460009A
According to the Intel Hex Format, this sets the upper 16 bits of the 32-bit memory address. It uses the value 0x6000 to set this value. This then sets the extended_addr to 0x60000000, which suggests there is almost 1.5GB of memory available on the Teensy 4.0!
In order to get around this problem, I also changed this line of code to ignore any commands to use an extended address above the MAX_MEMORY_SIZE
.
if (code == 4 && len == 2) {
if (!sscanf(ptr, "%04x", &i)) return 1;
ptr += 4;
sum += ((i >> 8) & 255) + (i & 255);
if (!sscanf(ptr, "%02x", &cksum)) return 1;
if (((sum & 255) + (cksum & 255)) & 255) return 1;
if ((i << 16) > MAX_MEMORY_SIZE) return 1;
extended_addr = i << 16;
printf("ext addr = %08X\n", extended_addr);
}
This solution is admittedly hacky, but it has worked with several different hex files I have. It ends up ignoring any line in the hex file that tries to set the upper 16-bits to a location over 2MB. I'm not sure what will happen with this solution with hex files that approach the upper size limit of the teensy 4.0, but it should work with most firmwares.
It looks like the Teensy 4.0 hex files have this fun little line added to the beginning: :0200000460009A
Makes sense if you look at the linker skript:
imxrt1062.ld
Looks like this is some virtual address the flash is mapped to. Just wondering if ignoring this adress is the right way to do it but if it works...
Maybe Paul can shed some light into that?
If somebody feels like experimenting, I just published a first version of loader CLI reimplementation in Rust that should work with 4.0 (but haven't tested it with a 4.0 yet – I still need to get some binary working; tested with an LC, though, and tested booting from HalfKay into user mode with 3.6 and 4.0): https://crates.io/crates/teensy-loader
Caveats: libusb only (Linux/FreeBSD), accepts ELF file as an input (because I was tired of having to convert to ihex); patches for supporting other platforms / input formats are welcome, though.
Not sure what's needed, but I'm happy to pitch in and help.