Skip to content

Commit

Permalink
Fix broken ELF upload support for Teensy 4
Browse files Browse the repository at this point in the history
  • Loading branch information
Koromix committed Dec 1, 2019
1 parent 7f80cc2 commit 0b18c1f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 26 deletions.
60 changes: 35 additions & 25 deletions src/libty/class_teensy.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ static int halfkay_send(hs_port *port, unsigned int halfkay_version, size_t bloc
}

static int get_halfkay_settings(ty_model model, unsigned int *rhalfkay_version,
size_t *rcode_size, size_t *rblock_size)
size_t *rmin_address, size_t *rmax_address, size_t *rblock_size)
{
if ((model == TY_MODEL_TEENSY_PP_10 || model == TY_MODEL_TEENSY_20) &&
!getenv("TYTOOLS_EXPERIMENTAL_BOARDS")) {
Expand All @@ -604,49 +604,58 @@ static int get_halfkay_settings(ty_model model, unsigned int *rhalfkay_version,
switch ((ty_model_teensy)model) {
case TY_MODEL_TEENSY_PP_10: {
*rhalfkay_version = 1;
*rcode_size = 64512;
*rmin_address = 0;
*rmax_address = 0xFC00;
*rblock_size = 256;
} break;
case TY_MODEL_TEENSY_20: {
*rhalfkay_version = 1;
*rcode_size = 32256;
*rmin_address = 0;
*rmax_address = 0x7E00;
*rblock_size = 128;
} break;
case TY_MODEL_TEENSY_PP_20: {
*rhalfkay_version = 2;
*rcode_size = 130048;
*rmin_address = 0;
*rmax_address = 0x1FC00;
*rblock_size = 256;
} break;
case TY_MODEL_TEENSY_30: {
*rhalfkay_version = 3;
*rcode_size = 131072;
*rmin_address = 0;
*rmax_address = 0x20000;
*rblock_size = 1024;
} break;
case TY_MODEL_TEENSY_31:
case TY_MODEL_TEENSY_32: {
*rhalfkay_version = 3;
*rcode_size = 262144;
*rmin_address = 0;
*rmax_address = 0x40000;
*rblock_size = 1024;
} break;
case TY_MODEL_TEENSY_35: {
*rhalfkay_version = 3;
*rcode_size = 524288;
*rmin_address = 0;
*rmax_address = 0x80000;
*rblock_size = 1024;
} break;
case TY_MODEL_TEENSY_36: {
*rhalfkay_version = 3;
*rcode_size = 1048576;
*rmin_address = 0;
*rmax_address = 0x100000;
*rblock_size = 1024;
} break;
case TY_MODEL_TEENSY_LC: {
*rhalfkay_version = 3;
*rcode_size = 63488;
*rmin_address = 0;
*rmax_address = 0xF800;
*rblock_size = 512;
} break;
case TY_MODEL_TEENSY_40_BETA1:
case TY_MODEL_TEENSY_40: {
*rhalfkay_version = 3;
*rcode_size = 1572864;
*rmin_address = 0x60000000;
*rmax_address = 0x60180000;
*rblock_size = 1024;
} break;

Expand All @@ -663,38 +672,39 @@ static int teensy_upload(ty_board_interface *iface, ty_firmware *fw,
ty_board_upload_progress_func *pf, void *udata)
{
unsigned int halfkay_version;
size_t code_size, block_size;
size_t min_address, max_address, block_size;
int r;

r = get_halfkay_settings(iface->model, &halfkay_version, &code_size, &block_size);
r = get_halfkay_settings(iface->model, &halfkay_version, &min_address, &max_address, &block_size);
if (r < 0)
return r;

if (fw->total_size > code_size)
if (fw->max_address > max_address)
return ty_error(TY_ERROR_RANGE, "Firmware is too big for %s",
ty_models[iface->model].name);

if (pf) {
r = (*pf)(iface->board, fw, 0, code_size, udata);
r = (*pf)(iface->board, fw, 0, max_address - min_address, udata);
if (r)
return r;
}

for (unsigned int segment_idx = 0; segment_idx < fw->segments_count; segment_idx++) {
const ty_firmware_segment *segment = &fw->segments[segment_idx];
size_t uploaded_len = 0;
for (size_t address = min_address; address < fw->max_address; address += block_size) {
char buf[8192];
size_t buf_len;

size_t uploaded_size = 0;
for (size_t offset = 0; offset < segment->size; offset += block_size) {
size_t write_size = TY_MIN(block_size, (size_t)(segment->size - offset));
memset(buf, 0, sizeof(buf));
buf_len = ty_firmware_extract(fw, (uint32_t)address, buf, block_size);

r = halfkay_send(iface->port, halfkay_version, block_size,
segment->address + offset, segment->data + offset, write_size, 3000);
if (buf_len) {
r = halfkay_send(iface->port, halfkay_version, block_size, address, buf, buf_len, 3000);
if (r < 0)
return r;
uploaded_size += write_size;
uploaded_len += buf_len;

if (pf) {
r = (*pf)(iface->board, fw, uploaded_size, code_size, udata);
r = (*pf)(iface->board, fw, uploaded_len, max_address - min_address, udata);
if (r)
return r;
}
Expand All @@ -707,9 +717,9 @@ static int teensy_upload(ty_board_interface *iface, ty_firmware *fw,
static int teensy_reset(ty_board_interface *iface)
{
unsigned int halfkay_version;
size_t code_size, block_size;
size_t min_address, max_address, block_size;

int r = get_halfkay_settings(iface->model, &halfkay_version, &code_size, &block_size);
int r = get_halfkay_settings(iface->model, &halfkay_version, &min_address, &max_address, &block_size);
if (r < 0)
return r;

Expand Down
27 changes: 27 additions & 0 deletions src/libty/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,40 @@ const ty_firmware_segment *ty_firmware_find_segment(const ty_firmware *fw, uint3

for (unsigned int i = fw->segments_count; i-- > 0;) {
const ty_firmware_segment *segment = &fw->segments[i];

if (address >= segment->address && address < segment->address + segment->size)
return segment;
}

return NULL;
}

size_t ty_firmware_extract(const ty_firmware *fw, uint32_t address, uint8_t *buf, size_t size)
{
assert(fw);

size_t total_len = 0;
for (unsigned int i = 0; i < fw->segments_count; i++) {
const ty_firmware_segment *segment = &fw->segments[i];

if (address >= segment->address && address < segment->address + segment->size) {
size_t delta = address - segment->address;
size_t len = TY_MIN(segment->size - delta, size);

memcpy(buf, segment->data + delta, len);
total_len += len;
} else if (address < segment->address && address + size > segment->address) {
size_t delta = segment->address - address;
size_t len = TY_MIN(segment->size, size - delta);

memcpy(buf + delta, segment->data, len);
total_len += len;
}
}

return total_len;
}

int ty_firmware_add_segment(ty_firmware *fw, uint32_t address, size_t size,
ty_firmware_segment **rsegment)
{
Expand Down
4 changes: 3 additions & 1 deletion src/libty/firmware.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ int ty_firmware_load_ihex(ty_firmware *fw, const uint8_t *mem, size_t len);
ty_firmware *ty_firmware_ref(ty_firmware *fw);
void ty_firmware_unref(ty_firmware *fw);

const ty_firmware_segment *ty_firmware_find_segment(const ty_firmware *fw, uint32_t address);
size_t ty_firmware_extract(const ty_firmware *fw, uint32_t address, uint8_t *buf, size_t size);

int ty_firmware_add_segment(ty_firmware *fw, uint32_t address, size_t size,
ty_firmware_segment **rsegment);
int ty_firmware_expand_segment(ty_firmware *fw, ty_firmware_segment *segment, size_t size);

const ty_firmware_segment *ty_firmware_find_segment(const ty_firmware *fw, uint32_t address);

unsigned int ty_firmware_identify(const ty_firmware *fw, ty_model *rmodels,
unsigned int max_models);
Expand Down

0 comments on commit 0b18c1f

Please sign in to comment.