FreeCalypso > hg > freecalypso-reveng
view frbl/test/frbl2.c @ 398:e5e5ed527cc1
compal: one more flash bootloader version
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 14 Jan 2023 06:09:25 +0000 |
parents | 10d62a3bfeec |
children |
line wrap: on
line source
#include <sys/types.h> #include <sys/ioctl.h> #include <sys/time.h> #include <sys/errno.h> #include <ctype.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <termios.h> #include <unistd.h> #include "srecreader.h" extern int errno; extern char *target_ttydev; extern int target_fd; extern struct srecreader srimage; #define MAX_IMAGE_LEN 32768 static u_char codeimage[MAX_IMAGE_LEN]; static unsigned codeimage_len; static uint32_t loadaddr; static u_char beacon_cmd[3] = {0xAA, 0x01, 0xDD}; static u_char fluid_baudrate_cmd[2] = {0x00, 0x07}; static u_char fluid_version_cmd[1] = {'V'}; static u_char fluid_chipquery_cmd[2] = {'Q', 'C'}; static u_char fluid_download_cmd[7] = {'L'}; #define BEACON_INTERVAL 13 /* ms between beacons */ #define INTERMEDIATE_TIMEOUT 500 /* ms to wait for responses */ #define SERIAL_FLUSH_DELAY 200 /* also in ms */ read_srec_image() { u_char *writep; uint32_t endaddr; int i; if (open_srec_file(&srimage) < 0) exit(1); for (;;) { if (read_s_record(&srimage) < 0) exit(1); switch (srimage.record_type) { case '0': if (srimage.lineno == 1) continue; fprintf(stderr, "%s: S0 record found in line %d (expected in line 1 only)\n", srimage.filename, srimage.lineno); exit(1); case '3': case '7': if (s3s7_get_addr_data(&srimage) < 0) exit(1); break; default: fprintf(stderr, "%s line %d: S%c record type not supported\n", srimage.filename, srimage.lineno, srimage.record_type); exit(1); } if (srimage.record_type == '7') break; /* must be S3 */ if (srimage.datalen < 1) { fprintf(stderr, "%s line %d: S3 record has zero data length\n", srimage.filename, srimage.lineno); exit(1); } if (srimage.datalen & 1) { fprintf(stderr, "%s line %d: S3 record has odd data length\n", srimage.filename, srimage.lineno); exit(1); } if (srimage.addr & 1) { fprintf(stderr, "%s line %d: S3 record has odd address\n", srimage.filename, srimage.lineno); exit(1); } /* handle first record */ if (!codeimage_len) { endaddr = loadaddr = srimage.addr; writep = codeimage; } if (srimage.addr != endaddr) { fprintf(stderr, "%s line %d: address discontinuity\n", srimage.filename, srimage.lineno); exit(1); } if (codeimage_len + srimage.datalen > MAX_IMAGE_LEN) { fprintf(stderr, "%s line %d: max image length exceeded\n", srimage.filename, srimage.lineno); exit(1); } /* reverse byte order */ for (i = 0; i < srimage.datalen; i += 2) { *writep++ = srimage.record[i+6]; *writep++ = srimage.record[i+5]; } endaddr += srimage.datalen; codeimage_len += srimage.datalen; } /* got S7 */ fclose(srimage.openfile); if (!codeimage_len) { fprintf(stderr, "%s line %d: S7 without any preceding S3 data records\n", srimage.filename, srimage.lineno); exit(1); } if (srimage.addr != loadaddr) { fprintf(stderr, "%s line %d: S7 address differs from image load address\n", srimage.filename, srimage.lineno); exit(1); } /* all good */ return(0); } static void fill_download_cmd() { unsigned nwords; nwords = codeimage_len >> 1; fluid_download_cmd[1] = loadaddr; fluid_download_cmd[2] = loadaddr >> 8; fluid_download_cmd[3] = loadaddr >> 16; fluid_download_cmd[4] = loadaddr >> 24; fluid_download_cmd[5] = nwords; fluid_download_cmd[6] = nwords >> 8; } static int expect_beacon_response(timeout) { u_char buf; fd_set fds; struct timeval tv; int cc; for (;;) { FD_ZERO(&fds); FD_SET(target_fd, &fds); tv.tv_sec = 0; tv.tv_usec = timeout * 1000; cc = select(target_fd+1, &fds, NULL, NULL, &tv); if (cc < 0) { if (errno == EINTR) continue; perror("select"); exit(1); } if (cc < 1) return(0); cc = read(target_fd, &buf, 1); if (cc <= 0) { perror("read after successful select"); exit(1); } if (buf == 'H') return(1); } } static send_beacons() { printf("Sending beacons to %s\n", target_ttydev); do write(target_fd, beacon_cmd, sizeof beacon_cmd); while (!expect_beacon_response(BEACON_INTERVAL)); return 0; } static int expect_add_response(buf, expect_bytes, timeout) u_char *buf; { fd_set fds; struct timeval tv; int pass, cc; for (pass = 0; pass < expect_bytes; ) { FD_ZERO(&fds); FD_SET(target_fd, &fds); tv.tv_sec = 0; tv.tv_usec = timeout * 1000; cc = select(target_fd+1, &fds, NULL, NULL, &tv); if (cc < 0) { if (errno == EINTR) continue; perror("select"); exit(1); } if (cc < 1) return(-1); cc = read(target_fd, buf + pass, expect_bytes - pass); if (cc <= 0) { perror("read after successful select"); exit(1); } pass += cc; } return(0); } perform_frbl2_protocol() { u_char respbuf[4]; static int zero = 0; ioctl(target_fd, FIONBIO, &zero); send_beacons(); printf("Got Hello response, attempting FLUID protocol\n"); write(target_fd, fluid_baudrate_cmd, sizeof fluid_baudrate_cmd); usleep(SERIAL_FLUSH_DELAY * 1000); tcflush(target_fd, TCIFLUSH); write(target_fd, fluid_version_cmd, sizeof fluid_version_cmd); if (expect_add_response(respbuf, 1, INTERMEDIATE_TIMEOUT) < 0) { fprintf(stderr, "no response to version query\n"); exit(1); } if (!isdigit(respbuf[0])) { fprintf(stderr, "bad response to version query: 0x%02X\n", respbuf[0]); exit(1); } printf("Version response: %d\n", respbuf[0] - '0'); write(target_fd, fluid_chipquery_cmd, sizeof fluid_chipquery_cmd); if (expect_add_response(respbuf, 4, INTERMEDIATE_TIMEOUT) < 0) { fprintf(stderr, "no response to chip ID query\n"); exit(1); } if (respbuf[2] || respbuf[3]) { fprintf(stderr, "bad response to chip ID query: %02X %02X %02X %02X\n", respbuf[0], respbuf[1], respbuf[2], respbuf[3]); exit(1); } printf("Chip ID response: %04X\n", (respbuf[1] << 8) | respbuf[0]); printf("Sending download command\n"); write(target_fd, fluid_download_cmd, sizeof fluid_download_cmd); if (expect_add_response(respbuf, 1, INTERMEDIATE_TIMEOUT) < 0) { fprintf(stderr, "no response to download command\n"); exit(1); } if (respbuf[0] != 'R') { fprintf(stderr, "bad response to download command: 0x%02X\n", respbuf[0]); exit(1); } if (write(target_fd, codeimage, codeimage_len) != codeimage_len) { perror("write of download image bulk"); exit(1); } printf("Code image sent!\n"); } frbl_test_main() { read_srec_image(); fill_download_cmd(); perform_frbl2_protocol(); }