summaryrefslogtreecommitdiff
path: root/recipes/simpad-utilities/serload
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/simpad-utilities/serload')
-rw-r--r--recipes/simpad-utilities/serload/main.cpp136
-rw-r--r--recipes/simpad-utilities/serload/serialdownload.cpp408
-rw-r--r--recipes/simpad-utilities/serload/serialdownload.h158
-rw-r--r--recipes/simpad-utilities/serload/serload.138
4 files changed, 740 insertions, 0 deletions
diff --git a/recipes/simpad-utilities/serload/main.cpp b/recipes/simpad-utilities/serload/main.cpp
new file mode 100644
index 0000000000..b65d71753c
--- /dev/null
+++ b/recipes/simpad-utilities/serload/main.cpp
@@ -0,0 +1,136 @@
+//=============================================================================
+// Project: SIMpad
+//=============================================================================
+// FILE-NAME: main.cpp
+// FUNCTION: Serial download of a new image from PC to SIMpad
+//
+// AUTHOR: Juergen Messerer, Peter Voser
+// CREAT.-DATE: 01.04.2001 (dd.mm.yy)
+//
+// NOTES: -
+//
+//=============================================================================
+
+#include <unistd.h>
+#include <iostream>
+#include <string.h>
+#include "serialdownload.h"
+using namespace std;
+
+const int STRING_LENGTH = 128;
+
+//=============================================================================
+//=============================================================================
+void printHelp(void)
+{
+ cout << "serload V1.0 for Linux " << endl;
+ cout << "Downloading a new image to the SIMpad "
+ << "using the serial interface." << endl << endl;
+ cout << "Invocation: serload [IMAGEFILE] [ttyS-PORT]" << endl;
+ cout << "IMAGEFILE: the file with the new image prepared for the"
+ << " SIMpad Bootloader."
+ << endl;
+ cout << "ttyS-PORT: number of the ttyS-Port for the download."
+ << endl;
+ cout << "Note: ttyS0 = COM1, ttyS1 = COM2, ..." << endl << endl;
+}
+
+//=============================================================================
+//=============================================================================
+int main(int argc, char *argv[])
+{
+ int i;
+ for(i = 0; i < argc; ++i)
+ {
+ if(strcmp(argv[i], "--help") == 0)
+ {
+ // The user asks for help.
+ printHelp();
+ exit(0);
+ }
+ }
+
+ if(argc != 3 && argc != 2)
+ {
+ cerr << endl << "Usage: serload [IMAGEFILE] [ttyS-PORT]" << endl;
+ cerr << "See also \"serload --help\"!" << endl << endl;
+ exit(1);
+ }
+
+ char device[STRING_LENGTH];
+ if(argc == 3)
+ {
+ strcpy(device, "/dev/ttyS");
+ strcat(device, argv[2]);
+ }
+ else
+ {
+ // If no serial port is given, use ttyS0 as default.
+ strcpy(device, "/dev/ttyS0");
+ }
+
+ SerialDownload serload;
+ int myError, imagesize;
+ static char *image;
+
+ int success = serload.openSerialPort(device, myError);
+ if(success != 0)
+ {
+ cerr << "Error: cannot open " << device << ". Aborting."
+ << endl << endl;
+ exit(2);
+ }
+
+ myError = serload.loadFile(argv[1], image, imagesize);
+ if(myError != 0)
+ {
+ cerr << "Error: cannot load file "
+ << argv[1] << "! Aborting." << endl << endl;
+ exit(3);
+ }
+
+ cout << "Please press RESET at the back of the SIMpad!" << endl;
+ int reply = serload.connectToSimpad(115200, myError);
+
+ if(reply != 0)
+ {
+ cerr << "Error: cannot connect to SIMpad! Aborting."
+ << endl << endl;
+ exit(4);
+ }
+
+ // Determine number of blocks to send without remaining bytes!
+ int progress = 0;
+ int size = imagesize;
+ int totalBlocks = size / 512;
+ int numberOfBlocksToSend = totalBlocks;
+ int numberOfBlocksSent = 0;
+
+ // Send blocks.
+ while(numberOfBlocksToSend)
+ {
+ serload.sendBlock(image, 512, myError);
+ image += 512;
+ --numberOfBlocksToSend;
+ // Update progress info every 100th block.
+ if(!(numberOfBlocksSent % 100))
+ {
+ progress = 100 * numberOfBlocksSent / totalBlocks;
+ }
+ ++numberOfBlocksSent;
+ }
+
+ // Determine, if there are remaining bytes.
+ int numberOfRemainingBytes = size % 512;
+ if(numberOfRemainingBytes)
+ {
+ serload.sendBlock(image, numberOfRemainingBytes, myError);
+ }
+
+ // The bootloader burns the new image.
+ serload.waitForEndOfBurning();
+
+ cout << "Update successfully finished! Swich the SIMpad on." << endl;
+
+ return 0;
+}
diff --git a/recipes/simpad-utilities/serload/serialdownload.cpp b/recipes/simpad-utilities/serload/serialdownload.cpp
new file mode 100644
index 0000000000..c58de2280f
--- /dev/null
+++ b/recipes/simpad-utilities/serload/serialdownload.cpp
@@ -0,0 +1,408 @@
+//=============================================================================
+// Project: SIMpad
+//=============================================================================
+// FILE-NAME: serialdownload.cpp
+// FUNCTION: Serial download of a new image from PC to SIMpad
+//
+// AUTHOR: Juergen Messerer, Peter Voser
+// CREAT.-DATE: 01.04.2001 (dd.mm.yy)
+//
+// NOTES: -
+//
+//=============================================================================
+
+#include <iostream>
+#include "serialdownload.h"
+using namespace std;
+
+//=============================================================================
+//=============================================================================
+SerialDownload::SerialDownload()
+{
+}
+
+//=============================================================================
+//=============================================================================
+SerialDownload::~SerialDownload()
+{
+}
+
+//=============================================================================
+//=============================================================================
+int SerialDownload::openSerialPort(const char* portDev, int& errorNumber)
+{
+ _serialPort = open(portDev, O_RDWR | O_NONBLOCK);
+
+ if (_serialPort == -1)
+ {
+ errorNumber = errno;
+ return -1;
+ }
+
+ // Read old serial port setup
+ termios serialPortSetup;
+ int success = tcgetattr(_serialPort, &serialPortSetup );
+ if (success < 0)
+ {
+ errorNumber = errno;
+ perror(0);
+ return -1;
+ }
+
+ serialPortSetup.c_iflag = 0L;
+ serialPortSetup.c_oflag = 0L;
+
+ // Control mode flags
+ serialPortSetup.c_cflag &= ~(CSTOPB|PARENB|CRTSCTS);
+ serialPortSetup.c_cflag |= (CS8|CLOCAL);
+
+ // Local mode flags
+ serialPortSetup.c_lflag = 0L;
+
+ // control characters
+ serialPortSetup.c_cc[VTIME] = 0;
+ serialPortSetup.c_cc[VMIN] = 0;
+
+ // Set baud rate = 38.4kBaud
+ cfsetispeed(&serialPortSetup, B38400);
+ cfsetospeed(&serialPortSetup, B38400);
+
+ success=tcsetattr(_serialPort, TCSANOW, &serialPortSetup);
+ if(success < 0)
+ {
+ errorNumber = errno;
+ perror(0);
+ return -1;
+ }
+
+ return 0;
+}
+
+//=============================================================================
+//=============================================================================
+int SerialDownload::loadFile(const char *fileName,
+ char *&buffer,
+ int &numberOfBytes)
+{
+ FILE *path;
+
+ if((path = fopen(fileName,"rb")) == 0)
+ {
+ // Specified file not found.
+ return -1;
+ }
+
+ fseek(path, 0, 2);
+ numberOfBytes = ftell(path);
+ rewind(path);
+
+ buffer = (char*)malloc((size_t)numberOfBytes);
+ if(buffer == 0)
+ {
+ // Insufficient memory to load file.
+ fclose(path);
+ return -2;
+ }
+
+ if(fread(buffer, numberOfBytes, 1, path) != 1)
+ {
+ // Cannot read file.
+ fclose(path);
+ return -3;
+ }
+
+ fclose(path);
+ return 0;
+}
+
+//=============================================================================
+//=============================================================================
+bool SerialDownload::changeBaudRate(const int newBaudRate,
+ int& errorNumber)
+{
+ int success;
+ int baudRate;
+ struct termios setup;
+
+ switch(newBaudRate)
+ {
+ case 9600:
+ baudRate = B9600;
+ break;
+ case 19200:
+ baudRate = B19200;
+ break;
+ case 38400:
+ baudRate = B38400;
+ break;
+ case 57600:
+ baudRate = B57600;
+ break;
+ case 115200:
+ baudRate = B115200;
+ break;
+ case 230400:
+ baudRate = B230400;
+ break;
+ case 460800:
+ baudRate = B460800;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ success = tcgetattr(_serialPort, &setup);
+ if (success < 0)
+ {
+ errorNumber = errno;
+ perror(0);
+ return 0;
+ }
+
+ cfsetispeed(&setup, baudRate);
+ cfsetospeed(&setup, baudRate);
+ success = tcsetattr(_serialPort, TCSANOW, &setup);
+ if (success < 0)
+ {
+ errorNumber = errno;
+ perror(0);
+ return 0;
+ }
+
+ return 1;
+}
+
+//=============================================================================
+//=============================================================================
+unsigned char SerialDownload::waitForReply(const int transparent)
+{
+ unsigned char c(0);
+ int numberBytes(0);
+ int reply(0);
+
+ struct pollfd commEvent;
+ commEvent.fd = _serialPort;
+ commEvent.events = POLLIN;
+
+ for(;;)
+ {
+ // Wait until a character has received.
+ do
+ {
+ reply = poll(&commEvent, 1, 1000);
+ }
+ while(reply == 0);
+
+ if(commEvent.revents == POLLIN)
+ {
+ do
+ {
+ numberBytes=read(_serialPort, &c, 1);
+ if(transparent && numberBytes)
+ {
+ cout << c;
+ cout.flush();
+ }
+ if((c == STX) ||
+ (c == ETX) ||
+ (c == BEL) ||
+ (c == ACK_OK) ||
+ (c == ACK_NOK))
+ {
+ return c;
+ }
+ }
+ while(numberBytes);
+ }
+ }
+ return 0;
+}
+
+//=============================================================================
+//=============================================================================
+int SerialDownload::connectToSimpad(const int fastBaudRate,
+ int& errorNumber)
+{
+ errorNumber = 0;
+ int bytesWritten;
+ unsigned char c;
+
+ // Switch baud rate to low connecting baud rate.
+ if(!changeBaudRate(38400, errorNumber))
+ {
+ return -1;
+ }
+
+ // Wait for character STX (02) and BEL (07)
+ while(waitForReply(1) != STX);
+ while(waitForReply(1) != BEL);
+ bytesWritten = write(_serialPort, &ACK_BD, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return -2;
+ }
+
+ // Send byte #2 of baud rate
+ c = (fastBaudRate>>16)&0xff;
+ bytesWritten = write(_serialPort, &c, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return -2;
+ }
+
+ // Send byte #1 of baud rate
+ c = (fastBaudRate>>8)&0xff;
+ bytesWritten = write(_serialPort, &c, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return -2;
+ }
+
+ // Send byte #0 of baud rate
+ c = fastBaudRate&0xff;
+ bytesWritten = write(_serialPort, &c, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return -2;
+ }
+
+ c = waitForReply(1);
+ if (c == ACK_OK)
+ {
+ // Switch baud rate to fast baud rate.
+ if(!changeBaudRate(fastBaudRate, errorNumber))
+ {
+ return -3;
+ }
+ }
+
+ // Wait for 1st character with new baud rate.
+ while(waitForReply(1) != STX);
+
+ bytesWritten = write(_serialPort, &STX, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return -4;
+ }
+
+ while(waitForReply(1) != STX);
+ return 0;
+}
+
+//=============================================================================
+//=============================================================================
+bool SerialDownload::sendBlock(const char *buffer,
+ const int length,
+ int& errorNumber)
+{
+ errorNumber = 0;
+ unsigned char c, check=0xff;
+ int i;
+ int bytesWritten;
+
+ while(1)
+ {
+ if(length == 512)
+ {
+ // It's a complete block.
+ bytesWritten = write(_serialPort, buffer, 512);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return 0;
+ }
+ // Create checksum.
+ for(i = 0; i < 512; ++i)
+ {
+ check=(check<<1) ^ buffer[i];
+ }
+ }
+ else
+ {
+ // It's an incomplete block, which must be filled with
+ // the FILLER pattern.
+ char lastBlock[512];
+ for(i = 0; i < 512; ++i)
+ {
+ if(i < length)
+ {
+ // Create checksum.
+ check=(check<<1) ^ buffer[i];
+ lastBlock[i] = buffer[i];
+ }
+ else
+ {
+ // Create checksum
+ check=(check<<1) ^ FILLER;
+ lastBlock[i] = FILLER;
+ }
+ }
+ bytesWritten = write(_serialPort, lastBlock, 512);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return 0;
+ }
+ }
+
+ while(waitForReply(1) != STX);
+
+ if(length == 512)
+ {
+ bytesWritten = write(_serialPort, &STX, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return 0;
+ }
+ }
+ else
+ {
+ // It was the last block.
+ bytesWritten = write(_serialPort, &ETX, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return 0;
+ }
+ }
+
+ // Send checksum.
+ bytesWritten = write(_serialPort, &check, 1);
+ if(!bytesWritten)
+ {
+ errorNumber = errno;
+ return 0;
+ }
+
+ // Wait for ACK_OK as confirmation. Send block again otherwise.
+ c = waitForReply(1);
+ if(c == ACK_OK)
+ {
+ // The block was successfully sent.
+ return 1;
+ }
+ }
+}
+
+//=============================================================================
+//=============================================================================
+void SerialDownload::waitForEndOfBurning(void)
+{
+ // Wait for ETX, which indicates the end of burning.
+ while(waitForReply(1) != ETX);
+
+ // Send the characters "r" (erase registry) and "o" (power off).
+ char c = 'r';
+ int bytesWritten;
+ bytesWritten = write(_serialPort, &c, 1);
+ c = 'o';
+ bytesWritten = write(_serialPort, &c, 1);
+ usleep(7000);
+}
diff --git a/recipes/simpad-utilities/serload/serialdownload.h b/recipes/simpad-utilities/serload/serialdownload.h
new file mode 100644
index 0000000000..1dd05892b1
--- /dev/null
+++ b/recipes/simpad-utilities/serload/serialdownload.h
@@ -0,0 +1,158 @@
+//=============================================================================
+// Project: SIMpad
+//=============================================================================
+// FILE-NAME: serialdownload.hpp
+// FUNCTION: Serial download interface.
+//
+// AUTHOR: Juergen Messerer, Peter Voser
+// CREAT.-DATE: 01.04.2001 (dd.mm.yy)
+//
+// NOTES: -
+//
+//=============================================================================
+
+#ifndef __SERIAL_DOWNLOAD
+#define __SERIAL_DOWNLOAD
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+const unsigned char STX = 2;
+const unsigned char ETX = 3;
+const unsigned char BEL = 7;
+const unsigned char ACK_BD = 11;
+const unsigned char ACK_OK = 6;
+const unsigned char ACK_NOK = 15;
+const unsigned char FILLER = 0xff;
+
+class SerialDownload
+{
+public:
+ SerialDownload();
+ ~SerialDownload();
+//=============================================================================
+// PURPOSE: Opening a serial port.
+//
+// PARAMETERS:
+// portDev: (IN) port device to open.
+// errorNumber: (OUT) error number determined with
+// GetLastError().
+// RETURN VALUE:
+// serialPort: Filedescriptor of opened serial port.
+// If the function fails, it returns -1.
+//
+// COMMENTS: -
+//=============================================================================
+ int openSerialPort(const char* portDev, int &errorNumber);
+
+//=============================================================================
+// PURPOSE: Loading file with a image
+//
+// PARAMETERS:
+// fileName: (IN) name of file to open
+// buffer: (OUT) pointer to loaded image file.
+// numberOfBytes: (OUT) size of file.
+//
+// RETURN VALUE:
+// 0: success
+// -1: specified file not found
+// -2: not enough memory to load file
+// -3: cannot read file
+//
+// COMMENTS: -
+//=============================================================================
+ int loadFile(const char *fileName, char *&buffer, int &numberOfBytes);
+
+//=============================================================================
+// PURPOSE: Connecting to the SIMpad.
+//
+// PARAMETERS:
+// fastBaudRate: (IN) value of fast baud rate.
+// errorNumber: (OUT) error number errno
+//
+// RETURN VALUE:
+// 0: success
+// -1: switching to connection baud rate 38400baud failed.
+// -2: writing to serial port failed.
+// -3: switching to fast baud rate failed.
+// -4: writing to serial port with fast baud rate failed.
+//
+// COMMENTS: The connection is set up according to the bootloader's
+// serial download protocoll.
+//=============================================================================
+ int connectToSimpad(const int fastBaudRate,
+ int& errorNumber);
+
+//=============================================================================
+// PURPOSE: Sending a block of 512byte.
+//
+// PARAMETERS:
+// b: (IN) pointer to the beginning of the 512byte buffer.
+// len: (IN) length of the buffer.
+// errorNumber: (OUT) error number determined with
+// GetLastError().
+// RETURN VALUE:
+// TRUE: success
+// FALSE: error. See errorNumber for the reason.
+//
+// COMMENTS: The block, which is sent, is always 512byte long. If the
+// buffer counts less than 512byte, the block is filled with
+// the FILLER pattern.
+//=============================================================================
+ bool sendBlock(const char *b,
+ const int len,
+ int& errorNumber);
+
+//=============================================================================
+// PURPOSE: Waiting for the end of burning.
+//
+// PARAMETERS: -
+//
+// RETURN VALUE: -
+//
+// COMMENTS: -
+//=============================================================================
+ void waitForEndOfBurning(void);
+
+private:
+ // File descriptor of open serial port.
+ int _serialPort;
+
+//=============================================================================
+// PURPOSE: Changing baud rate.
+//
+// PARAMETERS:
+// newBaudRate: (IN) new baud rate to switch to.
+// errorNumber: (OUT) error number determined with
+// GetLastError().
+//
+// RETURN VALUE:
+// TRUE: success
+// FALSE: error. See errorNumber for the reason.
+//
+// serialMENTS: -
+//=============================================================================
+ bool changeBaudRate(const int newBaudRate,
+ int &errorNumber);
+
+//=============================================================================
+// PURPOSE: Waiting for control character.
+//
+// PARAMETERS:
+// transparent: (IN) 0 = received characters are sent to
+// stdout.
+//
+// RETURN VALUE:
+// c: control character.
+//
+// COMMENTS: -
+//=============================================================================
+ unsigned char waitForReply(const int transparent);
+
+};
+#endif // __SERIAL_DOWNLOAD
diff --git a/recipes/simpad-utilities/serload/serload.1 b/recipes/simpad-utilities/serload/serload.1
new file mode 100644
index 0000000000..4d5738b7de
--- /dev/null
+++ b/recipes/simpad-utilities/serload/serload.1
@@ -0,0 +1,38 @@
+.TH serload 1 19.08.2001 Distribution "SIMpad Serial Download"
+.SH NAME
+serload - Downloading a new image to the SIMpad
+
+.SH SYNOPSIS
+.B serload
+.I [IMAGEFILENAME] [ttyS-PORT]
+
+.SH DESCRIPTION
+.B serload
+downloads a new image to the SIMpad using
+the serial port. You need to connect the SIMpad
+to your PC with the delivered serial crossover cable
+and execute
+.B serload
+with the image name as parameter.
+As an optional parameter, you can provide the serial port
+for
+.B serload
+to use, otherwise, /dev/ttyS0 is assumed as
+default.
+.B serload
+will ask you to reset the SIMpad to
+download the new image. Depending on the image, it will
+be burnt into the Flash or directly executed in the
+RAM without burning.
+.P
+You can update the operating system,
+the firmware (PBL), and the bootloader with this utility. Updating
+the bootloader needs two steps: 1st downloading/burning
+a special bootloader (the so-called alternativ bootloader),
+2nd downloading/burning the new bootloader.
+
+.SH AUTHORS
+Peter Voser, peter.voser@siemens.ch
+.br
+Juergen Messerer, juergen.messerer@siemens.ch
+