mirror of
https://github.com/adrcs/ip400.git
synced 2025-07-04 11:05:45 +03:00
added utils
This commit is contained in:
parent
a9a3f739b4
commit
a9b13d2c39
85 changed files with 9213 additions and 0 deletions
14
rpi/eeprom/docs/eepromutils/Makefile
Normal file
14
rpi/eeprom/docs/eepromutils/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Current tools are eepmake and eepdump
|
||||
|
||||
CC ?= gcc
|
||||
|
||||
all: eepmake eepdump
|
||||
|
||||
eepmake: eeptypes.h eepmake.c
|
||||
$(CC) eepmake.c -o eepmake -Wno-format
|
||||
|
||||
eepdump: eeptypes.h eepdump.c
|
||||
$(CC) eepdump.c -o eepdump -Wno-format
|
||||
|
||||
clean:
|
||||
rm -f eepmake eepdump
|
BIN
rpi/eeprom/docs/eepromutils/MaplePi.eep
Normal file
BIN
rpi/eeprom/docs/eepromutils/MaplePi.eep
Normal file
Binary file not shown.
87
rpi/eeprom/docs/eepromutils/MaplePi_Settings.txt
Normal file
87
rpi/eeprom/docs/eepromutils/MaplePi_Settings.txt
Normal file
|
@ -0,0 +1,87 @@
|
|||
########################################################################
|
||||
# EEPROM settings text file
|
||||
#
|
||||
# Edit this file for your particular board and run through eepmake tool,
|
||||
# then use eepflash tool to write to attached HAT ID EEPROM
|
||||
#
|
||||
# Tools available:
|
||||
# eepmake Parses EEPROM text file and creates binary .eep file
|
||||
# eepdump Dumps a binary .eep file as human readable text (for debug)
|
||||
# eepflash Write or read .eep binary image to/from HAT EEPROM
|
||||
#
|
||||
########################################################################
|
||||
|
||||
########################################################################
|
||||
# Vendor info
|
||||
|
||||
# 128 bit UUID. If left at zero eepmake tool will auto-generate
|
||||
# RFC 4122 compliant UUID
|
||||
product_uuid 00000000-0000-0000-0000-000000000000
|
||||
|
||||
# 16 bit product id
|
||||
product_id 0x0002
|
||||
|
||||
# 16 bit product version
|
||||
product_ver 0x0003
|
||||
|
||||
# ASCII vendor string (max 255 characters)
|
||||
vendor "Praebius Communications Inc"
|
||||
|
||||
# ASCII product string (max 255 characters)
|
||||
product "MaplePi Radio Interface"
|
||||
|
||||
|
||||
########################################################################
|
||||
# GPIO bank settings, set to nonzero to change from the default.
|
||||
# NOTE these setting can only be set per BANK, uncommenting any of
|
||||
# these will force the bank to use the custom setting.
|
||||
|
||||
# drive strength, 0=default, 1-8=2,4,6,8,10,12,14,16mA, 9-15=reserved
|
||||
gpio_drive 0
|
||||
|
||||
# 0=default, 1=slew rate limiting, 2=no slew limiting, 3=reserved
|
||||
gpio_slew 0
|
||||
|
||||
# 0=default, 1=hysteresis disabled, 2=hysteresis enabled, 3=reserved
|
||||
gpio_hysteresis 0
|
||||
|
||||
# If board back-powers Pi via 5V GPIO header pins:
|
||||
# 0 = board does not back-power
|
||||
# 1 = board back-powers and can supply the Pi with a minimum of 1.3A
|
||||
# 2 = board back-powers and can supply the Pi with a minimum of 2A
|
||||
# 3 = reserved
|
||||
# If back_power=2 then USB high current mode will be automatically
|
||||
# enabled on the Pi
|
||||
back_power 1
|
||||
|
||||
########################################################################
|
||||
# GPIO pins, uncomment for GPIOs used on board
|
||||
# Options for FUNCTION: INPUT, OUTPUT, ALT0-ALT5
|
||||
# Options for PULL: DEFAULT, UP, DOWN, NONE
|
||||
# NB GPIO0 and GPIO1 are reserved for ID EEPROM so cannot be set
|
||||
|
||||
# GPIO FUNCTION PULL
|
||||
# ---- -------- ----
|
||||
setgpio 5 OUTPUT NONE # TMS
|
||||
setgpio 6 OUTPUT NONE # TDI
|
||||
setgpio 7 ALT0 DEFAULT # SPI0_CE1
|
||||
setgpio 8 ALT0 DEFAULT # SPI0_CE0
|
||||
setgpio 9 ALT0 DEFAULT # SPI0_MISO
|
||||
setgpio 10 ALT0 DEFAULT # SPI0_MOSI
|
||||
setgpio 11 ALT0 DEFAULT # SPI0_CLK
|
||||
setgpio 12 OUTPUT NONE # TCK
|
||||
setgpio 13 INPUT NONE # TDO
|
||||
setgpio 14 ALT5 DEFAULT # TXD0
|
||||
setgpio 15 ALT5 DEFAULT # RXD0
|
||||
setgpio 16 ALT4 DEFAULT # SPI1_CE2
|
||||
setgpio 17 ALT4 DEFAULT # SPI1_CE1
|
||||
setgpio 18 ALT4 DEFAULT # SPI1_CE0
|
||||
setgpio 19 ALT4 DEFAULT # SPI1_MISO
|
||||
setgpio 20 ALT4 DEFAULT # SPI1_MOSI
|
||||
setgpio 21 ALT4 DEFAULT # SPI1_SCLK
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
12
rpi/eeprom/docs/eepromutils/README.txt
Normal file
12
rpi/eeprom/docs/eepromutils/README.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
Utilities to create, flash and dump HAT EEPROM images.
|
||||
|
||||
Edit eeprom_setting.txt for your particular board and run through
|
||||
eepmake tool, then use eepflash tool to write to attached HAT ID EEPROM
|
||||
|
||||
Tools available:
|
||||
|
||||
eepmake: Parses EEPROM text file and creates binary .eep file
|
||||
|
||||
eepdump: Dumps a binary .eep file as human readable text (for debug)
|
||||
|
||||
eepflash: Write or read .eep binary image to/from HAT EEPROM
|
BIN
rpi/eeprom/docs/eepromutils/blank.eep
Normal file
BIN
rpi/eeprom/docs/eepromutils/blank.eep
Normal file
Binary file not shown.
BIN
rpi/eeprom/docs/eepromutils/eepdump
Normal file
BIN
rpi/eeprom/docs/eepromutils/eepdump
Normal file
Binary file not shown.
230
rpi/eeprom/docs/eepromutils/eepdump.c
Normal file
230
rpi/eeprom/docs/eepromutils/eepdump.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "eeptypes.h"
|
||||
|
||||
struct header_t header;
|
||||
struct atom_t atom;
|
||||
struct vendor_info_d vinf;
|
||||
struct gpio_map_d gpiomap;
|
||||
unsigned char* data;
|
||||
|
||||
int read_bin(char *in, char *outf) {
|
||||
|
||||
uint16_t crc;
|
||||
FILE *fp, *out;
|
||||
int i,j;
|
||||
|
||||
fp=fopen(in, "r");
|
||||
if (!fp) {
|
||||
printf("Error reading file %s\n", in);
|
||||
return -1;
|
||||
}
|
||||
|
||||
out=fopen(outf, "w");
|
||||
if (!out) {
|
||||
printf("Error writing file %s\n", outf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!fread(&header, sizeof(header), 1, fp)) goto err;
|
||||
|
||||
fprintf(out, "# ---------- Dump generated by eepdump handling format version 0x%02x ----------\n#\n", FORMAT_VERSION);
|
||||
|
||||
if (FORMAT_VERSION!=header.ver) fprintf(out, "# WARNING: format version mismatch!!!\n");
|
||||
|
||||
fprintf(out, "# --Header--\n# signature=0x%08x\n# version=0x%02x\n# reserved=%u\n# numatoms=%u\n# eeplen=%u\n# ----------\n\n\n", header.signature, header.ver, header.res, header.numatoms, header.eeplen);
|
||||
|
||||
|
||||
for (i = 0; i<header.numatoms; i++) {
|
||||
|
||||
if (!fread(&atom, ATOM_SIZE-CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
printf("Reading atom %d...\n", i);
|
||||
|
||||
fprintf(out, "# Start of atom #%u of type 0x%04x and length %u\n", atom.count, atom.type, atom.dlen);
|
||||
|
||||
if (atom.count != i) {
|
||||
printf("Error: atom count mismatch\n");
|
||||
fprintf(out, "# Error: atom count mismatch\n");
|
||||
}
|
||||
|
||||
long pos = ftell(fp);
|
||||
char *atom_data = (char *) malloc(atom.dlen + ATOM_SIZE-CRC_SIZE);
|
||||
memcpy(atom_data, &atom, ATOM_SIZE-CRC_SIZE);
|
||||
if (!fread(atom_data+ATOM_SIZE-CRC_SIZE, atom.dlen, 1, fp)) goto err;
|
||||
uint16_t calc_crc = getcrc(atom_data, atom.dlen-CRC_SIZE+ATOM_SIZE-CRC_SIZE);
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
|
||||
if (atom.type==ATOM_VENDOR_TYPE) {
|
||||
//decode vendor info
|
||||
|
||||
if (!fread(&vinf, VENDOR_SIZE, 1, fp)) goto err;
|
||||
|
||||
fprintf(out, "# Vendor info\n");
|
||||
fprintf(out, "product_uuid %08x-%04x-%04x-%04x-%04x%08x\n", vinf.serial_4, vinf.serial_3>>16, vinf.serial_3 & 0xffff, vinf.serial_2>>16, vinf.serial_2 & 0xffff, vinf.serial_1);
|
||||
fprintf(out, "product_id 0x%04x\n", vinf.pid);
|
||||
fprintf(out, "product_ver 0x%04x\n", vinf.pver);
|
||||
|
||||
vinf.vstr = (char *) malloc(vinf.vslen+1);
|
||||
vinf.pstr = (char *) malloc(vinf.pslen+1);
|
||||
|
||||
if (!fread(vinf.vstr, vinf.vslen, 1, fp)) goto err;
|
||||
if (!fread(vinf.pstr, vinf.pslen, 1, fp)) goto err;
|
||||
//close strings
|
||||
vinf.vstr[vinf.vslen] = 0;
|
||||
vinf.pstr[vinf.pslen] = 0;
|
||||
|
||||
fprintf(out, "vendor \"%s\" # length=%u\n", vinf.vstr, vinf.vslen);
|
||||
fprintf(out, "product \"%s\" # length=%u\n", vinf.pstr, vinf.pslen);
|
||||
|
||||
if (!fread(&crc, CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
} else if (atom.type==ATOM_GPIO_TYPE) {
|
||||
//decode GPIO map
|
||||
if (!fread(&gpiomap, GPIO_SIZE, 1, fp)) goto err;
|
||||
|
||||
fprintf(out, "# GPIO map info\n");
|
||||
fprintf(out, "gpio_drive %d\n", gpiomap.flags & 15); //1111
|
||||
fprintf(out, "gpio_slew %d\n", (gpiomap.flags & 48)>>4); //110000
|
||||
fprintf(out, "gpio_hysteresis %d\n", (gpiomap.flags & 192)>>6); //11000000
|
||||
fprintf(out, "back_power %d\n", gpiomap.power);
|
||||
fprintf(out, "# GPIO FUNCTION PULL\n# ---- -------- ----\n");
|
||||
|
||||
for (j = 0; j<28; j++) {
|
||||
if (gpiomap.pins[j] & (1<<7)) {
|
||||
//board uses this pin
|
||||
|
||||
char *pull_str = "INVALID";
|
||||
switch ((gpiomap.pins[j] & 96)>>5) { //1100000
|
||||
case 0: pull_str = "DEFAULT";
|
||||
break;
|
||||
case 1: pull_str = "UP";
|
||||
break;
|
||||
case 2: pull_str = "DOWN";
|
||||
break;
|
||||
case 3: pull_str = "NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
char *func_str = "INVALID";
|
||||
switch ((gpiomap.pins[j] & 7)) { //111
|
||||
case 0: func_str = "INPUT";
|
||||
break;
|
||||
case 1: func_str = "OUTPUT";
|
||||
break;
|
||||
case 4: func_str = "ALT0";
|
||||
break;
|
||||
case 5: func_str = "ALT1";
|
||||
break;
|
||||
case 6: func_str = "ALT2";
|
||||
break;
|
||||
case 7: func_str = "ALT3";
|
||||
break;
|
||||
case 3: func_str = "ALT4";
|
||||
break;
|
||||
case 2: func_str = "ALT5";
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(out, "setgpio %d %s %s\n", j, func_str, pull_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fread(&crc, CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
} else if (atom.type==ATOM_DT_TYPE) {
|
||||
//decode DT blob
|
||||
|
||||
fprintf(out, "dt_blob");
|
||||
data = (char *) malloc(atom.dlen-CRC_SIZE);
|
||||
if (!fread(data, atom.dlen-CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
for (j = 0; j<atom.dlen-CRC_SIZE; j++) {
|
||||
if (j % 16 == 0) fprintf(out, "\n");
|
||||
fprintf(out, "%02X ", *(data+j));
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
|
||||
if (!fread(&crc, CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
} else if (atom.type==ATOM_CUSTOM_TYPE) {
|
||||
//decode custom data
|
||||
|
||||
fprintf(out, "custom_data");
|
||||
data = (char *) malloc(atom.dlen-CRC_SIZE);
|
||||
if (!fread(data, atom.dlen-CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
for (j = 0; j<atom.dlen-CRC_SIZE; j++) {
|
||||
if (j % 16 == 0) fprintf(out, "\n");
|
||||
fprintf(out, "%02X ", *(data+j));
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
|
||||
if (!fread(&crc, CRC_SIZE, 1, fp)) goto err;
|
||||
|
||||
|
||||
} else {
|
||||
printf("Error: unrecognised atom type\n");
|
||||
fprintf(out, "# Error: unrecognised atom type\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
fprintf(out, "# End of atom. CRC16=0x%04x\n", crc);
|
||||
|
||||
if (calc_crc != crc) {
|
||||
printf("Error: atom CRC16 mismatch\n");
|
||||
fprintf(out, "# Error: atom CRC16 mismatch. Calculated CRC16=0x%02x", crc);
|
||||
} else printf("CRC OK\n");
|
||||
|
||||
fprintf(out, "\n\n");
|
||||
|
||||
}
|
||||
|
||||
//Total length checks. We need header.eeplen=current_position=file_length.
|
||||
long pos = ftell(fp);
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
|
||||
if (pos!=ftell(fp)) printf("Warning: Dump finished before EOF\n");
|
||||
if (pos!=header.eeplen) printf("Warning: Dump finished before length specified in header\n");
|
||||
if (ftell(fp)!=header.eeplen) printf("Warning: EOF does not match length specified in header\n");
|
||||
|
||||
printf("Done.\n");
|
||||
|
||||
fclose(fp);
|
||||
fclose(out);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printf("Unexpected EOF or error occurred\n");
|
||||
fclose(fp);
|
||||
fclose(out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (argc<3) {
|
||||
printf("Wrong input format.\n");
|
||||
printf("Try 'eepdump input_file output_file'\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ret = read_bin(argv[1], argv[2]);
|
||||
if (ret) {
|
||||
printf("Error reading input, aborting\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
171
rpi/eeprom/docs/eepromutils/eepflash.sh
Normal file
171
rpi/eeprom/docs/eepromutils/eepflash.sh
Normal file
|
@ -0,0 +1,171 @@
|
|||
#!/bin/sh
|
||||
|
||||
MODE="NOT_SET"
|
||||
FILE="NOT_SET"
|
||||
TYPE="NOT_SET"
|
||||
BUS="NOT_SET"
|
||||
ADDR="NOT_SET"
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "eepflash: Writes or reads .eep binary image to/from HAT EEPROM on a Raspberry Pi"
|
||||
echo ""
|
||||
echo "./eepflash.sh"
|
||||
echo " -h --help: display this help message"
|
||||
echo " -r --read: read .eep from the eeprom"
|
||||
echo " -w --write: write .eep to the eeprom"
|
||||
echo " -f=file_name --file=file_name: binary .eep file to read to/from"
|
||||
echo " -d= --device= i2c bus number (ex if the eeprom is on i2c-0 set -d=0)"
|
||||
echo " -a= --address= i2c eeprom address"
|
||||
echo " -t=eeprom_type --type=eeprom_type: eeprom type to use"
|
||||
echo " We support the following eeprom types:"
|
||||
echo " -24c32"
|
||||
echo " -24c64"
|
||||
echo " -24c128"
|
||||
echo " -24c256"
|
||||
echo " -24c512"
|
||||
echo " -24c1024"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo "./eepflash -w -f=crex0.1.eep -t=24c32 -d=1 -a=57"
|
||||
echo "./eepflash -r -f=dump.eep -t=24c32 -d=1 -a=57"
|
||||
echo ""
|
||||
}
|
||||
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "This script must be run as root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
PARAM=`echo $1 | awk -F= '{print $1}'`
|
||||
VALUE=`echo $1 | awk -F= '{print $2}'`
|
||||
case $PARAM in
|
||||
-h | --help)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
-r | --read)
|
||||
MODE="read"
|
||||
;;
|
||||
-w | --write)
|
||||
MODE="write"
|
||||
;;
|
||||
-t | --type)
|
||||
if [ "$VALUE" = "24c32" ] || [ "$VALUE" = "24c64" ] || [ "$VALUE" = "24c128" ] ||
|
||||
[ "$VALUE" = "24c256" ] || [ "$VALUE" = "24c512" ] || [ "$VALUE" = "24c1024" ]; then
|
||||
TYPE=$VALUE
|
||||
else
|
||||
echo "ERROR: Unrecognised eeprom type. Try -h for help"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-d | --device)
|
||||
BUS=$VALUE
|
||||
;;
|
||||
-a | --address)
|
||||
ADDR=$VALUE
|
||||
;;
|
||||
-f | --file)
|
||||
FILE=$VALUE
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown parameter \"$PARAM\""
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$MODE" = "NOT_SET" ]; then
|
||||
echo "You need to set mode (read or write). Try -h for help."
|
||||
exit 1
|
||||
elif [ "$FILE" = "NOT_SET" ]; then
|
||||
echo "You need to set binary .eep file to read to/from. Try -h for help."
|
||||
exit 1
|
||||
elif [ "$TYPE" = "NOT_SET" ]; then
|
||||
echo "You need to set eeprom type. Try -h for help."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "This will attempt to talk to an eeprom at i2c address 0x$ADDR on bus $BUS. Make sure there is an eeprom at this address."
|
||||
echo "This script comes with ABSOLUTELY no warranty. Continue only if you know what you are doing."
|
||||
|
||||
while true; do
|
||||
read -p "Do you wish to continue? (yes/no): " yn
|
||||
case $yn in
|
||||
yes | Yes ) break;;
|
||||
no | No ) exit;;
|
||||
* ) echo "Please type yes or no.";;
|
||||
esac
|
||||
done
|
||||
|
||||
modprobe i2c_dev
|
||||
if [ "$BUS" = "NOT_SET" ]; then
|
||||
if [ -e "/dev/i2c-0" ]; then
|
||||
BUS=0
|
||||
elif [ -e "/dev/i2c-10" ]; then
|
||||
BUS=10
|
||||
else
|
||||
dtoverlay i2c-gpio i2c_gpio_sda=0 i2c_gpio_scl=1 bus=10
|
||||
rc=$?
|
||||
if [ $rc != 0 ]; then
|
||||
echo "Loading of i2c-gpio dtoverlay failed. Do an rpi-update (and maybe apt-get update; apt-get upgrade)."
|
||||
exit $rc
|
||||
fi
|
||||
if [ -e "/dev/i2c-10" ]; then
|
||||
BUS=10
|
||||
else
|
||||
echo "Expected I2C bus (i2c-10) not found."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$ADDR" = "NOT_SET" ]; then
|
||||
ADDR=50
|
||||
fi
|
||||
|
||||
modprobe at24
|
||||
|
||||
rc=$?
|
||||
if [ $rc != 0 ]; then
|
||||
echo "Modprobe of at24 failed. Do an rpi-update."
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
SYS=/sys/class/i2c-adapter/i2c-$BUS
|
||||
|
||||
if [ ! -d "$SYS/$BUS-00$ADDR" ]; then
|
||||
echo "$TYPE 0x$ADDR" > $SYS/new_device
|
||||
fi
|
||||
|
||||
DD_VERSION=$(dd --version | grep coreutils | sed -e 's/\.//' | cut -d' ' -f 3)
|
||||
if [ $DD_VERSION -ge 824 ]
|
||||
then
|
||||
DD_STATUS="progress"
|
||||
else
|
||||
DD_STATUS="none"
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "write" ]
|
||||
then
|
||||
echo "Writing..."
|
||||
dd if=$FILE of=$SYS/$BUS-00$ADDR/eeprom status=$DD_STATUS
|
||||
rc=$?
|
||||
elif [ "$MODE" = "read" ]
|
||||
then
|
||||
echo "Reading..."
|
||||
dd if=$SYS/$BUS-00$ADDR/eeprom of=$FILE status=$DD_STATUS
|
||||
rc=$?
|
||||
fi
|
||||
|
||||
echo "Closing EEPROM Device."
|
||||
echo "0x$ADDR" > $SYS/delete_device
|
||||
|
||||
if [ $rc != 0 ]; then
|
||||
echo "Error doing I/O operation."
|
||||
exit $rc
|
||||
else
|
||||
echo "Done."
|
||||
fi
|
BIN
rpi/eeprom/docs/eepromutils/eepmake
Normal file
BIN
rpi/eeprom/docs/eepromutils/eepmake
Normal file
Binary file not shown.
620
rpi/eeprom/docs/eepromutils/eepmake.c
Normal file
620
rpi/eeprom/docs/eepromutils/eepmake.c
Normal file
|
@ -0,0 +1,620 @@
|
|||
/*
|
||||
* Parses EEPROM text file and createds binary .eep file
|
||||
* Usage: eepmake input_file output_file
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "eeptypes.h"
|
||||
|
||||
#define HEADER_SIGN 0x69502d52 //"R-Pi" in ASCII reversed for endianness
|
||||
|
||||
//todo: larger initial mallocs
|
||||
|
||||
struct header_t header;
|
||||
struct atom_t *custom_atom, vinf_atom, gpio_atom, dt_atom;
|
||||
struct vendor_info_d* vinf;
|
||||
struct gpio_map_d* gpiomap;
|
||||
|
||||
bool product_serial_set, product_id_set, product_ver_set, vendor_set, product_set,
|
||||
gpio_drive_set, gpio_slew_set, gpio_hysteresis_set, gpio_power_set;
|
||||
|
||||
bool data_receive, has_dt, receive_dt;
|
||||
|
||||
char **data;
|
||||
char *current_atom; //rearranged to write out
|
||||
unsigned int data_len, custom_ct, total_size, data_cap, custom_cap;
|
||||
|
||||
|
||||
int write_binary(char* out) {
|
||||
FILE *fp;
|
||||
int i, offset;
|
||||
short crc;
|
||||
|
||||
fp=fopen(out, "wb");
|
||||
if (!fp) {
|
||||
printf("Error writing file %s\n", out);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fwrite(&header, sizeof(header), 1, fp);
|
||||
|
||||
|
||||
current_atom = (char *) malloc(vinf_atom.dlen+ATOM_SIZE-CRC_SIZE);
|
||||
offset = 0;
|
||||
//vendor information atom first part
|
||||
memcpy(current_atom, &vinf_atom, ATOM_SIZE-CRC_SIZE);
|
||||
offset += ATOM_SIZE-2;
|
||||
//data first part
|
||||
memcpy(current_atom+offset, vinf_atom.data, VENDOR_SIZE);
|
||||
offset += VENDOR_SIZE;
|
||||
//data strings
|
||||
memcpy(current_atom+offset, vinf->vstr, vinf->vslen);
|
||||
offset += vinf->vslen;
|
||||
memcpy(current_atom+offset, vinf->pstr, vinf->pslen);
|
||||
offset += vinf->pslen;
|
||||
//vinf last part
|
||||
crc = getcrc(current_atom, offset);
|
||||
memcpy(current_atom+offset, &crc, CRC_SIZE);
|
||||
offset += CRC_SIZE;
|
||||
|
||||
fwrite(current_atom, offset, 1, fp);
|
||||
free(current_atom);
|
||||
|
||||
current_atom = (char *) malloc(gpio_atom.dlen+ATOM_SIZE-CRC_SIZE);
|
||||
offset = 0;
|
||||
//GPIO map first part
|
||||
memcpy(current_atom, &gpio_atom, ATOM_SIZE-CRC_SIZE);
|
||||
offset += ATOM_SIZE-CRC_SIZE;
|
||||
//GPIO data
|
||||
memcpy(current_atom+offset, gpiomap, GPIO_SIZE);
|
||||
offset += GPIO_SIZE;
|
||||
//GPIO map last part
|
||||
crc = getcrc(current_atom, offset);
|
||||
memcpy(current_atom+offset, &crc, CRC_SIZE);
|
||||
offset += CRC_SIZE;
|
||||
|
||||
fwrite(current_atom, offset, 1, fp);
|
||||
free(current_atom);
|
||||
|
||||
if (has_dt) {
|
||||
printf("Writing out DT...\n");
|
||||
current_atom = (char *) malloc(dt_atom.dlen+ATOM_SIZE-CRC_SIZE);
|
||||
offset = 0;
|
||||
|
||||
memcpy(current_atom, &dt_atom, ATOM_SIZE-CRC_SIZE);
|
||||
offset += ATOM_SIZE-CRC_SIZE;
|
||||
|
||||
memcpy(current_atom+offset, dt_atom.data, dt_atom.dlen-CRC_SIZE);
|
||||
offset += dt_atom.dlen-CRC_SIZE;
|
||||
|
||||
crc = getcrc(current_atom, offset);
|
||||
memcpy(current_atom+offset, &crc, CRC_SIZE);
|
||||
offset += CRC_SIZE;
|
||||
|
||||
fwrite(current_atom, offset, 1, fp);
|
||||
free(current_atom);
|
||||
}
|
||||
|
||||
for (i = 0; i<custom_ct; i++) {
|
||||
custom_atom[i].count-=!has_dt;
|
||||
|
||||
current_atom = (char *) malloc(custom_atom[i].dlen+ATOM_SIZE-CRC_SIZE);
|
||||
offset = 0;
|
||||
|
||||
memcpy(current_atom, &custom_atom[i], ATOM_SIZE-CRC_SIZE);
|
||||
offset += ATOM_SIZE-CRC_SIZE;
|
||||
|
||||
memcpy(current_atom+offset, custom_atom[i].data, custom_atom[i].dlen-CRC_SIZE);
|
||||
offset += custom_atom[i].dlen-CRC_SIZE;
|
||||
|
||||
crc = getcrc(current_atom, offset);
|
||||
memcpy(current_atom+offset, &crc, CRC_SIZE);
|
||||
offset += CRC_SIZE;
|
||||
|
||||
fwrite(current_atom, offset, 1, fp);
|
||||
free(current_atom);
|
||||
}
|
||||
|
||||
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void parse_data(char* c) {
|
||||
int k;
|
||||
char s;
|
||||
char* i = c;
|
||||
char* j = c;
|
||||
while(*j != '\0')
|
||||
{
|
||||
*i = *j++;
|
||||
if(isxdigit(*i))
|
||||
i++;
|
||||
}
|
||||
*i = '\0';
|
||||
|
||||
int len = strlen(c);
|
||||
if (len % 2 != 0) {
|
||||
printf("Error: data must have an even number of hex digits\n");
|
||||
} else {
|
||||
for (k = 0; k<len/2; k++) {
|
||||
//read a byte at a time
|
||||
s = *(c+2);
|
||||
*(c+2)='\0';
|
||||
|
||||
if (data_len==data_cap) {
|
||||
data_cap *=2;
|
||||
*data = (char *) realloc(*data, data_cap);
|
||||
}
|
||||
|
||||
sscanf(c, "%2x", *data+data_len++);
|
||||
|
||||
*(c+2) = s;
|
||||
c+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void finish_data() {
|
||||
if (data_receive) {
|
||||
*data = (char *) realloc(*data, data_len);
|
||||
|
||||
total_size+=ATOM_SIZE+data_len;
|
||||
|
||||
if (receive_dt) {
|
||||
dt_atom.type = ATOM_DT_TYPE;
|
||||
dt_atom.count = ATOM_DT_NUM;
|
||||
dt_atom.dlen = data_len+CRC_SIZE;
|
||||
} else {
|
||||
//finish atom description
|
||||
custom_atom[custom_ct].type = ATOM_CUSTOM_TYPE;
|
||||
custom_atom[custom_ct].count = 3+custom_ct;
|
||||
custom_atom[custom_ct].dlen = data_len+CRC_SIZE;
|
||||
|
||||
custom_ct++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void parse_command(char* cmd, char* c) {
|
||||
int val;
|
||||
uint32_t high1, high2;
|
||||
char *fn, *pull;
|
||||
char pin;
|
||||
bool valid;
|
||||
bool continue_data=false;
|
||||
|
||||
/* Vendor info related part */
|
||||
if (strcmp(cmd, "product_uuid")==0) {
|
||||
product_serial_set = true; //required field
|
||||
high1 = 0; high2 = 0;
|
||||
|
||||
sscanf(c, "%100s %08x-%04x-%04x-%04x-%04x%08x\n", cmd, &vinf->serial_4,
|
||||
&high1, &vinf->serial_3, &high2, &vinf->serial_2, &vinf->serial_1);
|
||||
|
||||
vinf->serial_3 |= high1<<16;
|
||||
vinf->serial_2 |= high2<<16;
|
||||
|
||||
if ((vinf->serial_4==0) && (vinf->serial_3==0) && (vinf->serial_2==0) && (vinf->serial_1==0)) {
|
||||
//read 128 random bits from /dev/urandom
|
||||
int random_file = open("/dev/urandom", O_RDONLY);
|
||||
ssize_t result = read(random_file, &vinf->serial_1, 16);
|
||||
close(random_file);
|
||||
if (result <= 0) printf("Unable to read from /dev/urandom to set up UUID");
|
||||
else {
|
||||
//put in the version
|
||||
vinf->serial_3 = (vinf->serial_3 & 0xffff0fff) | 0x00004000;
|
||||
|
||||
//put in the variant
|
||||
vinf->serial_2 = (vinf->serial_2 & 0x3fffffff) | 0x80000000;
|
||||
|
||||
printf("UUID=%08x-%04x-%04x-%04x-%04x%08x\n", vinf->serial_4, vinf->serial_3>>16, vinf->serial_3 & 0xffff, vinf->serial_2>>16, vinf->serial_2 & 0xffff, vinf->serial_1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd, "product_id")==0) {
|
||||
product_id_set = true; //required field
|
||||
sscanf(c, "%100s %hx", cmd, &vinf->pid);
|
||||
|
||||
} else if (strcmp(cmd, "product_ver")==0) {
|
||||
product_ver_set = true; //required field
|
||||
sscanf(c, "%100s %hx", cmd, &vinf->pver);
|
||||
|
||||
} else if (strcmp(cmd, "vendor")==0) {
|
||||
vendor_set = true; //required field
|
||||
|
||||
vinf->vstr = (char*) malloc (256);
|
||||
sscanf(c, "%100s \"%255[^\"]\"", cmd, vinf->vstr);
|
||||
|
||||
total_size-=vinf->vslen;
|
||||
vinf_atom.dlen-=vinf->vslen;
|
||||
|
||||
vinf->vslen = strlen(vinf->vstr);
|
||||
|
||||
total_size+=vinf->vslen;
|
||||
vinf_atom.dlen+=vinf->vslen;
|
||||
|
||||
} else if (strcmp(cmd, "product")==0) {
|
||||
product_set = true; //required field
|
||||
|
||||
vinf->pstr = (char*) malloc (256);
|
||||
sscanf(c, "%100s \"%255[^\"]\"", cmd, vinf->pstr);
|
||||
|
||||
total_size-=vinf->pslen;
|
||||
vinf_atom.dlen-=vinf->pslen;
|
||||
|
||||
vinf->pslen = strlen(vinf->pstr);
|
||||
|
||||
total_size+=vinf->pslen;
|
||||
vinf_atom.dlen+=vinf->pslen;
|
||||
}
|
||||
|
||||
/* GPIO map related part */
|
||||
else if (strcmp(cmd, "gpio_drive")==0) {
|
||||
gpio_drive_set = true; //required field
|
||||
|
||||
sscanf(c, "%100s %1x", cmd, &val);
|
||||
if (val>8 || val<0) printf("Warning: gpio_drive property in invalid region, using default value instead\n");
|
||||
else gpiomap->flags |= val;
|
||||
|
||||
|
||||
} else if (strcmp(cmd, "gpio_slew")==0) {
|
||||
gpio_slew_set = true; //required field
|
||||
|
||||
sscanf(c, "%100s %1x", cmd, &val);
|
||||
|
||||
if (val>2 || val<0) printf("Warning: gpio_slew property in invalid region, using default value instead\n");
|
||||
else gpiomap->flags |= val<<4;
|
||||
|
||||
} else if (strcmp(cmd, "gpio_hysteresis")==0) {
|
||||
gpio_hysteresis_set = true; //required field
|
||||
|
||||
sscanf(c, "%100s %1x", cmd, &val);
|
||||
|
||||
if (val>2 || val<0) printf("Warning: gpio_hysteresis property in invalid region, using default value instead\n");
|
||||
else gpiomap->flags |= val<<6;
|
||||
|
||||
} else if (strcmp(cmd, "back_power")==0) {
|
||||
gpio_power_set = true; //required field
|
||||
|
||||
sscanf(c, "%100s %1x", cmd, &val);
|
||||
|
||||
if (val>2 || val<0) printf("Warning: back_power property in invalid region, using default value instead\n");
|
||||
else gpiomap->power = val;
|
||||
|
||||
} else if (strcmp(cmd, "setgpio")==0) {
|
||||
fn = (char*) malloc (101);
|
||||
pull = (char*) malloc (101);
|
||||
|
||||
sscanf(c, "%100s %d %100s %100s", cmd, &val, fn, pull);
|
||||
|
||||
if (val<GPIO_MIN || val>=GPIO_COUNT) printf("Error: GPIO number out of bounds\n");
|
||||
else {
|
||||
valid = true;
|
||||
pin = 0;
|
||||
|
||||
if (strcmp(fn, "INPUT")==0) {
|
||||
//no action
|
||||
} else if (strcmp(fn, "OUTPUT")==0) {
|
||||
pin |= 1;
|
||||
} else if (strcmp(fn, "ALT0")==0) {
|
||||
pin |= 4;
|
||||
} else if (strcmp(fn, "ALT1")==0) {
|
||||
pin |= 5;
|
||||
} else if (strcmp(fn, "ALT2")==0) {
|
||||
pin |= 6;
|
||||
} else if (strcmp(fn, "ALT3")==0) {
|
||||
pin |= 7;
|
||||
} else if (strcmp(fn, "ALT4")==0) {
|
||||
pin |= 3;
|
||||
} else if (strcmp(fn, "ALT5")==0) {
|
||||
pin |= 2;
|
||||
} else {
|
||||
printf("Error at setgpio: function type not recognised\n");
|
||||
valid=false;
|
||||
}
|
||||
|
||||
if (strcmp(pull, "DEFAULT")==0) {
|
||||
//no action
|
||||
} else if (strcmp(pull, "UP")==0) {
|
||||
pin |= 1<<5;
|
||||
} else if (strcmp(pull, "DOWN")==0) {
|
||||
pin |= 2<<5;
|
||||
} else if (strcmp(pull, "NONE")==0) {
|
||||
pin |= 3<<5;
|
||||
} else {
|
||||
printf("Error at setgpio: pull type not recognised\n");
|
||||
valid=false;
|
||||
}
|
||||
|
||||
pin |= 1<<7; //board uses this pin
|
||||
|
||||
if (valid) gpiomap->pins[val] = pin;
|
||||
}
|
||||
}
|
||||
|
||||
/* DT atom related part */
|
||||
else if (strcmp(cmd, "dt_blob")==0) {
|
||||
finish_data();
|
||||
|
||||
has_dt = true;
|
||||
c+=strlen("dt_blob");
|
||||
|
||||
receive_dt=true;
|
||||
data_receive=true;
|
||||
|
||||
data_len = 0;
|
||||
data_cap = 4;
|
||||
data = &dt_atom.data;
|
||||
*data = (char *) malloc(data_cap);
|
||||
|
||||
parse_data(c);
|
||||
continue_data = true;
|
||||
|
||||
}
|
||||
|
||||
/* Custom data related part */
|
||||
else if (strcmp(cmd, "custom_data")==0) {
|
||||
finish_data();
|
||||
|
||||
c+=strlen("custom_data");
|
||||
|
||||
if (custom_cap == custom_ct) {
|
||||
custom_cap *= 2;
|
||||
custom_atom = (struct atom_t*) realloc(custom_atom, custom_cap * sizeof(struct atom_t));
|
||||
}
|
||||
|
||||
receive_dt=false;
|
||||
data_receive=true;
|
||||
|
||||
data_len = 0;
|
||||
data_cap = 4;
|
||||
data = &custom_atom[custom_ct].data;
|
||||
*data = (char *) malloc(data_cap);
|
||||
|
||||
parse_data(c);
|
||||
continue_data = true;
|
||||
|
||||
} else if (strcmp(cmd, "end") ==0) {
|
||||
//close last data atom
|
||||
continue_data=false;
|
||||
}
|
||||
/* Incoming data */
|
||||
else if (data_receive) {
|
||||
parse_data(c);
|
||||
continue_data = true;
|
||||
}
|
||||
|
||||
|
||||
if (!continue_data) finish_data();
|
||||
|
||||
}
|
||||
|
||||
int read_text(char* in) {
|
||||
FILE * fp;
|
||||
char * line = NULL;
|
||||
char * c = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
char *comment = NULL;
|
||||
int atomct = 2;
|
||||
int linect = 0;
|
||||
char * command = (char*) malloc (101);
|
||||
int i;
|
||||
|
||||
has_dt = false;
|
||||
|
||||
printf("Opening file %s for read\n", in);
|
||||
|
||||
fp = fopen(in, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Error opening input file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//allocating memory and setting up required atoms
|
||||
custom_cap = 1;
|
||||
custom_atom = (struct atom_t*) malloc(sizeof(struct atom_t) * custom_cap);
|
||||
|
||||
total_size=ATOM_SIZE*2+HEADER_SIZE+VENDOR_SIZE+GPIO_SIZE;
|
||||
|
||||
vinf_atom.type = ATOM_VENDOR_TYPE;
|
||||
vinf_atom.count = ATOM_VENDOR_NUM;
|
||||
vinf = (struct vendor_info_d *) calloc(1, sizeof(struct vendor_info_d));
|
||||
vinf_atom.data = (char *)vinf;
|
||||
vinf_atom.dlen = VENDOR_SIZE + CRC_SIZE;
|
||||
|
||||
gpio_atom.type = ATOM_GPIO_TYPE;
|
||||
gpio_atom.count = ATOM_GPIO_NUM;
|
||||
gpiomap = (struct gpio_map_d *) calloc(1, sizeof(struct gpio_map_d));
|
||||
gpio_atom.data = (char *)gpiomap;
|
||||
gpio_atom.dlen = GPIO_SIZE + CRC_SIZE;
|
||||
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
linect++;
|
||||
c = line;
|
||||
|
||||
for (i=0; i<read; i++) if (c[i]=='#') c[i]='\0';
|
||||
|
||||
while (isspace(*c)) ++c;
|
||||
|
||||
|
||||
if (*c=='\0' || *c=='\n' || *c=='\r') {
|
||||
//empty line, do nothing
|
||||
} else if (isalnum (*c)) {
|
||||
sscanf(c, "%100s", command);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Processing line %u: %s", linect, c);
|
||||
if ((*(c+strlen(c)-1))!='\n') printf("\n");
|
||||
#endif
|
||||
|
||||
parse_command(command, c);
|
||||
|
||||
|
||||
} else printf("Can't parse line %u: %s", linect, c);
|
||||
}
|
||||
|
||||
finish_data();
|
||||
|
||||
if (!product_serial_set || !product_id_set || !product_ver_set || !vendor_set || !product_set ||
|
||||
!gpio_drive_set || !gpio_slew_set || !gpio_hysteresis_set || !gpio_power_set) {
|
||||
|
||||
printf("Warning: required fields missing in vendor information or GPIO map, using default values\n");
|
||||
}
|
||||
|
||||
printf("Done reading\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int read_dt(char* in) {
|
||||
FILE * fp;
|
||||
unsigned long size = 0;
|
||||
|
||||
printf("Opening DT file %s for read\n", in);
|
||||
|
||||
fp = fopen(in, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Error opening input file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
|
||||
printf("Adding %lu bytes of DT data\n", size);
|
||||
|
||||
total_size+=ATOM_SIZE+size;
|
||||
has_dt = true;
|
||||
dt_atom.type = ATOM_DT_TYPE;
|
||||
dt_atom.count = ATOM_DT_NUM;
|
||||
dt_atom.dlen = size+CRC_SIZE;
|
||||
|
||||
dt_atom.data = (char *) malloc(size);
|
||||
if (!fread(dt_atom.data, size, 1, fp)) goto err;
|
||||
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printf("Unexpected EOF or error occurred\n");
|
||||
fclose(fp);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int read_custom(char* in) {
|
||||
FILE * fp;
|
||||
unsigned long size = 0;
|
||||
|
||||
printf("Opening custom data file %s for read\n", in);
|
||||
|
||||
fp = fopen(in, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Error opening input file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
|
||||
printf("Adding %lu bytes of custom data\n", size);
|
||||
|
||||
total_size+=ATOM_SIZE+size;
|
||||
|
||||
custom_atom[custom_ct].type = ATOM_CUSTOM_TYPE;
|
||||
custom_atom[custom_ct].count = 3+custom_ct;
|
||||
custom_atom[custom_ct].dlen = size+CRC_SIZE;
|
||||
|
||||
custom_atom[custom_ct].data = (char *) malloc(size);
|
||||
if (!fread(custom_atom[custom_ct].data, size, 1, fp)) goto err;
|
||||
|
||||
custom_ct++;
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printf("Unexpected EOF or error occurred\n");
|
||||
fclose(fp);
|
||||
return 0;
|
||||
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret;
|
||||
int i, custom_o=0;
|
||||
|
||||
if (argc<3) {
|
||||
printf("Wrong input format.\n");
|
||||
printf("Try 'eepmake input_file output_file [dt_file] [-c custom_file_1 ... custom_file_n]'\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ret = read_text(argv[1]);
|
||||
if (ret) {
|
||||
printf("Error reading and parsing input, aborting\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc>3) {
|
||||
if (strcmp(argv[3], "-c")==0) {
|
||||
custom_o=4;
|
||||
} else {
|
||||
//DT file specified
|
||||
if (dt_atom.dlen) total_size-=(ATOM_SIZE +dt_atom.dlen - CRC_SIZE);
|
||||
ret = read_dt(argv[3]);
|
||||
if (ret) {
|
||||
printf("Error reading DT file, aborting\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc>4 && strcmp(argv[4], "-c")==0) custom_o = 5;
|
||||
|
||||
if (custom_o)
|
||||
for (i = custom_o; i<argc; i++) {
|
||||
//new custom data file
|
||||
ret = read_custom(argv[i]);
|
||||
if (ret) {
|
||||
printf("Error reading DT file, aborting\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
header.signature = HEADER_SIGN;
|
||||
header.ver = FORMAT_VERSION;
|
||||
header.res = 0;
|
||||
header.numatoms = 2+has_dt+custom_ct;
|
||||
header.eeplen = total_size;
|
||||
|
||||
printf("Writing out...\n");
|
||||
|
||||
ret = write_binary(argv[2]);
|
||||
if (ret) {
|
||||
printf("Error writing output\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
90
rpi/eeprom/docs/eepromutils/eeprom_settings.txt
Normal file
90
rpi/eeprom/docs/eepromutils/eeprom_settings.txt
Normal file
|
@ -0,0 +1,90 @@
|
|||
########################################################################
|
||||
# EEPROM settings text file
|
||||
#
|
||||
# Edit this file for your particular board and run through eepmake tool,
|
||||
# then use eepflash tool to write to attached HAT ID EEPROM
|
||||
#
|
||||
# Tools available:
|
||||
# eepmake Parses EEPROM text file and creates binary .eep file
|
||||
# eepdump Dumps a binary .eep file as human readable text (for debug)
|
||||
# eepflash Write or read .eep binary image to/from HAT EEPROM
|
||||
#
|
||||
########################################################################
|
||||
|
||||
########################################################################
|
||||
# Vendor info
|
||||
|
||||
# 128 bit UUID. If left at zero eepmake tool will auto-generate
|
||||
# RFC 4122 compliant UUID
|
||||
product_uuid 00000000-0000-0000-0000-000000000000
|
||||
|
||||
# 16 bit product id
|
||||
product_id 0x0000
|
||||
|
||||
# 16 bit product version
|
||||
product_ver 0x0000
|
||||
|
||||
# ASCII vendor string (max 255 characters)
|
||||
vendor "ACME Technology Company"
|
||||
|
||||
# ASCII product string (max 255 characters)
|
||||
product "Special Sensor Board"
|
||||
|
||||
|
||||
########################################################################
|
||||
# GPIO bank settings, set to nonzero to change from the default.
|
||||
# NOTE these setting can only be set per BANK, uncommenting any of
|
||||
# these will force the bank to use the custom setting.
|
||||
|
||||
# drive strength, 0=default, 1-8=2,4,6,8,10,12,14,16mA, 9-15=reserved
|
||||
gpio_drive 0
|
||||
|
||||
# 0=default, 1=slew rate limiting, 2=no slew limiting, 3=reserved
|
||||
gpio_slew 0
|
||||
|
||||
# 0=default, 1=hysteresis disabled, 2=hysteresis enabled, 3=reserved
|
||||
gpio_hysteresis 0
|
||||
|
||||
# If board back-powers Pi via 5V GPIO header pins:
|
||||
# 0 = board does not back-power
|
||||
# 1 = board back-powers and can supply the Pi with a minimum of 1.3A
|
||||
# 2 = board back-powers and can supply the Pi with a minimum of 2A
|
||||
# 3 = reserved
|
||||
# If back_power=2 then USB high current mode will be automatically
|
||||
# enabled on the Pi
|
||||
back_power 0
|
||||
|
||||
########################################################################
|
||||
# GPIO pins, uncomment for GPIOs used on board
|
||||
# Options for FUNCTION: INPUT, OUTPUT, ALT0-ALT5
|
||||
# Options for PULL: DEFAULT, UP, DOWN, NONE
|
||||
# NB GPIO0 and GPIO1 are reserved for ID EEPROM so cannot be set
|
||||
|
||||
# GPIO FUNCTION PULL
|
||||
# ---- -------- ----
|
||||
#setgpio 2 INPUT DEFAULT
|
||||
#setgpio 3 INPUT DEFAULT
|
||||
#setgpio 4 INPUT DEFAULT
|
||||
#setgpio 5 INPUT DEFAULT
|
||||
#setgpio 6 INPUT DEFAULT
|
||||
#setgpio 7 INPUT DEFAULT
|
||||
#setgpio 8 INPUT DEFAULT
|
||||
#setgpio 9 INPUT DEFAULT
|
||||
#setgpio 10 INPUT DEFAULT
|
||||
#setgpio 11 INPUT DEFAULT
|
||||
#setgpio 12 INPUT DEFAULT
|
||||
#setgpio 13 INPUT DEFAULT
|
||||
#setgpio 14 INPUT DEFAULT
|
||||
#setgpio 15 INPUT DEFAULT
|
||||
#setgpio 16 INPUT DEFAULT
|
||||
#setgpio 17 INPUT DEFAULT
|
||||
#setgpio 18 INPUT DEFAULT
|
||||
#setgpio 19 INPUT DEFAULT
|
||||
#setgpio 20 INPUT DEFAULT
|
||||
#setgpio 21 INPUT DEFAULT
|
||||
#setgpio 22 INPUT DEFAULT
|
||||
#setgpio 23 INPUT DEFAULT
|
||||
#setgpio 24 INPUT DEFAULT
|
||||
#setgpio 25 INPUT DEFAULT
|
||||
#setgpio 26 INPUT DEFAULT
|
||||
#setgpio 27 INPUT DEFAULT
|
119
rpi/eeprom/docs/eepromutils/eeptypes.h
Normal file
119
rpi/eeprom/docs/eepromutils/eeptypes.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* Atom types */
|
||||
#define ATOM_INVALID_TYPE 0x0000
|
||||
#define ATOM_VENDOR_TYPE 0x0001
|
||||
#define ATOM_GPIO_TYPE 0x0002
|
||||
#define ATOM_DT_TYPE 0x0003
|
||||
#define ATOM_CUSTOM_TYPE 0x0004
|
||||
#define ATOM_HINVALID_TYPE 0xffff
|
||||
|
||||
#define ATOM_VENDOR_NUM 0x0000
|
||||
#define ATOM_GPIO_NUM 0x0001
|
||||
#define ATOM_DT_NUM 0x0002
|
||||
|
||||
//minimal sizes of data structures
|
||||
#define HEADER_SIZE 12
|
||||
#define ATOM_SIZE 10
|
||||
#define VENDOR_SIZE 22
|
||||
#define GPIO_SIZE 30
|
||||
#define CRC_SIZE 2
|
||||
|
||||
#define GPIO_MIN 2
|
||||
#define GPIO_COUNT 28
|
||||
|
||||
#define FORMAT_VERSION 0x01
|
||||
|
||||
#define CRC16 0x8005
|
||||
|
||||
/* EEPROM header structure */
|
||||
struct header_t {
|
||||
uint32_t signature;
|
||||
unsigned char ver;
|
||||
unsigned char res;
|
||||
uint16_t numatoms;
|
||||
uint32_t eeplen;
|
||||
};
|
||||
|
||||
/* Atom structure */
|
||||
struct atom_t {
|
||||
uint16_t type;
|
||||
uint16_t count;
|
||||
uint32_t dlen;
|
||||
char* data;
|
||||
uint16_t crc16;
|
||||
};
|
||||
|
||||
/* Vendor info atom data */
|
||||
struct vendor_info_d {
|
||||
uint32_t serial_1; //least significant
|
||||
uint32_t serial_2;
|
||||
uint32_t serial_3;
|
||||
uint32_t serial_4; //most significant
|
||||
uint16_t pid;
|
||||
uint16_t pver;
|
||||
unsigned char vslen;
|
||||
unsigned char pslen;
|
||||
char* vstr;
|
||||
char* pstr;
|
||||
};
|
||||
|
||||
/* GPIO map atom data */
|
||||
struct gpio_map_d {
|
||||
unsigned char flags;
|
||||
unsigned char power;
|
||||
unsigned char pins[GPIO_COUNT];
|
||||
};
|
||||
|
||||
|
||||
uint16_t getcrc(char* data, unsigned int size) {
|
||||
|
||||
uint16_t out = 0;
|
||||
int bits_read = 0, bit_flag;
|
||||
|
||||
/* Sanity check: */
|
||||
if((data == NULL) || size==0)
|
||||
return 0;
|
||||
|
||||
while(size > 0)
|
||||
{
|
||||
bit_flag = out >> 15;
|
||||
|
||||
/* Get next bit: */
|
||||
out <<= 1;
|
||||
out |= (*data >> bits_read) & 1; // item a) work from the least significant bits
|
||||
|
||||
/* Increment bit counter: */
|
||||
bits_read++;
|
||||
if(bits_read > 7)
|
||||
{
|
||||
bits_read = 0;
|
||||
data++;
|
||||
size--;
|
||||
}
|
||||
|
||||
/* Cycle check: */
|
||||
if(bit_flag)
|
||||
out ^= CRC16;
|
||||
|
||||
}
|
||||
|
||||
// item b) "push out" the last 16 bits
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
bit_flag = out >> 15;
|
||||
out <<= 1;
|
||||
if(bit_flag)
|
||||
out ^= CRC16;
|
||||
}
|
||||
|
||||
// item c) reverse the bits
|
||||
uint16_t crc = 0;
|
||||
i = 0x8000;
|
||||
int j = 0x0001;
|
||||
for (; i != 0; i >>=1, j <<= 1) {
|
||||
if (i & out) crc |= j;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue