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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-bootloader/] [main.c] - Rev 20

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

/* Copyright (C) 2010, 2011 Embedded Computing Systems Group,
Department of Computer Engineering, Vienna University of Technology.
Contributed by Martin Walter <mwalter@opencores.org>
 
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 
#include <inttypes.h>
#include <machine/UART.h>
#include <machine/modules.h>
 
#if defined __SCARTS_16__
  #include "gdb/sim-scarts_16.h"
  #define SCARTS_ADDR_CTYPE  uint16_t
#elif defined __SCARTS_32__
  #include "gdb/sim-scarts_32.h"
  #define SCARTS_ADDR_CTYPE  uint32_t
#else
  #error "Unsupported target machine type"
#endif
 
#define SCARTS_INSN_SIZE 2
 
#define NUM_HEX_CHARS_PER_BYTE     2
#define SREC_MAX_LINE_LEN         80
#define SREC_FIELD_TYPE_OFFSET     1
#define SREC_FIELD_LENGTH_LEN      2
#define SREC_FIELD_LENGTH_OFFSET   2
#define SREC_FIELD_ADDRESS_OFFSET  4
#define SREC_FIELD_CHECKSUM_LEN    2
#define SREC_TYPE_HEADER           0
#define SREC_TYPE_DATA2            1
#define SREC_TYPE_DATA2_TERM       9
#define SREC_TYPE_DATA4            3
#define SREC_TYPE_DATA4_TERM       7
 
typedef struct
{
  uint8_t           type;
  uint8_t           length;
  uint8_t           address_length;
  SCARTS_ADDR_CTYPE address;
  uint8_t           payload_num_bytes;
  uint8_t           payload_offset;
  uint8_t           size;
} srecord_t;
 
static uint8_t
char_to_int (char c)
{
  if (c >= '0' && c <= '9')
    return c - 48;
  else if (c >= 'A' && c <= 'F')
    return c - 55;
  else
    return 0;
}
 
static void
program_codemem (srecord_t *srec, char *buffer)
{
  int8_t i;
 
  srec->address -= SCARTS_CODEMEM_LMA;
  srec->address /= SCARTS_INSN_SIZE;
 
  /* Iterate over the number of codewords in the current srecord. */
  for (i = 0; i < srec->payload_num_bytes / SCARTS_INSN_SIZE; ++i)
  {
    /* Write the address of the current codeword to
     * the address register of the programmer module. */
    PROGRAMMER_ADDRESS = srec->address + i;
 
    /* Prepare the characters in the buffer to form a proper codeword
     * and write this to the data register of the programmer module. */
    PROGRAMMER_DATA = (char_to_int (buffer[srec->payload_offset + 2]) << 12)
                    + (char_to_int (buffer[srec->payload_offset + 3]) << 8)
                    + (char_to_int (buffer[srec->payload_offset + 0]) << 4)
                    + (char_to_int (buffer[srec->payload_offset + 1]));
 
    /* Advance the payload offset pointer to point to the next codeword. */
    srec->payload_offset += (SCARTS_INSN_SIZE * NUM_HEX_CHARS_PER_BYTE);
 
    /* Tell the programmer module to perform the download. */
    PROGRAMMER_CONFIG_C |= (1 << PROGRAMMER_CONFIG_C_PREXE);
  }
}
 
static void
program_datamem (srecord_t *srec, char *buffer)
{
  int8_t i;
  uint8_t data;
  volatile uint8_t *address;
 
  /* Iterate over the number of data bytes in the current srecord. */
  for (i = 0; i < srec->payload_num_bytes; ++i)
  {
    /* Write the address of the current data byte to
     * the address register of the programmer module. */
    address = (uint8_t *) srec->address + i;
 
    /* Prepare the characters in the buffer to form a proper data byte. */
    data = (char_to_int (buffer[srec->payload_offset + 0]) << 4)
         + (char_to_int (buffer[srec->payload_offset + 1]));
 
    /* Advance the payload offset pointer to point to the next datum. */
    srec->payload_offset += NUM_HEX_CHARS_PER_BYTE;
 
    *address = data;
  }
}
 
int main (int argc, char *argv[])
{
  char buffer[SREC_MAX_LINE_LEN+1];
  int8_t i, j;
  srecord_t srec;
  UART_Cfg cfg;
 
  /* Define the UART settings. */
  cfg.fclk = UART_CFG_FCLK_40MHZ;
  cfg.baud = UART_CFG_BAUD_57600;
  cfg.frame.msg_len = UART_CFG_MSG_LEN_8;
  cfg.frame.parity = UART_CFG_PARITY_EVEN;
  cfg.frame.stop_bits = UART_CFG_STOP_BITS_2;
 
  UART_init (cfg);
  while (1)
  {
    srec.size = UART_read_line (0, buffer, SREC_MAX_LINE_LEN);
 
    if (srec.size == 0)
      continue;
 
    /* Check if the line starts with an 'S'. */
    if (buffer[0] != 'S')
      continue;
 
    /* Extract the srecord type. */
    srec.type = char_to_int (buffer[SREC_FIELD_TYPE_OFFSET]);
 
    /* Extract the srecord length. */
    srec.length = (char_to_int (buffer[SREC_FIELD_LENGTH_OFFSET]) << 4)
                 + char_to_int (buffer[SREC_FIELD_LENGTH_OFFSET + 1]);
 
    /* Process the current srecord. */
    switch (srec.type)
    {
      case SREC_TYPE_DATA4:
      {
        /* Deduce the address field length from the srecord type. */
        srec.address_length = 8;
 
        /* Extract the address at which the payload is to be loaded. */
        srec.address = 0;
        for (i = 0; i < srec.address_length; ++i)
        {
          j = srec.address_length - 1 - i;
          srec.address += char_to_int (buffer[SREC_FIELD_ADDRESS_OFFSET + i]) << 4 * j;
        }
 
        /* Compute the offset and length (bytes) of the payload field. */
        srec.payload_offset = SREC_FIELD_ADDRESS_OFFSET + srec.address_length;
        srec.payload_num_bytes = (srec.size - srec.payload_offset - SREC_FIELD_CHECKSUM_LEN) / NUM_HEX_CHARS_PER_BYTE;
 
        if (srec.address >= SCARTS_CODEMEM_LMA)
          program_codemem (&srec, buffer);
        else
          program_datamem (&srec, buffer);
 
        break;
      }
      case SREC_TYPE_DATA4_TERM:
      {
        /* Set the program counter to SCARTS_CODEMEM_LMA. */
#if defined __SCARTS_16__
        asm ("ldhi r13, 0");
#elif defined __SCARTS_32__
        asm ("ldhi r13, 0");
        asm ("ldliu r13, 0");
        asm ("sli r13, 0x8");
        asm ("ldliu r13, 0");
        asm ("sli r13, 0x8");
#endif
        asm ("ldliu r13, 0");
        asm ("jmp r13");
      }
      default:
        continue;
    }
  }
 
  return 0;
}
 
 

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.