OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [monitor/] [monitor/] [common/] [load.c] - Rev 262

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * load.c -- load S-records from serial line
 */
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "load.h"
#include "serial.h"
#include "cpu.h"
#include "mmu.h"
 
 
#define NUM_TRIES	10
#define WAIT_DELAY	350000
 
#define SYN		((unsigned char) 's')
#define ACK		((unsigned char) 'a')
 
#define LINE_SIZE	520
 
 
static Byte line[LINE_SIZE];
 
 
static Word getByte(int index) {
  Word hi, lo;
 
  hi = line[index + 0];
  if (hi >= '0' && hi <= '9') {
    hi -= '0';
  } else
  if (hi >= 'A' && hi <= 'F') {
    hi -= 'A' - 10;
  } else
  if (hi >= 'a' && hi <= 'f') {
    hi -= 'a' - 10;
  } else {
    return (Word) -1;
  }
  lo = line[index + 1];
  if (lo >= '0' && lo <= '9') {
    lo -= '0';
  } else
  if (lo >= 'A' && lo <= 'F') {
    lo -= 'A' - 10;
  } else
  if (lo >= 'a' && lo <= 'f') {
    lo -= 'a' - 10;
  } else {
    return (Word) -1;
  }
  return (hi << 4) | lo;
}
 
 
static void serialOut(int serno, Word c) {
  if (serno == 0) {
    ser0out(c);
  } else {
    ser1out(c);
  }
}
 
 
static int serialChk(int serno) {
  if (serno == 0) {
    return ser0inchk();
  } else {
    return ser1inchk();
  }
}
 
 
static Word serialIn(int serno) {
  if (serno == 0) {
    return ser0in();
  } else {
    return ser1in();
  }
}
 
 
void load(int serno, Bool start) {
  int i, j;
  Bool run;
  int type;
  int count;
  Word chksum;
  Word addr;
  Byte b;
 
  printf("Trying to connect to load server...\n");
  for (i = 0; i < NUM_TRIES; i++) {
    serialOut(serno, SYN);
    for (j = 0; j < WAIT_DELAY; j++) {
      if (serialChk(serno) != 0) {
        break;
      }
    }
    if (j < WAIT_DELAY) {
      break;
    }
    printf("Request timed out...\n");
  }
  if (i == NUM_TRIES ||
      serialIn(serno) != ACK) {
    printf("Unable to establish connection to load server.\n");
    return;
  }
  serialOut(serno, ACK);
  printf("Connected to load server.\n");
  run = true;
  while (run) {
    serialOut(serno, 'r');
    for (i = 0; i < LINE_SIZE; i++) {
      line[i] = serialIn(serno);
      if (line[i] == '\n') {
        break;
      }
    }
    if (i == LINE_SIZE) {
      printf("Error: too many characters in S-record!\n");
      break;
    }
    line[i] = '\0';
    printf("%s\n", line);
    if (line[0] != 'S') {
      printf("Error: malformed S-record!\n");
      break;
    }
    type = line[1];
    count = getByte(2);
    if (i != 2 * count + 4) {
      printf("Error: inconsistent byte count in S-record!\n");
      break;
    }
    chksum = 0;
    for (j = 2; j < i; j += 2) {
      chksum += getByte(j);
    }
    if ((chksum & 0xFF) != 0xFF) {
      printf("Error: wrong checksum in S-record!\n");
      break;
    }
    switch (type) {
      case '0':
        /* S0 record: header (skip) */
        break;
      case '1':
        /* S1 record: 2 byte load address + data (load data) */
        addr = (getByte( 4) <<  8) |
               (getByte( 6) <<  0);
        addr |= 0xC0000000;
        for (j = 0; j < count - 3; j++) {
          b = getByte(2 * j + 8);
          mmuWriteByte(addr + j, b);
        }
        break;
      case '2':
        /* S2 record: 3 byte load address + data (load data) */
        addr = (getByte( 4) << 16) |
               (getByte( 6) <<  8) |
               (getByte( 8) <<  0);
        addr |= 0xC0000000;
        for (j = 0; j < count - 4; j++) {
          b = getByte(2 * j + 10);
          mmuWriteByte(addr + j, b);
        }
        break;
      case '3':
        /* S3 record: 4 byte load address + data (load data) */
        addr = (getByte( 4) << 24) |
               (getByte( 6) << 16) |
               (getByte( 8) <<  8) |
               (getByte(10) <<  0);
        addr |= 0xC0000000;
        for (j = 0; j < count - 5; j++) {
          b = getByte(2 * j + 12);
          mmuWriteByte(addr + j, b);
        }
        break;
      case '5':
        /* S5 record: record count (skip) */
        break;
      case '7':
        /* S7 record: 4 byte start address (set PC, stop loading) */
        addr = (getByte( 4) << 24) |
               (getByte( 6) << 16) |
               (getByte( 8) <<  8) |
               (getByte(10) <<  0);
        addr |= 0xC0000000;
        cpuSetPC(addr);
        run = false;
        break;
      case '8':
        /* S8 record: 3 byte start address (set PC, stop loading) */
        addr = (getByte( 4) << 16) |
               (getByte( 6) <<  8) |
               (getByte( 8) <<  0);
        addr |= 0xC0000000;
        cpuSetPC(addr);
        run = false;
        break;
      case '9':
        /* S9 record: 2 byte start address (set PC, stop loading) */
        addr = (getByte( 4) <<  8) |
               (getByte( 6) <<  0);
        addr |= 0xC0000000;
        cpuSetPC(addr);
        run = false;
        break;
      default:
        /* unknown type of S-record */
        printf("Error: unknown type of S-record!\n");
        run = false;
        break;
    }
  }
  serialOut(serno, 'q');
  printf("Connection to load server closed.\n");
  if (start) {
    cpuRun();
  }
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.