diff options
Diffstat (limited to 'host/lib/usrp_clock')
| -rw-r--r-- | host/lib/usrp_clock/octoclock/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | host/lib/usrp_clock/octoclock/kk_ihex.h | 191 | ||||
| -rw-r--r-- | host/lib/usrp_clock/octoclock/kk_ihex_license.txt | 20 | ||||
| -rw-r--r-- | host/lib/usrp_clock/octoclock/kk_ihex_read.c | 261 | ||||
| -rw-r--r-- | host/lib/usrp_clock/octoclock/kk_ihex_read.h | 119 | ||||
| -rw-r--r-- | host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp | 120 | 
6 files changed, 44 insertions, 670 deletions
diff --git a/host/lib/usrp_clock/octoclock/CMakeLists.txt b/host/lib/usrp_clock/octoclock/CMakeLists.txt index d3728344e..d2b70e356 100644 --- a/host/lib/usrp_clock/octoclock/CMakeLists.txt +++ b/host/lib/usrp_clock/octoclock/CMakeLists.txt @@ -19,10 +19,7 @@  # Conditionally configure the OctoClock support  ########################################################################  IF(ENABLE_OCTOCLOCK) -    ADD_DEFINITIONS(-DIHEX_USE_STDBOOL) -      LIBUHD_APPEND_SOURCES( -        ${CMAKE_CURRENT_SOURCE_DIR}/kk_ihex_read.c          ${CMAKE_CURRENT_SOURCE_DIR}/octoclock_eeprom.cpp          ${CMAKE_CURRENT_SOURCE_DIR}/octoclock_image_loader.cpp          ${CMAKE_CURRENT_SOURCE_DIR}/octoclock_impl.cpp diff --git a/host/lib/usrp_clock/octoclock/kk_ihex.h b/host/lib/usrp_clock/octoclock/kk_ihex.h deleted file mode 100644 index 20eba43cc..000000000 --- a/host/lib/usrp_clock/octoclock/kk_ihex.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * kk_ihex.h: A simple library for reading and writing the Intel HEX  - * or IHEX format. Intended mainly for embedded systems, and thus - * somewhat optimised for size at the expense of error handling and - * generality. - * - *      USAGE - *      ----- - * - * The library has been split into read and write parts, which use a - * common data structure (`struct ihex_state`), but each can be used - * independently. Include the header `kk_ihex_read.h` for reading, and/or - * the header `kk_ihex_write.h` for writing (and link with their respective - * object files). Both can be used simultaneously - this header defines - * the shared data structures and definitions. - * - * - *      READING INTEL HEX DATA - *      ---------------------- - * - * To read data in the Intel HEX format, you must perform the actual reading - * of bytes using other means (e.g., stdio). The bytes read must then be - * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions - * will then call `ihex_data_read`, at which stage the `struct ihex_state` - * structure will contain the data along with its address. See the header - * `kk_ihex_read.h` for details and example implementation of `ihex_data_read`. - * - * The sequence to read data in IHEX format is: - *      struct ihex_state ihex; - *      ihex_begin_read(&ihex); - *      ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes); - *      ihex_end_read(&ihex); - * - * - *      WRITING BINARY DATA AS INTEL HEX - *      -------------------------------- - * - * In order to write out data, the `ihex_write_at_address` or - * `ihex_write_at_segment` functions are used to set the data location, - * and then the binary bytes are written with `ihex_write_byte` and/or - * `ihex_write_bytes`. The writing functions will then call the function - * `ihex_flush_buffer` whenever the internal write buffer needs to be - * cleared - it is up to the caller to provide an implementation of - * `ihex_flush_buffer` to do the actual writing. See the header - * `kk_ihex_write.h` for details and an example implementation. - * - * See the declaration further down for an example implementation. - * - * The sequence to write data in IHEX format is: - *      struct ihex_state ihex; - *      ihex_init(&ihex); - *      ihex_write_at_address(&ihex, 0); - *      ihex_write_bytes(&ihex, my_data, length_of_my_data); - *      ihex_end_write(&ihex); - * - * For outputs larger than 64KiB, 32-bit linear addresses are output. Normally - * the initial linear extended address record of zero is NOT written - it can - * be forced by setting `ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW` before - * writing the first byte. - * - * Gaps in the data may be created by calling `ihex_write_at_address` with the - * new starting address without calling `ihex_end_write` in between. - * - * - * The same `struct ihex_state` may be used either for reading or writing, - * but NOT both at the same time. Furthermore, a global output buffer is - * used for writing, i.e., multiple threads must not write simultaneously - * (but multiple writes may be interleaved). - * - * - *      CONSERVING MEMORY - *      ----------------- - * - * For memory-critical use, you can save additional memory by defining - * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that - * this limit affects both reading and writing, so the resulting library - * will be unable to read lines with more than this number of data bytes. - * That said, I haven't encountered any IHEX files with more than 32 - * data bytes per line. For write only there is no reason to define the - * maximum as greater than the line length you'll actually be writing, - * e.g., 32 or 16. - * - * If the write functionality is only occasionally used, you can provide - * your own buffer for the duration by defining `IHEX_EXTERNAL_WRITE_BUFFER` - * and providing a `char *ihex_write_buffer` which points to valid storage - * for at least `IHEX_WRITE_BUFFER_LENGTH` characters from before the first - * call to any IHEX write function to until after the last. - * - * If you are doing both reading and writing, you can define the maximum - * output length separately as `IHEX_MAX_OUTPUT_LINE_LENGTH` - this will - * decrease the write buffer size, but `struct ihex_state` will still - * use the larger `IHEX_LINE_MAX_LENGTH` for its data storage. - * - * You can also save a few additional bytes by disabling support for - * segmented addresses, by defining `IHEX_DISABLE_SEGMENTS`. Both the - * read and write modules need to be build with the same option, as the - * resulting data structures will not be compatible otherwise. To be honest, - * this is a fairly pointless optimisation. - * - * - * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/ - * Provided with absolutely no warranty, use at your own risk only. - * Use and distribute freely, mark modified copies as such. - */ - -#ifndef KK_IHEX_H -#define KK_IHEX_H - -#define KK_IHEX_VERSION "2015-08-10" - -#include <stdint.h> - -#ifdef IHEX_USE_STDBOOL -#include <stdbool.h> -typedef bool ihex_bool_t; -#else -typedef uint_fast8_t ihex_bool_t; -#endif - -typedef uint_least32_t ihex_address_t; -typedef uint_least16_t ihex_segment_t; -typedef int ihex_count_t; - -// Maximum number of data bytes per line (applies to both reading and -// writing!); specify 255 to support reading all possible lengths. Less -// can be used to limit memory footprint on embedded systems, e.g., -// most programs with IHEX output use 32. -#ifndef IHEX_LINE_MAX_LENGTH -#define IHEX_LINE_MAX_LENGTH 255 -#endif - -enum ihex_flags { -    IHEX_FLAG_ADDRESS_OVERFLOW = 0x80   // 16-bit address overflow -}; -typedef uint8_t ihex_flags_t; - -typedef struct ihex_state { -    ihex_address_t  address; -#ifndef IHEX_DISABLE_SEGMENTS -    ihex_segment_t  segment; -#endif -    ihex_flags_t    flags; -    uint8_t         line_length; -    uint8_t         length; -    uint8_t         data[IHEX_LINE_MAX_LENGTH + 1]; -} kk_ihex_t; - -enum ihex_record_type { -    IHEX_DATA_RECORD, -    IHEX_END_OF_FILE_RECORD, -    IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD, -    IHEX_START_SEGMENT_ADDRESS_RECORD, -    IHEX_EXTENDED_LINEAR_ADDRESS_RECORD, -    IHEX_START_LINEAR_ADDRESS_RECORD -}; -typedef uint8_t ihex_record_type_t; - -#ifndef IHEX_DISABLE_SEGMENTS - -// Resolve segmented address (if any). It is the author's recommendation that -// segmented addressing not be used (and indeed the write function of this -// library uses linear 32-bit addressing unless manually overridden). -// -#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address + (((ihex_address_t)((ihex)->segment)) << 4)) -// -// Note that segmented addressing with the above macro is not strictly adherent -// to the IHEX specification, which mandates that the lowest 16 bits of the -// address and the index of the data byte must be added modulo 64K (i.e., -// at 16 bits precision with wraparound) and the segment address only added -// afterwards. -// -// To implement fully correct segmented addressing, compute the address -// of _each byte_ with its index in `data` as follows: -// -#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((((ihex)->address + (byte_index)) & 0xFFFFU) + (((ihex_address_t)((ihex)->segment)) << 4)) - -#else // IHEX_DISABLE_SEGMENTS: - -#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address) -#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((ihex)->address + (byte_index)) - -#endif - -// The newline string (appended to every output line, e.g., "\r\n") -#ifndef IHEX_NEWLINE_STRING -#define IHEX_NEWLINE_STRING "\n" -#endif - -// See kk_ihex_read.h and kk_ihex_write.h for function declarations! - -#endif // !KK_IHEX_H diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_license.txt b/host/lib/usrp_clock/octoclock/kk_ihex_license.txt deleted file mode 100644 index 530f413e3..000000000 --- a/host/lib/usrp_clock/octoclock/kk_ihex_license.txt +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2015 Kimmo Kulovesi - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_read.c b/host/lib/usrp_clock/octoclock/kk_ihex_read.c deleted file mode 100644 index 964cdd165..000000000 --- a/host/lib/usrp_clock/octoclock/kk_ihex_read.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * kk_ihex_read.c: A simple library for reading the Intel HEX (IHEX) format. - * - * See the header `kk_ihex.h` for instructions. - * - * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/ - * Provided with absolutely no warranty, use at your own risk only. - * Use and distribute freely, mark modified copies as such. - * - * Modifications Copyright (c) 2015 National Instruments Corp. - */ - -#include "kk_ihex_read.h" - -#include <stdio.h> -#include <stdlib.h> - -#define IHEX_START ':' - -#define AUTODETECT_ADDRESS (~0UL) - -#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U) - -enum ihex_read_state { -    READ_WAIT_FOR_START = 0, -    READ_COUNT_HIGH = 1, -    READ_COUNT_LOW, -    READ_ADDRESS_MSB_HIGH, -    READ_ADDRESS_MSB_LOW, -    READ_ADDRESS_LSB_HIGH, -    READ_ADDRESS_LSB_LOW, -    READ_RECORD_TYPE_HIGH, -    READ_RECORD_TYPE_LOW, -    READ_DATA_HIGH, -    READ_DATA_LOW -}; - -#define IHEX_READ_RECORD_TYPE_MASK 0x07 -#define IHEX_READ_STATE_MASK 0x78 -#define IHEX_READ_STATE_OFFSET 3 - -void -ihex_begin_read (struct ihex_state * const ihex) { -    ihex->address = 0; -#ifndef IHEX_DISABLE_SEGMENTS -    ihex->segment = 0; -#endif -    ihex->flags = 0; -    ihex->line_length = 0; -    ihex->length = 0; -} - -void -ihex_read_at_address (struct ihex_state * const ihex, ihex_address_t address) { -    ihex_begin_read(ihex); -    ihex->address = address; -} - -#ifndef IHEX_DISABLE_SEGMENTS -void -ihex_read_at_segment (struct ihex_state * const ihex, ihex_segment_t segment) { -    ihex_begin_read(ihex); -    ihex->segment = segment; -} -#endif - -void -ihex_end_read (struct ihex_state * const ihex, FILE* outfile) { -    uint_fast8_t type = ihex->flags & IHEX_READ_RECORD_TYPE_MASK; -    uint_fast8_t sum; -    if ((sum = ihex->length) == 0 && type == IHEX_DATA_RECORD) { -        return; -    } -    { -        // compute and validate checksum -        const uint8_t * const eptr = ihex->data + sum; -        const uint8_t *r = ihex->data; -        sum += type + (ihex->address & 0xFFU) + ((ihex->address >> 8) & 0xFFU); -        while (r != eptr) { -            sum += *r++; -        } -        sum = (~sum + 1U) ^ *eptr; // *eptr is the received checksum -    } -    if (ihex_data_read(ihex, type, sum, outfile)) { -        if (type == IHEX_EXTENDED_LINEAR_ADDRESS_RECORD) { -            ihex->address &= 0xFFFFU; -            ihex->address |= (((ihex_address_t) ihex->data[0]) << 24) | -                             (((ihex_address_t) ihex->data[1]) << 16); -#ifndef IHEX_DISABLE_SEGMENTS -        } else if (type == IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD) { -            ihex->segment = (ihex_segment_t) ((ihex->data[0] << 8) | ihex->data[1]); -#endif -        } -    } -    ihex->length = 0; -    ihex->flags = 0; -} - -void -ihex_read_byte (struct ihex_state * const ihex, const char byte, FILE* outfile) { -    uint_fast8_t b = (uint_fast8_t) byte; -    uint_fast8_t len = ihex->length; -    uint_fast8_t state = (ihex->flags & IHEX_READ_STATE_MASK); -    ihex->flags ^= state; // turn off the old state -    state >>= IHEX_READ_STATE_OFFSET; - -    if (b >= '0' && b <= '9') { -        b -= '0'; -    } else if (b >= 'A' && b <= 'F') { -        b -= 'A' - 10; -    } else if (b >= 'a' && b <= 'f') { -        b -= 'a' - 10; -    } else if (b == IHEX_START) { -        // sync to a new record at any state -        state = READ_COUNT_HIGH; -        goto end_read; -    } else { -        // ignore unknown characters (e.g., extra whitespace) -        goto save_read_state; -    } - -    if (!(++state & 1)) { -        // high nybble, store temporarily at end of data: -        b <<= 4; -        ihex->data[len] = b; -    } else { -        // low nybble, combine with stored high nybble: -        b = (ihex->data[len] |= b); -        switch (state >> 1) { -        default: -            // remain in initial state while waiting for : -            return; -        case (READ_COUNT_LOW >> 1): -            // data length -            ihex->line_length = b; -#if IHEX_LINE_MAX_LENGTH < 255 -            if (b > IHEX_LINE_MAX_LENGTH) { -                ihex_end_read(ihex); -                return; -            } -#endif -            break; -        case (READ_ADDRESS_MSB_LOW >> 1): -            // high byte of 16-bit address -            ihex->address &= ADDRESS_HIGH_MASK; // clear the 16-bit address -            ihex->address |= ((ihex_address_t) b) << 8U; -            break; -        case (READ_ADDRESS_LSB_LOW >> 1): -            // low byte of 16-bit address -            ihex->address |= (ihex_address_t) b; -            break; -        case (READ_RECORD_TYPE_LOW >> 1): -            // record type -            if (b & ~IHEX_READ_RECORD_TYPE_MASK) { -                // skip unknown record types silently -                return; -            }  -            ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK) | b; -            break; -        case (READ_DATA_LOW >> 1): -            if (len < ihex->line_length) { -                // data byte -                ihex->length = len + 1; -                state = READ_DATA_HIGH; -                goto save_read_state; -            } -            // end of line (last "data" byte is checksum) -            state = READ_WAIT_FOR_START; -        end_read: -            ihex_end_read(ihex, outfile); -        } -    } -save_read_state: -    ihex->flags |= state << IHEX_READ_STATE_OFFSET; -} - -void -ihex_read_bytes (struct ihex_state * ihex, -                 const char * data, -                 ihex_count_t count, -		 FILE* outfile) { -    while (count > 0) { -        ihex_read_byte(ihex, *data++, outfile); -        --count; -    } -} - -ihex_bool_t -ihex_data_read (struct ihex_state *ihex, -                ihex_record_type_t type, -                ihex_bool_t error, -		FILE* outfile) { -    unsigned long line_number = 1L; -    unsigned long file_position = 0L; -    unsigned long address_offset = 0L; -    bool debug_enabled = false; - -    if (error) { -        (void) fprintf(stderr, "Checksum error on line %lu\n", line_number); -        return false; -    } -    if ((error = (ihex->length < ihex->line_length))) { -        (void) fprintf(stderr, "Line length error on line %lu\n", line_number); -        return false; -    } -    if (!outfile) { -        (void) fprintf(stderr, "Excess data after end of file record\n"); -        return false; -    } -    if (type == IHEX_DATA_RECORD) { -        unsigned long address = (unsigned long) IHEX_LINEAR_ADDRESS(ihex); -        if (address < address_offset) { -            if (address_offset == AUTODETECT_ADDRESS) { -                // autodetect initial address -                address_offset = address; -                if (debug_enabled) { -                    (void) fprintf(stderr, "Address offset: 0x%lx\n", -                            address_offset); -                } -            } else { -                (void) fprintf(stderr, "Address underflow on line %lu\n", -                        line_number); -                return false; -            } -        } -        address -= address_offset; -        if (address != file_position) { -            if (debug_enabled) { -                (void) fprintf(stderr, -                        "Seeking from 0x%lx to 0x%lx on line %lu\n", -                        file_position, address, line_number); -            } -            if (outfile == stdout || fseek(outfile, (long) address, SEEK_SET)) { -                if (file_position < address) { -                    // "seek" forward in stdout by writing NUL bytes -                    do { -                        (void) fputc('\0', outfile); -                    } while (++file_position < address); -                } else { -                    perror("fseek"); -                    return false; -                } -            } -            file_position = address; -        } -        if (!fwrite(ihex->data, ihex->length, 1, outfile)) { -            perror("fwrite"); -            return false; -        } -        file_position += ihex->length; -    } else if (type == IHEX_END_OF_FILE_RECORD) { -        if (debug_enabled) { -            (void) fprintf(stderr, "%lu bytes written\n", file_position); -        } -        if (outfile != stdout) { -            (void) fclose(outfile); -        } -        outfile = NULL; -    } -    return true; -} diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_read.h b/host/lib/usrp_clock/octoclock/kk_ihex_read.h deleted file mode 100644 index 303622b18..000000000 --- a/host/lib/usrp_clock/octoclock/kk_ihex_read.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * kk_ihex_read.h: A simple library for reading Intel HEX data. See - * the accompanying kk_ihex_write.h for IHEX write support. - * - * - *      READING INTEL HEX DATA - *      ---------------------- - * - * To read data in the Intel HEX format, you must perform the actual reading - * of bytes using other means (e.g., stdio). The bytes read must then be - * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions - * will then call `ihex_data_read`, at which stage the `struct ihex_state` - * structure will contain the data along with its address. See below for - * details and example implementation of `ihex_data_read`. - * - * The sequence to read data in IHEX format is: - *      struct ihex_state ihex; - *      ihex_begin_read(&ihex); - *      ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes); - *      ihex_end_read(&ihex); - * - * - *      CONSERVING MEMORY - *      ----------------- - * - * For memory-critical use, you can save additional memory by defining - * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that - * this limit affects both reading and writing, so the resulting library - * will be unable to read lines with more than this number of data bytes. - * That said, I haven't encountered any IHEX files with more than 32 - * data bytes per line. - * - * - * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/ - * Provided with absolutely no warranty, use at your own risk only. - * Use and distribute freely, mark modified copies as such. - * - * Modifications Copyright (c) 2015 National Instruments Corp. - */ - -#ifndef KK_IHEX_READ_H -#define KK_IHEX_READ_H -#ifdef __cplusplus -extern "C" { -#endif - -#include "kk_ihex.h" - -#include <stdio.h> - -// Begin reading at address 0 -void ihex_begin_read(struct ihex_state * const ihex); - -// Begin reading at `address` (the lowest 16 bits of which will be ignored); -// this is required only if the high bytes of the 32-bit starting address -// are not specified in the input data and they are non-zero -void ihex_read_at_address(struct ihex_state * const ihex, -                          ihex_address_t address); - -// Read a single character -void ihex_read_byte(struct ihex_state * const ihex, const char byte, FILE* outfile); - -// Read `count` bytes from `data` -void ihex_read_bytes(struct ihex_state * ihex, -                     const char * data, -                     ihex_count_t count, -                     FILE* outfile); - -// End reading (may call `ihex_data_read` if there is data waiting) -void ihex_end_read(struct ihex_state * const ihex, FILE* outfile); - -// Called when a complete line has been read, the record type of which is -// passed as `type`. The `ihex` structure will have its fields `data`, -// `line_length`, `address`, and `segment` set appropriately. In case -// of reading an `IHEX_EXTENDED_LINEAR_ADDRESS_RECORD` or an -// `IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD` the record's data is not -// yet parsed - it will be parsed into the `address` or `segment` field -// only if `ihex_data_read` returns `true`. This allows manual handling -// of extended addresses by parsing the `ihex->data` bytes. -// -// Possible error cases include checksum mismatch (which is indicated -// as an argument), and excessive line length (in case this has been -// compiled with `IHEX_LINE_MAX_LENGTH` less than 255) which is indicated -// by `line_length` greater than `length`. Unknown record types and -// other erroneous data is usually silently ignored by this minimalistic -// parser. (It is recommended to compute a hash over the complete data -// once received and verify that against the source.) -// -// Example implementation: -// -//      ihex_bool_t ihex_data_read(struct ihex_state *ihex, -//                                 ihex_record_type_t type, -//                                 ihex_bool_t error) { -//          error = error || (ihex->length < ihex->line_length); -//          if (type == IHEX_DATA_RECORD && !error) { -//              (void) fseek(outfile, IHEX_LINEAR_ADDRESS(ihex), SEEK_SET); -//              (void) fwrite(ihex->data, 1, ihex->length, outfile); -//          } else if (type == IHEX_END_OF_FILE_RECORD) { -//              (void) fclose(outfile); -//          } -//          return !error; -//      } -// -ihex_bool_t ihex_data_read(struct ihex_state *ihex, -                           ihex_record_type_t type, -                           ihex_bool_t checksum_mismatch, -                           FILE* outfile); - -// Begin reading at `segment`; this is required only if the initial segment -// is not specified in the input data and it is non-zero. -// -#ifndef IHEX_DISABLE_SEGMENTS -void ihex_read_at_segment(struct ihex_state *ihex, ihex_segment_t segment); -#endif - -#ifdef __cplusplus -} -#endif -#endif // !KK_IHEX_READ_H diff --git a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp index 8b47da7e5..fdb254024 100644 --- a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp +++ b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp @@ -17,8 +17,8 @@  #include "octoclock_impl.hpp"  #include "common.h" -#include "kk_ihex_read.h" +#include "../../utils/ihex.hpp"  #include <uhd/device.hpp>  #include <uhd/image_loader.hpp>  #include <uhd/transport/udp_simple.hpp> @@ -34,6 +34,8 @@  #include <boost/lexical_cast.hpp>  #include <boost/thread.hpp> +#include <algorithm> +#include <iterator>  #include <cstdio>  #include <cstring>  #include <fstream> @@ -54,83 +56,70 @@ using namespace uhd::transport;  typedef struct {      bool                        found;      uhd::device_addr_t          dev_addr; -    std::string                 given_filepath; -    std::string                 actual_filepath; // If using a .hex, this is the converted .bin -    bool                        from_hex; -    boost::uint32_t             size; +    std::string                 image_filepath;      boost::uint16_t             crc;      boost::uint16_t             num_blocks;      udp_simple::sptr            ctrl_xport;      udp_simple::sptr            fw_xport;      boost::uint8_t              data_in[udp_simple::mtu]; +    std::vector<boost::uint8_t> image;  } octoclock_session_t;  static void octoclock_calculate_crc(octoclock_session_t &session){ -    std::ifstream ifile(session.actual_filepath.c_str()); -    boost::uint8_t temp_image[OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES]; -    ifile.read((char*)temp_image, session.size); -      session.crc = 0xFFFF; -    for(size_t i = 0; i < session.size; i++){ -        session.crc ^= temp_image[i]; +    for(size_t i = 0; i < session.image.size(); i++) +    { +        session.crc ^= session.image[i];          for(boost::uint8_t j = 0; j < 8; ++j){              if(session.crc & 1) session.crc = (session.crc >> 1) ^ 0xA001;              else session.crc = (session.crc >> 1);          }      } - -    ifile.close();  } -static void octoclock_convert_ihex(octoclock_session_t &session){ -    struct ihex_state ihex; -    ihex_count_t count; -    char buf[256]; -    FILE* infile = fopen(session.given_filepath.c_str(), "r"); -    FILE* outfile = fopen(session.actual_filepath.c_str(), "w"); -    uint64_t line_number = 1; - -    ihex_begin_read(&ihex); -    while(fgets(buf, 256, infile)){ -        count = ihex_count_t(strlen(buf)); -        ihex_read_bytes(&ihex, buf, count, outfile); -        line_number += (count && buf[count - 1] == '\n'); +static void octoclock_read_bin(octoclock_session_t &session) +{ +    std::ifstream bin_file(session.image_filepath.c_str(), std::ios::in | std::ios::binary); +    if (not bin_file.is_open()) { +        throw uhd::io_error("Could not read image file.");      } -    ihex_end_read(&ihex, outfile); // Closes outfile -    (void)fclose(infile); +    size_t filesize = fs::file_size(session.image_filepath); +    session.image.clear(); +    session.image.resize(filesize); +    bin_file.read((char*)&session.image[0], filesize); +    if(size_t(bin_file.gcount()) != filesize) { +        throw uhd::io_error("Failed to read firmware image."); +    } + +    bin_file.close();  }  static void octoclock_validate_firmware_image(octoclock_session_t &session){ -    if(not fs::exists(session.given_filepath)){ +    if(not fs::exists(session.image_filepath)){          throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\"") -                                     % session.given_filepath)); +                                     % session.image_filepath));      } -    std::string extension = fs::extension(session.given_filepath); +    std::string extension = fs::extension(session.image_filepath);      if(extension == ".bin"){ -        session.actual_filepath = session.given_filepath; -        session.from_hex = false; +        octoclock_read_bin(session);      }      else if(extension == ".hex"){ -        session.actual_filepath = fs::path(fs::path(uhd::get_tmp_path()) / -                                           str(boost::format("octoclock_fw_%d.bin") -                                               % time_spec_t::get_system_time().get_full_secs()) -                                          ).string(); - -        octoclock_convert_ihex(session); -        session.from_hex = true; +        ihex_reader hex_reader(session.image_filepath); +        session.image = hex_reader.to_vector(OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES);      } -    else throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .hex or .bin."))); +    else throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .hex or .bin.") +                                      % extension)); -    session.size = fs::file_size(session.actual_filepath); -    if(session.size > OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES){ +    if(session.image.size() > OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES){          throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d") -                                     % session.size % OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES)); +                                     % session.image.size() % OCTOCLOCK_FIRMWARE_MAX_SIZE_BYTES));      } -    session.num_blocks = (session.size % OCTOCLOCK_BLOCK_SIZE) ? ((session.size / OCTOCLOCK_BLOCK_SIZE) + 1) -                                                               : (session.size / OCTOCLOCK_BLOCK_SIZE); +    session.num_blocks = (session.image.size() % OCTOCLOCK_BLOCK_SIZE) +                            ? ((session.image.size() / OCTOCLOCK_BLOCK_SIZE) + 1) +                            : (session.image.size() / OCTOCLOCK_BLOCK_SIZE);      octoclock_calculate_crc(session);  } @@ -164,14 +153,15 @@ static void octoclock_setup_session(octoclock_session_t &session,      }      session.dev_addr = devs[0]; +    session.found = true;      // If no filepath is given, use the default      if(filepath == ""){ -        session.given_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex") +        session.image_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex")                                                       % session.dev_addr.get("revision","4")                                                   ));      } -    else session.given_filepath = filepath; +    else session.image_filepath = filepath;      octoclock_validate_firmware_image(session); @@ -231,10 +221,10 @@ static void octoclock_burn(octoclock_session_t &session){      const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);      // Tell OctoClock to prepare for burn -    pkt_out.len = htonx<boost::uint16_t>(session.size); +    pkt_out.len = htonx<boost::uint16_t>(session.image.size());      size_t len = 0;      std::cout << " -- Preparing OctoClock for firmware load..." << std::flush; -    pkt_out.len = session.size; +    pkt_out.len = session.image.size();      pkt_out.crc = session.crc;      UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, PREPARE_FW_BURN_CMD, pkt_out, len, session.data_in);      if(UHD_OCTOCLOCK_PACKET_MATCHES(FW_BURN_READY_ACK, pkt_out, pkt_in, len)){ @@ -242,14 +232,10 @@ static void octoclock_burn(octoclock_session_t &session){      }      else{          std::cout << "failed." << std::endl; -        if(session.from_hex){ -            fs::remove(session.actual_filepath); -        }          throw uhd::runtime_error("Failed to prepare OctoClock for firmware load.");      }      // Start burning -    std::ifstream image(session.actual_filepath.c_str(), std::ios::binary);      for(size_t i = 0; i < session.num_blocks; i++){          pkt_out.sequence++;          pkt_out.addr = i * OCTOCLOCK_BLOCK_SIZE; @@ -260,14 +246,10 @@ static void octoclock_burn(octoclock_session_t &session){                    << std::flush;          memset(pkt_out.data, 0, OCTOCLOCK_BLOCK_SIZE); -        image.read((char*)pkt_out.data, OCTOCLOCK_BLOCK_SIZE); +        memcpy((char*)pkt_out.data, &session.image[pkt_out.addr], OCTOCLOCK_BLOCK_SIZE);          UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, FILE_TRANSFER_CMD, pkt_out, len, session.data_in);          if(not UHD_OCTOCLOCK_PACKET_MATCHES(FILE_TRANSFER_ACK, pkt_out, pkt_in, len)){ -            image.close();              std::cout << std::endl; -            if(session.from_hex){ -                fs::remove(session.actual_filepath); -            }              throw uhd::runtime_error("Failed to load firmware.");          }      } @@ -275,7 +257,6 @@ static void octoclock_burn(octoclock_session_t &session){      std::cout << str(boost::format("\r -- Loading firmware: 100%% (%d/%d blocks)")                       % session.num_blocks % session.num_blocks)                << std::endl; -    image.close();  }  static void octoclock_verify(octoclock_session_t &session){ @@ -285,7 +266,6 @@ static void octoclock_verify(octoclock_session_t &session){      const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);      size_t len = 0; -    std::ifstream image(session.actual_filepath.c_str(), std::ios::binary);      boost::uint8_t image_part[OCTOCLOCK_BLOCK_SIZE];      boost::uint16_t cmp_len = 0;      for(size_t i = 0; i < session.num_blocks; i++){ @@ -298,34 +278,22 @@ static void octoclock_verify(octoclock_session_t &session){                    << std::flush;          memset(image_part, 0, OCTOCLOCK_BLOCK_SIZE); -        image.read((char*)image_part, OCTOCLOCK_BLOCK_SIZE); -        cmp_len = image.gcount(); +        memcpy((char*)image_part, &session.image[pkt_out.addr], OCTOCLOCK_BLOCK_SIZE); +        cmp_len = std::min<size_t>(OCTOCLOCK_BLOCK_SIZE, session.image.size() - size_t(pkt_out.addr));          UHD_OCTOCLOCK_SEND_AND_RECV(session.fw_xport, READ_FW_CMD, pkt_out, len, session.data_in);          if(UHD_OCTOCLOCK_PACKET_MATCHES(READ_FW_ACK, pkt_out, pkt_in, len)){              if(memcmp(pkt_in->data, image_part, cmp_len)){                  std::cout << std::endl; -                image.close(); -                if(session.from_hex){ -                    fs::remove(session.actual_filepath); -                }                  throw uhd::runtime_error("Failed to verify OctoClock firmware.");              }          }          else{              std::cout << std::endl; -            image.close(); -            if(session.from_hex){ -                fs::remove(session.actual_filepath); -            }              throw uhd::runtime_error("Failed to verify OctoClock firmware.");          }      } -    image.close(); -    if(session.from_hex){ -        fs::remove(session.actual_filepath); -    }      std::cout << str(boost::format("\r -- Verifying firmware load: 100%% (%d/%d blocks)")                       % session.num_blocks % session.num_blocks)                << std::endl; @@ -360,7 +328,7 @@ bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loade      std::cout << boost::format("Unit: OctoClock (%s)")                   % session.dev_addr["addr"]                << std::endl; -    std::cout << "Firmware: " << session.given_filepath << std::endl; +    std::cout << "Firmware: " << session.image_filepath << std::endl;      octoclock_burn(session);      octoclock_verify(session);  | 
