mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
303 lines
6.6 KiB
C
303 lines
6.6 KiB
C
/*
|
|
* LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm
|
|
* Copyright (c) 2004, PJRC.COM, LLC, <paul@pjrc.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/* If this code fails to build, please provide at least the following
|
|
* information when requesting (free) technical support.
|
|
*
|
|
* 1: Complete copy of all messages during the build.
|
|
* 2: Output of "gtk-config --version"
|
|
* 3: Output of "gtk-config --libs"
|
|
* 4: Output of "gtk-config --cflags"
|
|
* 5: Output of "uname -a"
|
|
* 6: Version of GTK installed... eg, type: ls -l /lib/libgtk*
|
|
* 7: Other info... which linux distribution, version, other software
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
// the maximum flash image size we can support
|
|
// chips with larger memory may be used, but only this
|
|
// much intel-hex data can be loaded into memory!
|
|
#define MAX_MEMORY_SIZE 0x80000
|
|
|
|
|
|
#include "ihex.h"
|
|
|
|
|
|
static unsigned char firmware_image[MAX_MEMORY_SIZE];
|
|
static unsigned char firmware_mask[MAX_MEMORY_SIZE];
|
|
static int end_record_seen = 0;
|
|
static int byte_count;
|
|
static unsigned int extended_addr = 0;
|
|
|
|
|
|
static int parse_hex_line(char *line);
|
|
|
|
|
|
/****************************************************************/
|
|
/* */
|
|
/* Read Intel Hex File */
|
|
/* */
|
|
/****************************************************************/
|
|
|
|
|
|
|
|
int read_intel_hex(const char *filename)
|
|
{
|
|
FILE *fp;
|
|
int i, lineno = 0;
|
|
char buf[1024];
|
|
|
|
byte_count = 0;
|
|
end_record_seen = 0;
|
|
|
|
for (i = 0; i < MAX_MEMORY_SIZE; i++) {
|
|
firmware_image[i] = 0xFF;
|
|
firmware_mask[i] = 0;
|
|
}
|
|
|
|
extended_addr = 0;
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
if (fp == NULL) {
|
|
printf("Unable to read file %s\n", filename);
|
|
return -1;
|
|
}
|
|
|
|
while (!feof(fp)) {
|
|
*buf = '\0';
|
|
fgets(buf, sizeof(buf), fp);
|
|
lineno++;
|
|
|
|
if (*buf) {
|
|
if (parse_hex_line(buf) == 0) {
|
|
printf("Warning, parse error line %d\n", lineno);
|
|
fclose(fp);
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
if (end_record_seen) {
|
|
break;
|
|
}
|
|
|
|
if (feof(stdin)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return byte_count;
|
|
}
|
|
|
|
|
|
/* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */
|
|
|
|
/* parses a line of intel hex code, stores the data in bytes[] */
|
|
/* and the beginning address in addr, and returns a 1 if the */
|
|
/* line was valid, or a 0 if an error occurred. The variable */
|
|
/* num gets the number of bytes that were stored into bytes[] */
|
|
|
|
|
|
int
|
|
parse_hex_line(char *line)
|
|
{
|
|
unsigned int addr, code, num;
|
|
unsigned int sum, len, cksum, i;
|
|
char *ptr;
|
|
|
|
num = 0;
|
|
|
|
if (line[0] != ':') {
|
|
return 0;
|
|
}
|
|
|
|
if (strlen(line) < 11) {
|
|
return 0;
|
|
}
|
|
|
|
ptr = line + 1;
|
|
|
|
if (!sscanf(ptr, "%02x", &len)) {
|
|
return 0;
|
|
}
|
|
|
|
ptr += 2;
|
|
|
|
if (strlen(line) < (11 + (len * 2))) {
|
|
return 0;
|
|
}
|
|
|
|
if (!sscanf(ptr, "%04x", &addr)) {
|
|
return 0;
|
|
}
|
|
|
|
ptr += 4;
|
|
|
|
/* printf("Line: length=%d Addr=%d\n", len, addr); */
|
|
if (!sscanf(ptr, "%02x", &code)) {
|
|
return 0;
|
|
}
|
|
|
|
if (addr + extended_addr + len >= MAX_MEMORY_SIZE) {
|
|
return 0;
|
|
}
|
|
|
|
ptr += 2;
|
|
sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
|
|
|
|
if (code != 0) {
|
|
if (code == 1) {
|
|
end_record_seen = 1;
|
|
return 1;
|
|
}
|
|
|
|
if (code == 2 && 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;
|
|
}
|
|
|
|
extended_addr = i << 4;
|
|
//printf("ext addr = %05X\n", extended_addr);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
extended_addr = i << 16;
|
|
//printf("ext addr = %08X\n", extended_addr);
|
|
}
|
|
|
|
return 1; // non-data line
|
|
}
|
|
|
|
byte_count += len;
|
|
|
|
while (num != len) {
|
|
if (sscanf(ptr, "%02x", &i) != 1) {
|
|
return 0;
|
|
}
|
|
|
|
i &= 255;
|
|
firmware_image[addr + extended_addr + num] = i;
|
|
firmware_mask[addr + extended_addr + num] = 1;
|
|
ptr += 2;
|
|
sum += i;
|
|
(num)++;
|
|
|
|
if (num >= 256) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (!sscanf(ptr, "%02x", &cksum)) {
|
|
return 0;
|
|
}
|
|
|
|
if (((sum & 255) + (cksum & 255)) & 255) {
|
|
return 0; /* checksum error */
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int bytes_within_range(int begin, int end)
|
|
{
|
|
int i;
|
|
|
|
if (begin < 0 || begin >= MAX_MEMORY_SIZE ||
|
|
end < 0 || end >= MAX_MEMORY_SIZE) {
|
|
return 0;
|
|
}
|
|
|
|
for (i = begin; i <= end; i++) {
|
|
if (firmware_mask[i]) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void get_ihex_data(int addr, int len, unsigned char *bytes)
|
|
{
|
|
int i;
|
|
|
|
if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) {
|
|
for (i = 0; i < len; i++) {
|
|
bytes[i] = 255;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (firmware_mask[addr]) {
|
|
bytes[i] = firmware_image[addr];
|
|
}
|
|
else {
|
|
bytes[i] = 255;
|
|
}
|
|
|
|
addr++;
|
|
}
|
|
}
|
|
|
|
void put_ihex_data(int addr, int len, const unsigned char *bytes)
|
|
{
|
|
int i;
|
|
|
|
if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
firmware_image[addr] = bytes[i];
|
|
firmware_mask[addr] = 1;
|
|
addr++;
|
|
}
|
|
}
|