summaryrefslogtreecommitdiff
path: root/src/sp12.h
blob: e3d116c856d575ff6a7a59a0b6b54be50a4bc387 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
/* 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          */

#ifndef _SP12_H
#define _SP12_H

#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 logging;

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);
 
#endif /* not _SP12_H */