summaryrefslogtreecommitdiff
path: root/src/sp12.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp12.h')
-rw-r--r--src/sp12.h520
1 files changed, 520 insertions, 0 deletions
diff --git a/src/sp12.h b/src/sp12.h
new file mode 100644
index 0000000..a75ef18
--- /dev/null
+++ b/src/sp12.h
@@ -0,0 +1,520 @@
+/* SP12: A serial programmer for working with Atmel AVR uCs */
+/* Copyright (C) 1997-2008 Ken Huntington, Kevin Towers, */
+/* Artur Pundsack, Pitronics. */
+
+/* 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; either version 2 */
+/* of the License, or (at your option) any later version. */
+
+/* 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. */
+
+/* Pitronics can be reached by email: sbolt@xs4all.nl */
+/* Kevin Towers can be reached by email: ktowers@omnexcontrols.com */
+/* Ken Huntington can be reached by email: kenh@compmore.net */
+/* Artur Pundsack can be reached by email: ap@pa-tec.de */
+
+#define WORDLEN 16
+#define DATALEN 5
+#define FLASH_DATAPTR 6
+#define MAXLEN 500
+#define FLASHBUF_UPPERLIMIT 1048576L
+#define EEPROMBUF_UPPERLIMIT 8192L
+#define FILE_ERROR "does not exist, wrong format,\n address > limit, or HEX file checksum failure."
+#define FILE_WRITE_ERROR "Unable to write to, or finish writing to"
+
+#define STK200TEST 0x02 /* data-1 connected to status-7 */
+#define STK200PRESENT 0x80
+#define STK300TEST 0x01 /* data-0 connected to status-5 */
+#define STK300PRESENT 0x20
+/*
+ * program control line definitions for sp12 cable/dongle
+ */
+#define S_SCK 0x01 /* SPI clock out */
+#define S_MOSI 0x80 /* SPI data out */
+#define S_MISO_BITNR 7 /* SPI data in bit number */
+#define S_MISO_INV 0xFF /* inverted */
+#define S_RESET 0x02 /* processor reset control */
+#define S_ENABLE 0 /* Dummy */
+#define S_PORTPOWER 0x7C /* `port power' bits */
+#define S_DEFAULT_EXIT_STATE 0
+#define S_PORTACTIVE 0x7C /* reserved for portControl() */
+/*
+ * program control line definitions for Kanda STK200 dongle
+ */
+#define K_SCK 0x10 /* SPI clock out */
+#define K_MOSI 0x20 /* SPI data out */
+#define K_MISO_BITNR 6 /* SPI data in bit number */
+#define K_MISO_INV 0x00 /* not inverted */
+#define K_RESET 0x80 /* processor reset control */
+#define K_ENABLE 0x0C /* ~enables Kanda `dongle' */
+#define K_PORTPOWER 0 /* Dummy */
+#define K_DEFAULT_EXIT_STATE 0x0C
+#define K_PORTACTIVE 0x43
+
+/*
+ * These macros perform various bit operations on scalar types using bit masks
+ */
+#define bit_set(value, bit) ((value) |= (bit))
+#define bit_clear(value, bit) ((value) &= ~(bit))
+#define bit_comp(value, bit) ((value) ^= (bit))
+#define bit_test(value, bit) (((value) & (bit)) != 0)
+
+/*---------------------- The global constants -----------------------*/
+/*----------------------- defined in init.c ------------------------*/
+
+extern unsigned long PROGRAM_ENABLE;
+extern unsigned long CHIP_ERASE;
+extern unsigned long READ_DEVICE;
+extern unsigned long READ_PROG_LO;
+extern unsigned long READ_PROG_HI;
+extern unsigned long WRITE_PROG_LO;
+extern unsigned long WRITE_PROG_HI;
+extern unsigned long LOAD_PAGE_HI;
+extern unsigned long LOAD_PAGE_LO;
+extern unsigned long LOAD_EXT_ADDR; /* AP, 15.01.2008: Added */
+extern unsigned long WRITE_PAGE;
+extern unsigned long READ_EEPROM;
+extern unsigned long WRITE_EEPROM;
+extern unsigned long POLL_RDY_BSY;
+extern unsigned long WRITE_LOCK_HM;
+extern unsigned long WRITE_LOCK_LM;
+extern unsigned long READ_LOCK;
+extern unsigned long WRITE_FUSES_HM;
+extern unsigned long WRITE_FUSES_LM;
+extern unsigned long READ_FUSES;
+extern unsigned long WRITE_HIGH_FUSES_HM;
+extern unsigned long WRITE_HIGH_FUSES_LM;
+extern unsigned long READ_HIGH_FUSES;
+extern unsigned long WRITE_EXTD_FUSES_HM;
+extern unsigned long WRITE_EXTD_FUSES_LM;
+extern unsigned long READ_EXTD_FUSES;
+extern unsigned long READ_CALIBRATION;
+extern char CALIB_MESSAGE[MAXLEN];
+extern char LOCK_MESSAGE[MAXLEN];
+extern char FUSES_MESSAGE[MAXLEN];
+extern char H_FUSES_MESSAGE[MAXLEN];
+extern char X_FUSES_MESSAGE[MAXLEN];
+extern int POLL_RBLSB;
+extern int POLL_RBLEN;
+extern int W_LOCKLSB;
+extern int R_LOCKLSB;
+extern int W_LOCKLEN;
+extern int R_LOCKLEN;
+extern int W_FUSESLSB;
+extern int R_FUSESLSB;
+extern int W_FUSESLEN;
+extern int R_FUSESLEN;
+extern int WH_FUSESLSB;
+extern int RH_FUSESLSB;
+extern int WH_FUSESLEN;
+extern int RH_FUSESLEN;
+extern int WX_FUSESLSB;
+extern int RX_FUSESLSB;
+extern int WX_FUSESLEN;
+extern int RX_FUSESLEN;
+extern int CALIBLSB;
+extern int CALIBLEN;
+
+/*-------------------- No more global constants ---------------------*/
+
+/*---------------------- The global variables -----------------------*/
+/*----------------------- defined in init.c ------------------------*/
+
+extern unsigned char SCK;
+extern unsigned char MOSI;
+extern unsigned char MISO_BITNR;
+extern unsigned char MISO_INV;
+extern unsigned char RESET;
+extern unsigned char ENABLE;
+extern unsigned char PORTPOWER;
+extern unsigned char DEFAULT_EXIT_STATE;
+extern unsigned char PORTACTIVE;
+
+struct timeConsts {
+ double loop;
+ double port; /* time taken by outportb() */
+ unsigned long sckLO;
+ unsigned long sckHI;
+ unsigned long resetPuls;
+ unsigned programEnable;
+ unsigned chipErase;
+ unsigned long byteWrite;
+ unsigned long byteWriteDefault;
+ int byteWriteAdjusted; /* a flag */
+ unsigned long pageWrite;
+ unsigned long pageWriteDefault;
+ int pageWriteAdjusted; /* a flag */
+ unsigned powerOn;
+};
+
+struct device_info {
+ unsigned char sigByte_0;
+ unsigned char sigByte_1;
+ unsigned char sigByte_2;
+ char name[30];
+ char madeBy[30];
+ long eepromLimit;
+ long flashLimit;
+ int initPerformed;
+ int pageMode; /* true if page programmed device */
+ int pageSize;
+ int fuseMode; /* 0: AT90S1200, 2313, 4414, 8515 */
+ /* 4: 2343 (lock +r, RCEN +rw) */
+ /* 5: 2323 4434, 8535 (lock +r, */
+ /* FSTRT +rw) */
+ /* 6: (ATmega103/603) */
+ /* 7: 2333, 4433 (lock +r, CKSELx3 +rw */
+ /* BODx2 +rw) */
+};
+
+struct logging {
+ char logPath[MAXLEN];
+ int logging;
+ int query;
+};
+
+extern struct timeConsts timeConst;
+extern struct device_info device;
+extern struct logging log;
+
+extern int portAddress;
+extern int portStatus;
+extern int writeRetries;
+extern float clockSpdDefault;
+extern int KandaMode; /* Cable/dongle Kanda or sp12 */
+extern int ExtAddr; /* AP, 15.01.2008: Added, Marker for crossing */
+ /* the 64k Flash boundary */
+
+extern unsigned char outbyte; /* current state of device */
+ /* control port */
+
+/*-------------------- No more global variables ---------------------*/
+
+/*
+ * A few prototypes.
+ */
+
+/* Look for the rc file, using environment variable `SP12' (if */
+/* this variable has not been set, the current directory is used). */
+/* If the rc file exists, then read the time constants and the */
+/* parallel port address from this file. If the rc file is not */
+/* found, then calibrate the time constants, check for available */
+/* parallel ports, set (usually the primary) address, and write */
+/* it all into a new rc file. Afterwards check if the parallel */
+/* port is actually there (guarding against a corrupt rc file, and */
+/* setting the port data register to 0xF0), and also check if the */
+/* time constants aren't 0. exit(1) if a check fails. */
+/* Based on either the KANDA setting in _sp12rc or the name by */
+/* which the program is called (sp12 or sp12.kanda), the */
+/* parallel port pinout is adapted to the cable/dongles supplied */
+/* with the Atmel/Kanda STK200/300 starter kits, or to the */
+/* original SP12 cable and Ken Huntington's dongle. */
+
+void initSp12(char *howWeAreCalled);
+
+
+/* Takes a devicecode (like 0392) or identifier ((-i)433) and sets */
+/* the device commands, messages and other parameters as found in */
+/* _sp12dev. */
+/* Returns 1 if _sp12dev not found; 2 if a line in _sp12dev is */
+/* corrupt; 3 if _sp12dev has no entry for the deviceCode or */
+/* identifier and the deviceCode (as an int) if all is well. */
+
+int setDevicePars(int initFlag, char *identifier);
+
+
+/* Collects all device codes and names from _sp12dev, and shows */
+/* them on screen. */
+/* Returns 1 if _sp12dev not found, else zero. */
+
+int supported(void);
+
+
+/* Delay by executing loops, not so empty as to be caught by */
+/* the compiler's optimization efforts. */
+
+void loopDelay(unsigned long loops);
+
+
+/* Determines the number of bits in command, and shifts them */
+/* highest bit first into unsigned char output, which then */
+/* is used to clock them out bit by bit through Centronics */
+/* data-7. */
+/* Reads back and returns whatever the uC clocks out on Miso */
+/* while the command is clocked in. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+unsigned long clockOutCommand(unsigned long command);
+
+
+/* Accepts a 32-bit address, and shifts it highest bit first */
+/* into unsigned char output, which then is used to clock the */
+/* bits out one by one hrough Centronics data-7 */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+void clockOutAddress(unsigned long address);
+
+
+/* Read one data byte from the status register of the */
+/* Centronics port. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+unsigned char clockInByte(void);
+
+
+/* Accepts a 32-bit address. Reads the codeWord in two steps */
+/* from the device connected to the Centronics port. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+unsigned int readCodeWord(unsigned long address);
+
+
+/* Accepts a 16-bit codeWord and a 7-bit address. Writes the code */
+/* in two steps with no delays into the ATMega device connected to */
+/* the Centronics port. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+void loadCodePage(unsigned long address, unsigned int codeWord);
+
+
+/* Accepts a 32-bit page number and programs it into the ATMega */
+/* device connected to the Centronics parallel port. */
+/* The page is read back and compared with the buffer; if all */
+/* is well, 0 is returned, else 1. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+int writeCodePage(unsigned int flashBuf[], unsigned long address);
+
+
+/* Accepts a 16-bit codeWord and a 16-bit address. Writes the code */
+/* in two steps into the device connected to the Centronics port and */
+/* verifies arrival. Returns 1 if verify fails three times, else 0. */
+/* The time constant byteWrite is adjusted dynamically, */
+/* if the device is not a 1200(A) and optimizeFlag allows. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+/* AP, 15.01.2008: This function is only available for non page mode!*/
+
+int writeFlashVerified(unsigned int address, unsigned int codeWord,
+ int optimizeFlag);
+
+
+/* Expects flashBuf[] to be filled with data. */
+/* If a (page) write fails, 1 is returned, else 0. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+int writeFlashArea(unsigned int flashBuf[], long bufLimit,
+ int optimizeFlag);
+
+
+/* Assume the device connected to the Centronics port is powered, */
+/* but that device sck was not held low during power-up, so a */
+/* reset pulse is needed before the SPI can be enabled. */
+/* Assume also that power has yet to be switched on (for separate */
+/* programmer powered by parallel port, instead of in-circuit */
+/* programming. */
+/* If uC is 1200, emit just one PROGRAM_ENABLE command. */
+/* Else retry until the third byte read back by clockOutCommand() */
+/* is 0x53, or at least 32 retries have been unsuccessful. */
+
+int enableSPI(int uC);
+
+
+/* Adapt Sck timing to user's clock speed setting */
+/* (Init sets the timing equal to sck0.5M, and the flag will be */
+/* zero unless altered by the command line.) */
+
+float setSckTiming(float clkSpeed);
+
+
+/* Before writing to the flash area, the device has to be erased. */
+/* Note: This command also erases the eeprom area (all to 0xFF). */
+/* There is no need for general erase before writing to the */
+/* eeprom area, since the device has an auto-erase built into */
+/* the eeprom write cycle. Thus you can alter one or more eeprom */
+/* addresses without disturbing the rest of the device. */
+
+void eraseDevice(void);
+
+
+/* A routine to switch off the powerbits; useful only when the */
+/* separate programmer is used instead of in-circuit programming. */
+
+void portControl(int portFlag, int exitFlag);
+
+
+/* Sends a lock or fuses string to the microcontroller. */
+/* Returns 9 if the writeCommand is zero (not available according */
+/* to _sp12dev). */
+/* The lock or fuses string may represent a binary or hex number. */
+/* If it's binary, the length of the string is compared with */
+/* W_FUSESLEN; a useful sanity check. The function returns 2 if */
+/* the length is wrong. A hex number is not checked, as there is no */
+/* way to know how many leading zeroes are intended. */
+/* Next, the block is ored into the writeCommand and uploaded to */
+/* the device. */
+/* Since (re)enabling brown-out detection usually causes the */
+/* AT90(L)S2333/4433 to hang, the fuses are only written, not */
+/* verified. */
+
+int writeFuses(unsigned long commandHM, unsigned long commandLM, \
+ char *fuses, int WfusesLsb, int WfusesLen);
+
+
+/* Reads the lock or fuse bit block from the microcontroller. */
+/* Returns 9 if the readCommand is zero (not available according */
+/* to _sp12dev). */
+
+int readFuses(unsigned long readCommand, char *fuses, \
+ int RfusesLsb, int RfusesLen);
+
+void readDeviceCode(void);
+
+
+/* Converts address or data string to number, automatically */
+/* selecting hex (0xNNN), oct (0NNN), binary (BNNN) or */
+/* dec (NNN) input. */
+
+unsigned int str2num(char *addressOrData);
+
+
+/* convert unsigned int to a string-representation of the */
+/* binary number (ascii `0' is 48, ascii `1' is 49) */
+
+void num2bin(unsigned char buffer, char *binary);
+
+
+/* Reads program file in format address:data, stores data into */
+/* flashBuf by address. The two numbers must be hex without `0x' */
+/* for example: 00000c:99e1 */
+
+int readFlashFile(char flashPath[], unsigned int flashBuf[], long bufLimit);
+
+
+/* Reads program file in Atmel generic format (address:data) or */
+/* Intel HEX format; stores data into into flashBuf by address. */
+/* flashBuf by address. The two numbers in the generic format are */
+/* hex without `0x'. For example: 00000c:99e1 */
+
+int readEepromFile(char eepromPath[], unsigned int eepromBuf[], long bufLimit);
+
+
+/* Calculate checksum over buffer[]; bufLimit is number of */
+/* elements in buffer. */
+
+unsigned int checksum(unsigned int buffer[], long bufLimit);
+
+
+/* (expects flashBuf[] to be filled with 0xFFFF) */
+/* Loops readCodeWord into flashBuf[] */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+void readFlashArea(unsigned int flashBuf[], long bufLimit);
+
+
+/* Writes flashBuf[] into FILE *flashBufPtr; */
+/* If write to file fails, return(1), else return(0) */
+
+int fileFlashBuf(unsigned int flashBuf[], long bufLimit,
+ char flashPath[], int intel_flag, int hex_ascii_flag);
+
+
+/* Reads flash and eeprom area's. Return 1 if a flash address does */
+/* not contain 0xFFFF, or 3 if an eeprom address also isn't blank; */
+/* return 2 if the flash is blank, but the eeprom isn't; */
+/* return 0 is both area's are blank. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+int blankCheck(long flashLimit, long eepromLimit);
+
+
+/* Accepts a dataByte and a 16-bit address. Writes the byte into */
+/* the device connected to the Centronics port and verifies arrival. */
+/* Returns 1 if verify fails three times, else 0. */
+/* The time constant byteWrite is adjusted dynamically, */
+/* if the device is not a 1200(A) and/or optimizeFlag allows. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+int writeByteVerified(unsigned long writeCommand,
+ unsigned long readCommand, int optimizeFlag);
+
+
+/* Writes eepromBuf[] into FILE *eepromBufPtr; */
+/* If write to file fails, return(1), else return(0) */
+
+int fileEepromBuf(unsigned int eepromBuf[], long bufLimit,
+ char eepromPath[], int intel_flag, int hex_ascii_flag);
+
+
+/* Accepts a 16-bit address. Reads the dataByte in two steps */
+/* from the device connected to the Centronics port. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+unsigned char readDataByte(unsigned int address);
+
+
+/* Writes buffer[] to stdout as a hex dump with ascii translation */
+
+void printBuffer(unsigned int buffer[], long bufLimit, int twoByteFlag);
+
+
+/* Add a line to the log about a write command */
+
+int logWrites(char *commandStr, unsigned int address, int data,
+ char *path, unsigned int buffer[], int overlayFlag, int *error);
+
+
+/* Add a line to the log about a lock command */
+
+int logLocks(unsigned int buffer[], char *lockBits);
+
+
+/* Accepts a dataByte and a 16-bit address. Writes the code in two */
+/* steps into the device connected to the Centronics port and */
+/* verifies arrival. Returns 1 if verify fails three times, else 0. */
+/* The time constant byteWrite is adjusted dynamically, */
+/* if the device is not a 1200(A) and optimizeFlag allows. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+int writeEepromVerified(unsigned int address, unsigned char dataByte,
+ int optimizeFlag);
+
+
+/* Expects eepromBuf[] to be filled with data. */
+/* executes writeEepromVerified() address by address; */
+/* if verify fails, stops and returns 1, else returns 0. */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+int writeEepromArea(unsigned int eepromBuf[], long bufLimit,
+ int optimizeFlag, int overlayFlag);
+
+
+/* (expects eepromBuf[] to be filled with 0xFF) */
+/* Loops readDataByte into eepromBuf[] */
+/* Power bits prior state assumed on; left on at return. */
+/* SCK prior state assumed lo; left lo at return. */
+
+void readEepromArea(unsigned int EepromBuf[], long bufLimit);
+