📄 tinitalk.c
字号:
/*------------------------------------------------------------------------- tinitalk.c - A tini utility to download files to TINI and talk to it Written By - Johan Knol johan.knol@iduna.nl 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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/#if defined(_MSC_VER) || defined(__BORLANDC__)#define TINI_PORT "COM2"#else#ifdef linux// must be linux#define TINI_PORT "/dev/ttyS0"#else// could be solaris#define TINI_PORT "/dev/term/a"#endif#endif#define TINI_BAUD 115200#define TINI_ESCAPE_CHAR 0x1b#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <fcntl.h>#if !defined( _MSC_VER) && !defined(__BORLANDC__)#include <unistd.h>#include <termios.h>#include <sys/ioctl.h>#else#include <conio.h>#include <windows.h>#define sleep(ms) Sleep((ms*1000))#define usleep(us) Sleep((us/1000))#endif#include "tinitalk.h"char *programName;char escapeChar = 0;char *port = NULL;int baud = 0, appBaud = 0;voidUsage (){ fprintf (stderr, "usage: %s <options> command [args] \n", programName); fprintf (stderr, "\nwhere options are:\n"); fprintf (stderr, " <-p port> set the serial port, defaults to %s\n", TINI_PORT); fprintf (stderr, " <-b baud> set the baud rate, defaults to %d\n", TINI_BAUD); fprintf (stderr, " <-B baud> set the baud rate for the application\n"); fprintf (stderr, " <-c> connect to tini after command (if any)\n"); fprintf (stderr, " <-e #> to set the escape char\n"); fprintf (stderr, " <-s> to see some examples.\n"); fprintf (stderr, "\nand commands are:\n"); fprintf (stderr, " <load file> load a hex file and restart the bootloader\n"); fprintf (stderr, " <execute [file]> load a hex file and/or start the program in bank 1\n"); exit (1);}voidExamples (){ printf ("\n"); printf ("%s -p /dev/ttyS1\n", programName); printf (" now you are talking to the bootloader through serial-1\n"); printf ("%s -b 19200\n", programName); printf (" now you are talking to the bootloader at 19200 baud\n"); printf ("%s load tini.hex\n", programName); printf (" load tini.hex\n"); printf ("%s -c load tini.hex\n", programName); printf (" after loading tini.hex you are talking to the bootloader\n"); printf ("%s execute tini.hex\n", programName); printf (" load tini.hex and start the program in bank 1\n"); printf ("%s -c execute tini.hex\n", programName); printf (" after loading the file you are talking to the (restarted)\n"); printf (" program in bank 1\n"); printf ("%s execute\n", programName); printf (" now the program in bank 1 is restarted.\n"); printf ("%s -c execute\n", programName); printf (" now you are talking to the (restarted) program in bank 1\n"); printf ("%s -b 115200 -B 9600 -c execute tini.hex\n", programName); printf (" download tini.hex at 115200 baud, but talk the program at 9600 baud\n"); exit (0);}intmain (int argc, char **argv){ int connect = 0; char command[64]; int arg = 1; //programName=argv[0]; programName = "tinitalk"; // process options while (arg < argc && argv[arg][0] == '-') { // no arguments required if (argv[arg][1] == 'c') { connect = 1; arg++; continue; } else if (argv[arg][1] == 's') { Examples (); // will not return } // argument required if (arg >= (argc - 1)) { Usage (); } switch (argv[arg][1]) { case 'p': port = argv[arg + 1]; break; case 'b': baud = atoi (argv[arg + 1]); break; case 'B': appBaud = atoi (argv[arg + 1]); break; case 'e': escapeChar = atoi (argv[arg + 1]); break; default: Usage (); } arg += 2; } if (port == NULL) { if ((port = getenv ("TINI_PORT")) == NULL) { port = TINI_PORT; } } if (baud == 0) { if (getenv ("TINI_BAUD")) { baud = atoi (getenv ("TINI_BAUD")); } else { baud = TINI_BAUD; } } if (escapeChar == 0) { if (getenv ("TINI_ESCAPE_CHAR")) { escapeChar = atoi (getenv ("TINI_ESCAPE_CHAR")); } else { escapeChar = TINI_ESCAPE_CHAR; } } if (appBaud == 0) { appBaud = baud; } if (!TiniOpen (port, baud)) { exit (1); } // process commands while (arg < argc) { if (strcmp (argv[arg], "load") == 0) { // argument required if (arg >= (argc - 1)) { Usage (); } if (LoadHexFile (argv[arg + 1])) { TiniReset (1); if (connect) { TiniConnect (baud); } } exit (0); } if (strcmp (argv[arg], "execute") == 0) { // argument supplied? if (arg < (argc - 1)) { if (!LoadHexFile (argv[arg + 1])) { exit (0); } } TiniReset (0); if (connect) { TiniConnect (appBaud); } exit (0); } // unsupported command Usage (); } // no commands, just connect // on my linux box, DTR is always set after opening the port, so: // reset the bootloader strcpy (command, "r"); while (1) { switch (tolower (command[0])) { case '?': case '\n': case 'h': printf ("\n"); printf ("r - reset, start bootloader and connect to TINI\n"); printf ("e - reset, start program in bank 1 and connect to TINI\n"); printf ("c - connect to TINI.\n"); printf ("l - load file.\n"); printf ("s - save file.\n"); printf ("q - quit.\n"); break; case 'e': TiniReset (0); TiniConnect (appBaud); break; case 'r': TiniReset (1); TiniConnect (baud); break; case 'c': // leave it as it was TiniConnect (0); break; case 'l': { char fileName[FILENAME_MAX] = ""; printf ("Enter filename: "); fflush (stdout); fgets (fileName, FILENAME_MAX, stdin); // remove the EOL character fileName[strlen (fileName) - 1] = 0; LoadHexFile (fileName); } break; case 's': printf ("Command \"%c\" not implemented yet.\n", command[0]); break; case 'q': return 0; break; default: printf ("Unknown command: \"%c\".\n", command[0]); break; } printf ("\n<%s> ", programName); fflush (stdout);#if defined(_MSC_VER) || defined(__BORLANDC__) // don't know why getch ();#endif fgets (command, 64, stdin); } return 0;}intLoadHexFile (char *path){ FILE *hexFile; char hexLine[256]; int bank = 0; int line = 0, type; char tempString[16]; char c, ctrlC = 0x03; int bytesLoaded = 0, progress = 0; char banksZapped[8] = {0, 0, 0, 0, 0, 0, 0, 0}; unsigned int address, bytes, i; unsigned int checksum, chk; if ((hexFile = fopen (path, "r")) == NULL) { perror (path); return 0; } TiniFlush (); while (fgets (hexLine, 256, hexFile)) { if (TiniRead (&c, 1) == 1) { // show error messages from TINI printf ("\n"); do { putchar (c); } while (TiniRead (&c, 1) == 1); printf ("\nInterrupted by loader.\n"); return 0; } line++; if (hexLine[0] != ':' || sscanf (&hexLine[1], "%02x", &bytes) != 1 || sscanf (&hexLine[3], "%04x", &address) != 1 || sscanf (&hexLine[7], "%02x", &type) != 1) { printf ("Invalid ihx record: \"%s\"\n", hexLine); TiniReset (1); return 0; } // make sure line ends with '\r' or TINI won't swallow it hexLine[strlen (hexLine) - 1] = '\r'; address += bank << 16; // test checksum checksum = 0; for (i = 0; i < bytes + 5; i++) { sscanf (&hexLine[i * 2 + 1], "%02x", &chk); checksum += chk; } if (checksum & 0xff) { printf ("\nChecksum error at %06x (0x%02x!=0) in line: %d\n", address, checksum&0xff, line); TiniReset (1); return 0; } if (type == 4) { // new Hex386 record sscanf (&hexLine[9], "%04x", &bank); address = (address & 0xffff) + (bank << 16); // just for safety if (bank == 0) { printf ("==> No overwrite of bank 0 <==\n"); return 0; } if (0) { // interupt loader TiniWriteAndWait (&ctrlC, 1, '>'); } else { // reset TINI TiniReset (1); } if (!banksZapped[bank]) { // zap bank sprintf (tempString, "z%d\r", bank); TiniWriteAndWait (tempString, 3, '?'); TiniWriteAndWait ("y", 1, '\n'); printf ("[Zapping bank %d]\n", bank); TiniWait ('>'); banksZapped[bank] = 1; // start loader //printf ("[Starting loader]\n"); } TiniWriteAndWait ("l\r", 2, '\n'); printf ("[Loading bank %d]\n", bank); } if (bank > 0) { if ((type == 0) && (1 || ((bytesLoaded / 1024) > progress))) { progress = bytesLoaded / 1024; printf ("[%06x: sent %d bytes]\r", address, bytesLoaded); fflush (stdout); } bytesLoaded += bytes; //printf ("data: %s\n", hexLine); TiniWrite (" ", 12); TiniWrite (hexLine, strlen (hexLine)); TiniDrain (); } else { //printf ("skip: %s\n", hexLine); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -