Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file intelhex.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief Implementation of intelhex.h
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 8 *
Pawel Zarembski 0:01f31e923fe2 9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 10 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 11 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 12 *
Pawel Zarembski 0:01f31e923fe2 13 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 18 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 19 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 20 */
Pawel Zarembski 0:01f31e923fe2 21
Pawel Zarembski 0:01f31e923fe2 22 #include <string.h>
Pawel Zarembski 0:01f31e923fe2 23
Pawel Zarembski 0:01f31e923fe2 24 #include "intelhex.h"
Pawel Zarembski 0:01f31e923fe2 25
Pawel Zarembski 0:01f31e923fe2 26 typedef enum hex_record_t hex_record_t;
Pawel Zarembski 0:01f31e923fe2 27 enum hex_record_t {
Pawel Zarembski 0:01f31e923fe2 28 DATA_RECORD = 0,
Pawel Zarembski 0:01f31e923fe2 29 EOF_RECORD = 1,
Pawel Zarembski 0:01f31e923fe2 30 EXT_SEG_ADDR_RECORD = 2,
Pawel Zarembski 0:01f31e923fe2 31 START_SEG_ADDR_RECORD = 3,
Pawel Zarembski 0:01f31e923fe2 32 EXT_LINEAR_ADDR_RECORD = 4,
Pawel Zarembski 0:01f31e923fe2 33 START_LINEAR_ADDR_RECORD = 5
Pawel Zarembski 0:01f31e923fe2 34 };
Pawel Zarembski 0:01f31e923fe2 35
Pawel Zarembski 0:01f31e923fe2 36 typedef union hex_line_t hex_line_t;
Pawel Zarembski 0:01f31e923fe2 37 union __attribute__((packed)) hex_line_t {
Pawel Zarembski 0:01f31e923fe2 38 uint8_t buf[0x25];
Pawel Zarembski 0:01f31e923fe2 39 struct __attribute__((packed)) {
Pawel Zarembski 0:01f31e923fe2 40 uint8_t byte_count;
Pawel Zarembski 0:01f31e923fe2 41 uint16_t address;
Pawel Zarembski 0:01f31e923fe2 42 uint8_t record_type;
Pawel Zarembski 0:01f31e923fe2 43 uint8_t data[0x25 - 0x5];
Pawel Zarembski 0:01f31e923fe2 44 uint8_t checksum;
Pawel Zarembski 0:01f31e923fe2 45 };
Pawel Zarembski 0:01f31e923fe2 46 };
Pawel Zarembski 0:01f31e923fe2 47
Pawel Zarembski 0:01f31e923fe2 48 /** Swap 16bit value - let compiler figure out the best way
Pawel Zarembski 0:01f31e923fe2 49 * @param val a variable of size uint16_t to be swapped
Pawel Zarembski 0:01f31e923fe2 50 * @return the swapped value
Pawel Zarembski 0:01f31e923fe2 51 */
Pawel Zarembski 0:01f31e923fe2 52 static uint16_t swap16(uint16_t a)
Pawel Zarembski 0:01f31e923fe2 53 {
Pawel Zarembski 0:01f31e923fe2 54 return ((a & 0x00ff) << 8) | ((a & 0xff00) >> 8);
Pawel Zarembski 0:01f31e923fe2 55 }
Pawel Zarembski 0:01f31e923fe2 56
Pawel Zarembski 0:01f31e923fe2 57 /** Converts a character representation of a hex to real value.
Pawel Zarembski 0:01f31e923fe2 58 * @param c is the hex value in char format
Pawel Zarembski 0:01f31e923fe2 59 * @return the value of the hex
Pawel Zarembski 0:01f31e923fe2 60 */
Pawel Zarembski 0:01f31e923fe2 61 static uint8_t ctoh(char c)
Pawel Zarembski 0:01f31e923fe2 62 {
Pawel Zarembski 0:01f31e923fe2 63 return (c & 0x10) ? /*0-9*/ c & 0xf : /*A-F, a-f*/ (c & 0xf) + 9;
Pawel Zarembski 0:01f31e923fe2 64 }
Pawel Zarembski 0:01f31e923fe2 65
Pawel Zarembski 0:01f31e923fe2 66 /** Calculate checksum on a hex record
Pawel Zarembski 0:01f31e923fe2 67 * @param data is the line of hex record
Pawel Zarembski 0:01f31e923fe2 68 * @param size is the length of the data array
Pawel Zarembski 0:01f31e923fe2 69 * @return 1 if the data provided is a valid hex record otherwise 0
Pawel Zarembski 0:01f31e923fe2 70 */
Pawel Zarembski 0:01f31e923fe2 71 static uint8_t validate_checksum(hex_line_t *record)
Pawel Zarembski 0:01f31e923fe2 72 {
Pawel Zarembski 0:01f31e923fe2 73 uint8_t result = 0, i = 0;
Pawel Zarembski 0:01f31e923fe2 74
Pawel Zarembski 0:01f31e923fe2 75 for (; i < (record->byte_count + 5); i++) {
Pawel Zarembski 0:01f31e923fe2 76 result += record->buf[i];
Pawel Zarembski 0:01f31e923fe2 77 }
Pawel Zarembski 0:01f31e923fe2 78
Pawel Zarembski 0:01f31e923fe2 79 return (result == 0);
Pawel Zarembski 0:01f31e923fe2 80 }
Pawel Zarembski 0:01f31e923fe2 81
Pawel Zarembski 0:01f31e923fe2 82 static hex_line_t line = {0}, shadow_line = {0};
Pawel Zarembski 0:01f31e923fe2 83 static uint32_t next_address_to_write = 0;
Pawel Zarembski 0:01f31e923fe2 84 static uint8_t low_nibble = 0, idx = 0, record_processed = 0, load_unaligned_record = 0;
Pawel Zarembski 0:01f31e923fe2 85
Pawel Zarembski 0:01f31e923fe2 86 void reset_hex_parser(void)
Pawel Zarembski 0:01f31e923fe2 87 {
Pawel Zarembski 0:01f31e923fe2 88 memset(line.buf, 0, sizeof(hex_line_t));
Pawel Zarembski 0:01f31e923fe2 89 memset(shadow_line.buf, 0, sizeof(hex_line_t));
Pawel Zarembski 0:01f31e923fe2 90 next_address_to_write = 0;
Pawel Zarembski 0:01f31e923fe2 91 low_nibble = 0;
Pawel Zarembski 0:01f31e923fe2 92 idx = 0;
Pawel Zarembski 0:01f31e923fe2 93 record_processed = 0;
Pawel Zarembski 0:01f31e923fe2 94 load_unaligned_record = 0;
Pawel Zarembski 0:01f31e923fe2 95 }
Pawel Zarembski 0:01f31e923fe2 96
Pawel Zarembski 0:01f31e923fe2 97 hexfile_parse_status_t parse_hex_blob(const uint8_t *hex_blob, const uint32_t hex_blob_size, uint32_t *hex_parse_cnt, uint8_t *bin_buf, const uint32_t bin_buf_size, uint32_t *bin_buf_address, uint32_t *bin_buf_cnt)
Pawel Zarembski 0:01f31e923fe2 98 {
Pawel Zarembski 0:01f31e923fe2 99 uint8_t *end = (uint8_t *)hex_blob + hex_blob_size;
Pawel Zarembski 0:01f31e923fe2 100 hexfile_parse_status_t status = HEX_PARSE_UNINIT;
Pawel Zarembski 0:01f31e923fe2 101 // reset the amount of data that is being return'd
Pawel Zarembski 0:01f31e923fe2 102 *bin_buf_cnt = (uint32_t)0;
Pawel Zarembski 0:01f31e923fe2 103
Pawel Zarembski 0:01f31e923fe2 104 // we had an exit state where the address was unaligned to the previous record and data count.
Pawel Zarembski 0:01f31e923fe2 105 // Need to pop the last record into the buffer before decoding anthing else since it was
Pawel Zarembski 0:01f31e923fe2 106 // already decoded.
Pawel Zarembski 0:01f31e923fe2 107 if (load_unaligned_record) {
Pawel Zarembski 0:01f31e923fe2 108 // need some help...
Pawel Zarembski 0:01f31e923fe2 109 load_unaligned_record = 0;
Pawel Zarembski 0:01f31e923fe2 110 // move from line buffer back to input buffer
Pawel Zarembski 0:01f31e923fe2 111 memcpy((uint8_t *)bin_buf, (uint8_t *)line.data, line.byte_count);
Pawel Zarembski 0:01f31e923fe2 112 bin_buf += line.byte_count;
Pawel Zarembski 0:01f31e923fe2 113 *bin_buf_cnt = (uint32_t)(*bin_buf_cnt) + line.byte_count;
Pawel Zarembski 0:01f31e923fe2 114 // Store next address to write
Pawel Zarembski 0:01f31e923fe2 115 next_address_to_write = ((next_address_to_write & 0xffff0000) | line.address) + line.byte_count;
Pawel Zarembski 0:01f31e923fe2 116 }
Pawel Zarembski 0:01f31e923fe2 117
Pawel Zarembski 0:01f31e923fe2 118 while (hex_blob != end) {
Pawel Zarembski 0:01f31e923fe2 119 switch ((uint8_t)(*hex_blob)) {
Pawel Zarembski 0:01f31e923fe2 120 // we've hit the end of an ascii line
Pawel Zarembski 0:01f31e923fe2 121 // junk we dont care about could also just run the validate_checksum on &line
Pawel Zarembski 0:01f31e923fe2 122 case '\r':
Pawel Zarembski 0:01f31e923fe2 123 case '\n':
Pawel Zarembski 0:01f31e923fe2 124 //ignore new lines
Pawel Zarembski 0:01f31e923fe2 125 break;
Pawel Zarembski 0:01f31e923fe2 126
Pawel Zarembski 0:01f31e923fe2 127 // found start of a new record. reset state variables
Pawel Zarembski 0:01f31e923fe2 128 case ':':
Pawel Zarembski 0:01f31e923fe2 129 memset(line.buf, 0, sizeof(hex_line_t));
Pawel Zarembski 0:01f31e923fe2 130 low_nibble = 0;
Pawel Zarembski 0:01f31e923fe2 131 idx = 0;
Pawel Zarembski 0:01f31e923fe2 132 record_processed = 0;
Pawel Zarembski 0:01f31e923fe2 133 break;
Pawel Zarembski 0:01f31e923fe2 134
Pawel Zarembski 0:01f31e923fe2 135 // decoding lines
Pawel Zarembski 0:01f31e923fe2 136 default:
Pawel Zarembski 0:01f31e923fe2 137 if (low_nibble) {
Pawel Zarembski 0:01f31e923fe2 138 line.buf[idx] |= ctoh((uint8_t)(*hex_blob)) & 0xf;
Pawel Zarembski 0:01f31e923fe2 139 if (++idx >= (line.byte_count + 5)) { //all data in
Pawel Zarembski 0:01f31e923fe2 140 if (0 == validate_checksum(&line)) {
Pawel Zarembski 0:01f31e923fe2 141 status = HEX_PARSE_CKSUM_FAIL;
Pawel Zarembski 0:01f31e923fe2 142 goto hex_parser_exit;
Pawel Zarembski 0:01f31e923fe2 143 } else {
Pawel Zarembski 0:01f31e923fe2 144 if (!record_processed) {
Pawel Zarembski 0:01f31e923fe2 145 record_processed = 1;
Pawel Zarembski 0:01f31e923fe2 146 // address byteswap...
Pawel Zarembski 0:01f31e923fe2 147 line.address = swap16(line.address);
Pawel Zarembski 0:01f31e923fe2 148
Pawel Zarembski 0:01f31e923fe2 149 switch (line.record_type) {
Pawel Zarembski 0:01f31e923fe2 150 case DATA_RECORD:
Pawel Zarembski 0:01f31e923fe2 151 // keeping a record of the last hex record
Pawel Zarembski 0:01f31e923fe2 152 memcpy(shadow_line.buf, line.buf, sizeof(hex_line_t));
Pawel Zarembski 0:01f31e923fe2 153
Pawel Zarembski 0:01f31e923fe2 154 // verify this is a continous block of memory or need to exit and dump
Pawel Zarembski 0:01f31e923fe2 155 if (((next_address_to_write & 0xffff0000) | line.address) != next_address_to_write) {
Pawel Zarembski 0:01f31e923fe2 156 load_unaligned_record = 1;
Pawel Zarembski 0:01f31e923fe2 157 status = HEX_PARSE_UNALIGNED;
Pawel Zarembski 0:01f31e923fe2 158 goto hex_parser_exit;
Pawel Zarembski 0:01f31e923fe2 159 }
Pawel Zarembski 0:01f31e923fe2 160
Pawel Zarembski 0:01f31e923fe2 161 // move from line buffer back to input buffer
Pawel Zarembski 0:01f31e923fe2 162 memcpy(bin_buf, line.data, line.byte_count);
Pawel Zarembski 0:01f31e923fe2 163 bin_buf += line.byte_count;
Pawel Zarembski 0:01f31e923fe2 164 *bin_buf_cnt = (uint32_t)(*bin_buf_cnt) + line.byte_count;
Pawel Zarembski 0:01f31e923fe2 165 // Save next address to write
Pawel Zarembski 0:01f31e923fe2 166 next_address_to_write = ((next_address_to_write & 0xffff0000) | line.address) + line.byte_count;
Pawel Zarembski 0:01f31e923fe2 167 break;
Pawel Zarembski 0:01f31e923fe2 168
Pawel Zarembski 0:01f31e923fe2 169 case EOF_RECORD:
Pawel Zarembski 0:01f31e923fe2 170 status = HEX_PARSE_EOF;
Pawel Zarembski 0:01f31e923fe2 171 goto hex_parser_exit;
Pawel Zarembski 0:01f31e923fe2 172
Pawel Zarembski 0:01f31e923fe2 173 case EXT_SEG_ADDR_RECORD:
Pawel Zarembski 0:01f31e923fe2 174 // Could have had data in the buffer so must exit and try to program
Pawel Zarembski 0:01f31e923fe2 175 // before updating bin_buf_address with next_address_to_write
Pawel Zarembski 0:01f31e923fe2 176 memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt)));
Pawel Zarembski 0:01f31e923fe2 177 // figure the start address for the buffer before returning
Pawel Zarembski 0:01f31e923fe2 178 *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt);
Pawel Zarembski 0:01f31e923fe2 179 *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob));
Pawel Zarembski 0:01f31e923fe2 180 // update the address msb's
Pawel Zarembski 0:01f31e923fe2 181 next_address_to_write = (next_address_to_write & 0x00000000) | ((line.data[0] << 12) | (line.data[1] << 4));
Pawel Zarembski 0:01f31e923fe2 182 // Need to exit and program if buffer has been filled
Pawel Zarembski 0:01f31e923fe2 183 status = HEX_PARSE_UNALIGNED;
Pawel Zarembski 0:01f31e923fe2 184 return status;
Pawel Zarembski 0:01f31e923fe2 185
Pawel Zarembski 0:01f31e923fe2 186 case EXT_LINEAR_ADDR_RECORD:
Pawel Zarembski 0:01f31e923fe2 187 // Could have had data in the buffer so must exit and try to program
Pawel Zarembski 0:01f31e923fe2 188 // before updating bin_buf_address with next_address_to_write
Pawel Zarembski 0:01f31e923fe2 189 // Good catch Gaute!!
Pawel Zarembski 0:01f31e923fe2 190 memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt)));
Pawel Zarembski 0:01f31e923fe2 191 // figure the start address for the buffer before returning
Pawel Zarembski 0:01f31e923fe2 192 *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt);
Pawel Zarembski 0:01f31e923fe2 193 *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob));
Pawel Zarembski 0:01f31e923fe2 194 // update the address msb's
Pawel Zarembski 0:01f31e923fe2 195 next_address_to_write = (next_address_to_write & 0x00000000) | ((line.data[0] << 24) | (line.data[1] << 16));
Pawel Zarembski 0:01f31e923fe2 196 // Need to exit and program if buffer has been filled
Pawel Zarembski 0:01f31e923fe2 197 status = HEX_PARSE_UNALIGNED;
Pawel Zarembski 0:01f31e923fe2 198 return status;
Pawel Zarembski 0:01f31e923fe2 199
Pawel Zarembski 0:01f31e923fe2 200 default:
Pawel Zarembski 0:01f31e923fe2 201 break;
Pawel Zarembski 0:01f31e923fe2 202 }
Pawel Zarembski 0:01f31e923fe2 203 }
Pawel Zarembski 0:01f31e923fe2 204 }
Pawel Zarembski 0:01f31e923fe2 205 }
Pawel Zarembski 0:01f31e923fe2 206 } else {
Pawel Zarembski 0:01f31e923fe2 207 if (idx < sizeof(hex_line_t)) {
Pawel Zarembski 0:01f31e923fe2 208 line.buf[idx] = ctoh((uint8_t)(*hex_blob)) << 4;
Pawel Zarembski 0:01f31e923fe2 209 }
Pawel Zarembski 0:01f31e923fe2 210 }
Pawel Zarembski 0:01f31e923fe2 211
Pawel Zarembski 0:01f31e923fe2 212 low_nibble = !low_nibble;
Pawel Zarembski 0:01f31e923fe2 213 break;
Pawel Zarembski 0:01f31e923fe2 214 }
Pawel Zarembski 0:01f31e923fe2 215
Pawel Zarembski 0:01f31e923fe2 216 hex_blob++;
Pawel Zarembski 0:01f31e923fe2 217 }
Pawel Zarembski 0:01f31e923fe2 218
Pawel Zarembski 0:01f31e923fe2 219 // decoded an entire hex block - verify (cant do this hex_parse_cnt is figured below)
Pawel Zarembski 0:01f31e923fe2 220 //status = (hex_blob_size == (uint32_t)(*hex_parse_cnt)) ? HEX_PARSE_OK : HEX_PARSE_FAILURE;
Pawel Zarembski 0:01f31e923fe2 221 status = HEX_PARSE_OK;
Pawel Zarembski 0:01f31e923fe2 222 hex_parser_exit:
Pawel Zarembski 0:01f31e923fe2 223 memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt)));
Pawel Zarembski 0:01f31e923fe2 224 // figure the start address for the buffer before returning
Pawel Zarembski 0:01f31e923fe2 225 *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt);
Pawel Zarembski 0:01f31e923fe2 226 *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob));
Pawel Zarembski 0:01f31e923fe2 227 return status;
Pawel Zarembski 0:01f31e923fe2 228 }