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

Subversion Repositories gecko3

[/] [gecko3/] [trunk/] [GECKO3COM/] [gecko3com-fw/] [firmware/] [src/] [fpga_load.c] - Blame information for rev 36

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

Line No. Rev Author Line
1 9 nussgipfel
/* GECKO3COM
2
 *
3
 * Copyright (C) 2008 by
4
 *   ___    ____  _   _
5
 *  (  _`\ (  __)( ) ( )
6
 *  | (_) )| (_  | |_| |   Bern University of Applied Sciences
7
 *  |  _ <'|  _) |  _  |   School of Engineering and
8
 *  | (_) )| |   | | | |   Information Technology
9
 *  (____/'(_)   (_) (_)
10
 *
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation, either version 3 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
 
25
/*********************************************************************/
26
/** \file     fpga_load.c
27
 *********************************************************************
28
 * \brief     functions to programm an FPGA
29
 *
30
 *            These functions handle the bit file for an Xilinx Spartan3
31
 *            FPGA and programm it in parallel slave mode.
32
 *
33
 * \note      Currently only Xilinx FPGA's are supported, function stubs
34
 *            to handle Altera are provided as a guide for porting.
35
 *
36
 * \author    GNUradio team, Matthias Zurbrügg bfh.ch,
37
 *            Christoph Zimmermann bfh.ch
38
 * \date      2009-1-13
39
 *
40
*/
41
 
42
#include "gecko3com_common.h"
43
#include "gecko3com_regs.h"
44
#include "fpga_load.h"
45
#include "delay.h"
46
#include "debugprint.h"
47
 
48
/* ------------------------------------------------------------------------- */
49
/* Xilinx stuff. We use slave parallel mode (select map) to configure the FPGA
50
 */
51
#ifdef XILINX
52
 
53
/** makro to toggle the configuration clock line */
54
#define toggle_cclk() { \
55
    XILINX_CCLK &= ~bmXILINX_CCLK;      /* bring CCLK low */            \
56
    XILINX_CCLK |= bmXILINX_CCLK;       /* bring CCLK high */           \
57
}
58
 
59
 
60
void init_fpga_interface(void) {
61
 
62
  /* IFCLK is generated internally and runs at 48 MHz; IO Pins configured as normal Ports */
63
  //IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE;
64
  IFCONFIG = bmIFCLKSRC | bmIFCLKOE;
65
  SYNCDELAY;
66
}
67
 
68
 
69
int8_t fpga_scan_file(const xdata unsigned char *p, idata uint16_t *offset, \
70
                       idata uint16_t *length, xdata Fpga_Info* info)
71
{
72 33 nussgipfel
  static idata uint8_t string_length = 0, chars_left_to_read = 0;
73 9 nussgipfel
  xdata uint16_t local_position = *offset;
74
 
75
  for(local_position; local_position < *length; local_position++) {
76 33 nussgipfel
 
77 9 nussgipfel
    /* information found, copy data to output array */
78
    if(chars_left_to_read < string_length) {
79 33 nussgipfel
      //printf_tiny("fi: %d\n",local_position);
80 9 nussgipfel
      info->info[chars_left_to_read++] = p[local_position];
81
 
82
      /* end of information, return successfull */
83
      if(chars_left_to_read == string_length) {
84 33 nussgipfel
        //print_info("l\n");
85 9 nussgipfel
        info->position = local_position;
86
        *offset = local_position+1;
87 33 nussgipfel
        string_length = 0;
88
        chars_left_to_read = 0;
89 9 nussgipfel
        return FPGA_INFO_COMPLETE;
90
      }
91
      else {
92
        continue; /* ignore rest of these loop, load next character */
93
      }
94
    }
95
 
96
    /* search for the start of the desired type of information */
97
    if(chars_left_to_read == 0 && p[local_position] == info->type){
98
      chars_left_to_read = 1;
99
      continue; /* ignore rest of these loop, load next character */
100
    }
101
 
102
    /* start character found, check next character if it is \0 */
103
    if(chars_left_to_read == 1) {
104
      if(p[local_position] == 0) {
105
        chars_left_to_read = 2;
106
 
107
      }
108
      else {
109
        /* false alert, continue searching */
110
        chars_left_to_read = 0;
111
      }
112
      continue; /* ignore rest of these loop, load next character */
113
    }
114
 
115
    /* start of information found, copy length of following string */
116
    if(chars_left_to_read == 2) {
117
      chars_left_to_read = 0;
118
 
119
      if(p[local_position] > FPGA_INFO_LEN) {
120
        string_length = FPGA_INFO_LEN;
121
      }
122
      else {
123
        string_length = p[local_position];
124
      }
125
 
126
      /* exception: file length has a fixed length */
127
      if(info->type == FILE_LENGTH) {
128
        string_length = 3;
129
        chars_left_to_read = 1;
130
        info->info[0] = p[local_position];
131
      }
132
    }
133
 
134
    /* end of for loop. nothing found yet, load next character */
135
  }
136
 
137
 
138
  /* end of packet reached, no info found or not finished copying string */
139
  info->position = local_position;
140
  *offset = local_position;
141
  return FPGA_INFO_NOT_COMPLETE;
142
}
143
 
144
 
145
uint8_t fpga_load_begin(void)
146
{
147
  idata uint8_t i;
148
 
149
  /* enable autopointer 0 */
150
  AUTOPTRSETUP = bmAPTREN | bmAPTR1INC;
151
 
152
  /* CS_B, RDWR_B should be high after board initialization
153
   * but when something went wrong during fpga config the state is unknown */
154
  if(!(XILINX_CS_B | bmXILINX_CS_B) || !(XILINX_RDWR_B | bmXILINX_RDWR_B)) {
155
    /* bring first RDWR_B high to signal ABORT to the FPGA */
156
    XILINX_RDWR_B |= bmXILINX_RDWR_B;
157
 
158
    /* toggle CCLK four times more to complete the abort sequenze  */
159
    for(i=0; i<4; i++) {
160
      toggle_cclk();
161
    }
162
    XILINX_CS_B |= bmXILINX_CS_B;
163
  }
164
 
165
  /* bring Prog_B low brings the device in the initalisation mode */
166
  XILINX_PROG_B &= ~bmXILINX_PROG_B;
167
  udelay(100);                        // and hold it there
168
 
169
  /* bring Prog_B bit high */
170
  XILINX_PROG_B |= bmXILINX_PROG_B;
171
 
172
  /* if Init_B goes high the device is in the configuration load mode */
173
  for(i=0;i<50;i++) {
174
    if(XILINX_INIT_B & bmXILINX_INIT_B) {
175
    //if(1) { /* this line is needed for LA tests, uncomment this and comment the line befor */
176
 
177
      /* bring CS_B, RDWR_B low */
178
      XILINX_RDWR_B &= ~bmXILINX_RDWR_B;
179
      XILINX_CS_B &= ~bmXILINX_CS_B;
180
 
181
      return 1;
182
    }
183
    mdelay(1);
184
  }
185
 
186
  /* FPGA not ready to configure */
187
  return 0;
188
}
189
 
190
 
191
uint8_t fpga_load_xfer(xdata unsigned char *p, idata uint16_t *offset, \
192
                       idata uint16_t *bytecount)
193
{
194
  idata uint16_t local_count;
195
  uint8_t local_data;
196
 
197
  //printf_tiny("off %d ",local_count);
198
  //printf_tiny("c %d\n",*bytecount);
199
 
200
  local_count = *offset;
201
 
202
  /* setup  autopointer source adress from parameter p and the offset */
203
  AUTOPTRH1 = ((uintptr_t)p >> 8);
204
  AUTOPTRL1 = ((uintptr_t)p & 0xFF);
205
  AUTOPTRH1 += (local_count >> 8);
206
  AUTOPTRL1 += (local_count & 0xFF);
207
 
208
  /* setup a for loop to send the data to the fpga data port */
209
  for(local_count; local_count < *bytecount; local_count++ ) {
210
    //XILINX_DATA = AUTODAT1;           // drive Data Port with data
211
    local_data = AUTODAT1;
212
    XILINX_DATA = local_data;
213
 
214
    toggle_cclk();
215
 
216
    //printf_tiny("0x%x ",local_data);
217
 
218
    /* no need for us because we are way to slow that a busy occours */
219
    /* loop while busy is true */
220
    /*while((XILINX_BUSY & bmXILINX_BUSY) ==  bmXILINX_BUSY) {
221
      // if FPGA busy, toggle CCLK
222
      toggle_cclk();
223
    }
224
    */
225
  }
226
 
227
  *offset += *bytecount;
228
  return 1;
229
}
230
 
231
 
232
/*
233
 * check for successful load...
234
 */
235
uint8_t
236
fpga_load_end(void)
237
{
238
  idata uint8_t i;
239
 
240
  /* toggle CCLK four times more to complete the startup sequenze  */
241
  for(i=0; i<4; i++) {
242
    toggle_cclk();
243
  }
244
 
245
  /* bring CS_B, RDWR_B high */
246
  XILINX_CS_B |= bmXILINX_CS_B;
247
  XILINX_RDWR_B |= bmXILINX_RDWR_B;
248
 
249
  if(!fpga_done()) {
250
    /* if not DONE, an error occoured during configuration */
251 21 nussgipfel
    //print_err("fin.\n");
252 9 nussgipfel
    return 0;
253
  }
254
 
255
  return 1;
256
}
257
#endif /* XILINX */
258
 
259
 
260
/* ------------------------------------------------------------------------- */
261
/* Altera stuff. only copied from USRP source code. does not work. only a
262
 * guide to give you a start to port GECKO3COM to other boards using Altera
263
 * devices
264
 */
265
 
266
#ifdef ALTERA
267
/*
268
 * setup altera FPGA serial load (PS).
269
 *
270
 * On entry:
271
 *      don't care
272
 *
273
 * On exit:
274
 *      ALTERA_DCLK    = 0
275
 *      ALTERA_NCONFIG = 1
276
 *      ALTERA_NSTATUS = 1 (input)
277
 */
278
uint8_t
279
fpga_load_begin(void)
280
{
281
  ALTERA_CONFIG &= ~bmALTERA_BITS;              // clear all bits (NCONFIG low)
282
  udelay (40);                                  // wait 40 us
283
  ALTERA_CONFIG |= bmALTERA_NCONFIG;    // set NCONFIG high
284
 
285
  if (UC_BOARD_HAS_FPGA){
286
    // FIXME should really cap this loop with a counter so we
287
    //   don't hang forever on a hardware failure.
288
    while ((USRP_ALTERA_CONFIG & bmALTERA_NSTATUS) == 0) // wait for NSTATUS to go high
289
      ;
290
  }
291
 
292
  // ready to xfer now
293
 
294
  return 1;
295
}
296
 
297
/*
298
 * clock out the low bit of bits.
299
 *
300
 * On entry:
301
 *      ALTERA_DCLK    = 0
302
 *      ALTERA_NCONFIG = 1
303
 *      ALTERA_NSTATUS = 1 (input)
304
 *
305
 * On exit:
306
 *      ALTERA_DCLK    = 0
307
 *      ALTERA_NCONFIG = 1
308
 *      ALTERA_NSTATUS = 1 (input)
309
 */
310
 
311
static void
312
clock_out_config_byte(const uint8_t bits) _naked
313
{
314
    _asm
315
        mov     a, dpl
316
 
317
        rrc     a
318
        mov     _bitALTERA_DATA0,c
319
        setb    _bitALTERA_DCLK
320
        clr     _bitALTERA_DCLK
321
 
322
        rrc     a
323
        mov     _bitALTERA_DATA0,c
324
        setb    _bitALTERA_DCLK
325
        clr     _bitALTERA_DCLK
326
 
327
        rrc     a
328
        mov     _bitALTERA_DATA0,c
329
        setb    _bitALTERA_DCLK
330
        clr     _bitALTERA_DCLK
331
 
332
        rrc     a
333
        mov     _bitALTERA_DATA0,c
334
        setb    _bitALTERA_DCLK
335
        clr     _bitALTERA_DCLK
336
 
337
        rrc     a
338
        mov     _bitALTERA_DATA0,c
339
        setb    _bitALTERA_DCLK
340
        clr     _bitALTERA_DCLK
341
 
342
        rrc     a
343
        mov     _bitALTERA_DATA0,c
344
        setb    _bitALTERA_DCLK
345
        clr     _bitALTERA_DCLK
346
 
347
        rrc     a
348
        mov     _bitALTERA_DATA0,c
349
        setb    _bitALTERA_DCLK
350
        clr     _bitALTERA_DCLK
351
 
352
        rrc     a
353
        mov     _bitALTERA_DATA0,c
354
        setb    _bitALTERA_DCLK
355
        clr     _bitALTERA_DCLK
356
 
357
        ret
358
 
359
    _endasm;
360
}
361
 
362
static void
363
clock_out_bytes(const uint8_t bytecount,
364
                 uint8_t xdata *p)
365
{
366
  while (bytecount-- > 0)
367
    clock_out_config_byte (*p++);
368
}
369
 
370
/*
371
 * Transfer block of bytes from packet to FPGA serial configuration port
372
 *
373
 * On entry:
374
 *      ALTERA_DCLK    = 0
375
 *      ALTERA_NCONFIG = 1
376
 *      ALTERA_NSTATUS = 1 (input)
377
 *
378
 * On exit:
379
 *      ALTERA_DCLK    = 0
380
 *      ALTERA_NCONFIG = 1
381
 *      ALTERA_NSTATUS = 1 (input)
382
 */
383
uint8_t
384
fpga_load_xfer(const xdata uint8_t *p, const uint8_t bytecount)
385
{
386
  clock_out_bytes (bytecount, p);
387
  return 1;
388
}
389
 
390
/*
391
 * check for successful load...
392
 */
393
uint8_t
394
fpga_load_end(void)
395
{
396
  uint8_t status = ALTERA_CONFIG;
397
 
398
  if (!UC_BOARD_HAS_FPGA)                       // always true if we don't have FPGA
399
    return 1;
400
 
401
  if ((status & bmALTERA_NSTATUS) == 0)          // failed to program
402
    return 0;
403
 
404
  if ((status & bmALTERA_CONF_DONE) == bmALTERA_CONF_DONE)
405
    return 1;                                   // everything's cool
406
 
407
  // I don't think this should happen.  It indicates that
408
  // programming is still in progress.
409
 
410
  return 0;
411
}
412
 
413
#endif /* ALTERA */

powered by: WebSVN 2.1.0

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