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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-bootloader/] [main.c] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 jlechner
/* Copyright (C) 2010, 2011 Embedded Computing Systems Group,
2
Department of Computer Engineering, Vienna University of Technology.
3
Contributed by Martin Walter <mwalter@opencores.org>
4
 
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published
7
by the Free Software Foundation, either version 2.1 of the License, or
8
(at your option) any later version.
9
 
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU Lesser General Public License for more details.
14
 
15
You should have received a copy of the GNU Lesser General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17
 
18
 
19
#include <inttypes.h>
20
#include <machine/UART.h>
21
#include <machine/modules.h>
22
 
23
#if defined __SCARTS_16__
24
  #include "gdb/sim-scarts_16.h"
25
  #define SCARTS_ADDR_CTYPE  uint16_t
26
#elif defined __SCARTS_32__
27
  #include "gdb/sim-scarts_32.h"
28
  #define SCARTS_ADDR_CTYPE  uint32_t
29
#else
30
  #error "Unsupported target machine type"
31
#endif
32
 
33
#define SCARTS_INSN_SIZE 2
34
 
35
#define NUM_HEX_CHARS_PER_BYTE     2
36
#define SREC_MAX_LINE_LEN         80
37
#define SREC_FIELD_TYPE_OFFSET     1
38
#define SREC_FIELD_LENGTH_LEN      2
39
#define SREC_FIELD_LENGTH_OFFSET   2
40
#define SREC_FIELD_ADDRESS_OFFSET  4
41
#define SREC_FIELD_CHECKSUM_LEN    2
42
#define SREC_TYPE_HEADER           0
43
#define SREC_TYPE_DATA2            1
44
#define SREC_TYPE_DATA2_TERM       9
45
#define SREC_TYPE_DATA4            3
46
#define SREC_TYPE_DATA4_TERM       7
47
 
48
typedef struct
49
{
50
  uint8_t           type;
51
  uint8_t           length;
52
  uint8_t           address_length;
53
  SCARTS_ADDR_CTYPE address;
54
  uint8_t           payload_num_bytes;
55
  uint8_t           payload_offset;
56
  uint8_t           size;
57
} srecord_t;
58
 
59
static uint8_t
60
char_to_int (char c)
61
{
62
  if (c >= '0' && c <= '9')
63
    return c - 48;
64
  else if (c >= 'A' && c <= 'F')
65
    return c - 55;
66
  else
67
    return 0;
68
}
69
 
70
static void
71
program_codemem (srecord_t *srec, char *buffer)
72
{
73
  int8_t i;
74
 
75
  srec->address -= SCARTS_CODEMEM_LMA;
76
  srec->address /= SCARTS_INSN_SIZE;
77
 
78
  /* Iterate over the number of codewords in the current srecord. */
79
  for (i = 0; i < srec->payload_num_bytes / SCARTS_INSN_SIZE; ++i)
80
  {
81
    /* Write the address of the current codeword to
82
     * the address register of the programmer module. */
83
    PROGRAMMER_ADDRESS = srec->address + i;
84
 
85
    /* Prepare the characters in the buffer to form a proper codeword
86
     * and write this to the data register of the programmer module. */
87
    PROGRAMMER_DATA = (char_to_int (buffer[srec->payload_offset + 2]) << 12)
88
                    + (char_to_int (buffer[srec->payload_offset + 3]) << 8)
89
                    + (char_to_int (buffer[srec->payload_offset + 0]) << 4)
90
                    + (char_to_int (buffer[srec->payload_offset + 1]));
91
 
92
    /* Advance the payload offset pointer to point to the next codeword. */
93
    srec->payload_offset += (SCARTS_INSN_SIZE * NUM_HEX_CHARS_PER_BYTE);
94
 
95
    /* Tell the programmer module to perform the download. */
96
    PROGRAMMER_CONFIG_C |= (1 << PROGRAMMER_CONFIG_C_PREXE);
97
  }
98
}
99
 
100
static void
101
program_datamem (srecord_t *srec, char *buffer)
102
{
103
  int8_t i;
104
  uint8_t data;
105
  volatile uint8_t *address;
106
 
107
  /* Iterate over the number of data bytes in the current srecord. */
108
  for (i = 0; i < srec->payload_num_bytes; ++i)
109
  {
110
    /* Write the address of the current data byte to
111
     * the address register of the programmer module. */
112
    address = (uint8_t *) srec->address + i;
113
 
114
    /* Prepare the characters in the buffer to form a proper data byte. */
115
    data = (char_to_int (buffer[srec->payload_offset + 0]) << 4)
116
         + (char_to_int (buffer[srec->payload_offset + 1]));
117
 
118
    /* Advance the payload offset pointer to point to the next datum. */
119
    srec->payload_offset += NUM_HEX_CHARS_PER_BYTE;
120
 
121
    *address = data;
122
  }
123
}
124
 
125
int main (int argc, char *argv[])
126
{
127
  char buffer[SREC_MAX_LINE_LEN+1];
128
  int8_t i, j;
129
  srecord_t srec;
130
  UART_Cfg cfg;
131
 
132
  /* Define the UART settings. */
133
  cfg.fclk = UART_CFG_FCLK_40MHZ;
134
  cfg.baud = UART_CFG_BAUD_57600;
135
  cfg.frame.msg_len = UART_CFG_MSG_LEN_8;
136
  cfg.frame.parity = UART_CFG_PARITY_EVEN;
137
  cfg.frame.stop_bits = UART_CFG_STOP_BITS_2;
138
 
139
  UART_init (cfg);
140
  while (1)
141
  {
142
    srec.size = UART_read_line (0, buffer, SREC_MAX_LINE_LEN);
143
 
144
    if (srec.size == 0)
145
      continue;
146
 
147
    /* Check if the line starts with an 'S'. */
148
    if (buffer[0] != 'S')
149
      continue;
150
 
151
    /* Extract the srecord type. */
152
    srec.type = char_to_int (buffer[SREC_FIELD_TYPE_OFFSET]);
153
 
154
    /* Extract the srecord length. */
155
    srec.length = (char_to_int (buffer[SREC_FIELD_LENGTH_OFFSET]) << 4)
156
                 + char_to_int (buffer[SREC_FIELD_LENGTH_OFFSET + 1]);
157
 
158
    /* Process the current srecord. */
159
    switch (srec.type)
160
    {
161
      case SREC_TYPE_DATA4:
162
      {
163
        /* Deduce the address field length from the srecord type. */
164
        srec.address_length = 8;
165
 
166
        /* Extract the address at which the payload is to be loaded. */
167
        srec.address = 0;
168
        for (i = 0; i < srec.address_length; ++i)
169
        {
170
          j = srec.address_length - 1 - i;
171
          srec.address += char_to_int (buffer[SREC_FIELD_ADDRESS_OFFSET + i]) << 4 * j;
172
        }
173
 
174
        /* Compute the offset and length (bytes) of the payload field. */
175
        srec.payload_offset = SREC_FIELD_ADDRESS_OFFSET + srec.address_length;
176
        srec.payload_num_bytes = (srec.size - srec.payload_offset - SREC_FIELD_CHECKSUM_LEN) / NUM_HEX_CHARS_PER_BYTE;
177
 
178
        if (srec.address >= SCARTS_CODEMEM_LMA)
179
          program_codemem (&srec, buffer);
180
        else
181
          program_datamem (&srec, buffer);
182
 
183
        break;
184
      }
185
      case SREC_TYPE_DATA4_TERM:
186
      {
187
        /* Set the program counter to SCARTS_CODEMEM_LMA. */
188
#if defined __SCARTS_16__
189
        asm ("ldhi r13, 0");
190
#elif defined __SCARTS_32__
191
        asm ("ldhi r13, 0");
192
        asm ("ldliu r13, 0");
193
        asm ("sli r13, 0x8");
194
        asm ("ldliu r13, 0");
195
        asm ("sli r13, 0x8");
196
#endif
197
        asm ("ldliu r13, 0");
198
        asm ("jmp r13");
199
      }
200
      default:
201
        continue;
202
    }
203
  }
204
 
205
  return 0;
206
}
207
 

powered by: WebSVN 2.1.0

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