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 21

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
  idata uint8_t string_length = 0, chars_left_to_read = 0;
73
  xdata uint16_t local_position = *offset;
74
 
75
  for(local_position; local_position < *length; local_position++) {
76
    //printf_tiny("fi: %d\n",local_position);
77
    /* information found, copy data to output array */
78
    if(chars_left_to_read < string_length) {
79
      info->info[chars_left_to_read++] = p[local_position];
80
 
81
      /* end of information, return successfull */
82
      if(chars_left_to_read == string_length) {
83
        info->position = local_position;
84
        *offset = local_position+1;
85
        return FPGA_INFO_COMPLETE;
86
      }
87
      else {
88
        continue; /* ignore rest of these loop, load next character */
89
      }
90
    }
91
 
92
    /* search for the start of the desired type of information */
93
    if(chars_left_to_read == 0 && p[local_position] == info->type){
94
      chars_left_to_read = 1;
95
      continue; /* ignore rest of these loop, load next character */
96
    }
97
 
98
    /* start character found, check next character if it is \0 */
99
    if(chars_left_to_read == 1) {
100
      if(p[local_position] == 0) {
101
        chars_left_to_read = 2;
102
 
103
      }
104
      else {
105
        /* false alert, continue searching */
106
        chars_left_to_read = 0;
107
      }
108
      continue; /* ignore rest of these loop, load next character */
109
    }
110
 
111
    /* start of information found, copy length of following string */
112
    if(chars_left_to_read == 2) {
113
      chars_left_to_read = 0;
114
 
115
      if(p[local_position] > FPGA_INFO_LEN) {
116
        string_length = FPGA_INFO_LEN;
117
      }
118
      else {
119
        string_length = p[local_position];
120
      }
121
 
122
      /* exception: file length has a fixed length */
123
      if(info->type == FILE_LENGTH) {
124
        string_length = 3;
125
        chars_left_to_read = 1;
126
        info->info[0] = p[local_position];
127
      }
128
    }
129
 
130
    /* end of for loop. nothing found yet, load next character */
131
  }
132
 
133
 
134
  /* end of packet reached, no info found or not finished copying string */
135
  info->position = local_position;
136
  *offset = local_position;
137
  return FPGA_INFO_NOT_COMPLETE;
138
}
139
 
140
 
141
uint8_t fpga_load_begin(void)
142
{
143
  idata uint8_t i;
144
 
145
  /* enable autopointer 0 */
146
  AUTOPTRSETUP = bmAPTREN | bmAPTR1INC;
147
 
148
  /* CS_B, RDWR_B should be high after board initialization
149
   * but when something went wrong during fpga config the state is unknown */
150
  if(!(XILINX_CS_B | bmXILINX_CS_B) || !(XILINX_RDWR_B | bmXILINX_RDWR_B)) {
151
    /* bring first RDWR_B high to signal ABORT to the FPGA */
152
    XILINX_RDWR_B |= bmXILINX_RDWR_B;
153
 
154
    /* toggle CCLK four times more to complete the abort sequenze  */
155
    for(i=0; i<4; i++) {
156
      toggle_cclk();
157
    }
158
    XILINX_CS_B |= bmXILINX_CS_B;
159
  }
160
 
161
  /* bring Prog_B low brings the device in the initalisation mode */
162
  XILINX_PROG_B &= ~bmXILINX_PROG_B;
163
  udelay(100);                        // and hold it there
164
 
165
  /* bring Prog_B bit high */
166
  XILINX_PROG_B |= bmXILINX_PROG_B;
167
 
168
  /* if Init_B goes high the device is in the configuration load mode */
169
  for(i=0;i<50;i++) {
170
    if(XILINX_INIT_B & bmXILINX_INIT_B) {
171
    //if(1) { /* this line is needed for LA tests, uncomment this and comment the line befor */
172
 
173
      /* bring CS_B, RDWR_B low */
174
      XILINX_RDWR_B &= ~bmXILINX_RDWR_B;
175
      XILINX_CS_B &= ~bmXILINX_CS_B;
176
 
177
      return 1;
178
    }
179
    mdelay(1);
180
  }
181
 
182
  /* FPGA not ready to configure */
183
  return 0;
184
}
185
 
186
 
187
uint8_t fpga_load_xfer(xdata unsigned char *p, idata uint16_t *offset, \
188
                       idata uint16_t *bytecount)
189
{
190
  idata uint16_t local_count;
191
  uint8_t local_data;
192
 
193
  //printf_tiny("off %d ",local_count);
194
  //printf_tiny("c %d\n",*bytecount);
195
 
196
  local_count = *offset;
197
 
198
  /* setup  autopointer source adress from parameter p and the offset */
199
  AUTOPTRH1 = ((uintptr_t)p >> 8);
200
  AUTOPTRL1 = ((uintptr_t)p & 0xFF);
201
  AUTOPTRH1 += (local_count >> 8);
202
  AUTOPTRL1 += (local_count & 0xFF);
203
 
204
  /* setup a for loop to send the data to the fpga data port */
205
  for(local_count; local_count < *bytecount; local_count++ ) {
206
    //XILINX_DATA = AUTODAT1;           // drive Data Port with data
207
    local_data = AUTODAT1;
208
    XILINX_DATA = local_data;
209
 
210
    toggle_cclk();
211
 
212
    //printf_tiny("0x%x ",local_data);
213
 
214
    /* no need for us because we are way to slow that a busy occours */
215
    /* loop while busy is true */
216
    /*while((XILINX_BUSY & bmXILINX_BUSY) ==  bmXILINX_BUSY) {
217
      // if FPGA busy, toggle CCLK
218
      toggle_cclk();
219
    }
220
    */
221
  }
222
 
223
  *offset += *bytecount;
224
  return 1;
225
}
226
 
227
 
228
/*
229
 * check for successful load...
230
 */
231
uint8_t
232
fpga_load_end(void)
233
{
234
  idata uint8_t i;
235
 
236
  /* toggle CCLK four times more to complete the startup sequenze  */
237
  for(i=0; i<4; i++) {
238
    toggle_cclk();
239
  }
240
 
241
  /* bring CS_B, RDWR_B high */
242
  XILINX_CS_B |= bmXILINX_CS_B;
243
  XILINX_RDWR_B |= bmXILINX_RDWR_B;
244
 
245
  if(!fpga_done()) {
246
    /* if not DONE, an error occoured during configuration */
247 21 nussgipfel
    //print_err("fin.\n");
248 9 nussgipfel
    return 0;
249
  }
250
 
251
  return 1;
252
}
253
#endif /* XILINX */
254
 
255
 
256
/* ------------------------------------------------------------------------- */
257
/* Altera stuff. only copied from USRP source code. does not work. only a
258
 * guide to give you a start to port GECKO3COM to other boards using Altera
259
 * devices
260
 */
261
 
262
#ifdef ALTERA
263
/*
264
 * setup altera FPGA serial load (PS).
265
 *
266
 * On entry:
267
 *      don't care
268
 *
269
 * On exit:
270
 *      ALTERA_DCLK    = 0
271
 *      ALTERA_NCONFIG = 1
272
 *      ALTERA_NSTATUS = 1 (input)
273
 */
274
uint8_t
275
fpga_load_begin(void)
276
{
277
  ALTERA_CONFIG &= ~bmALTERA_BITS;              // clear all bits (NCONFIG low)
278
  udelay (40);                                  // wait 40 us
279
  ALTERA_CONFIG |= bmALTERA_NCONFIG;    // set NCONFIG high
280
 
281
  if (UC_BOARD_HAS_FPGA){
282
    // FIXME should really cap this loop with a counter so we
283
    //   don't hang forever on a hardware failure.
284
    while ((USRP_ALTERA_CONFIG & bmALTERA_NSTATUS) == 0) // wait for NSTATUS to go high
285
      ;
286
  }
287
 
288
  // ready to xfer now
289
 
290
  return 1;
291
}
292
 
293
/*
294
 * clock out the low bit of bits.
295
 *
296
 * On entry:
297
 *      ALTERA_DCLK    = 0
298
 *      ALTERA_NCONFIG = 1
299
 *      ALTERA_NSTATUS = 1 (input)
300
 *
301
 * On exit:
302
 *      ALTERA_DCLK    = 0
303
 *      ALTERA_NCONFIG = 1
304
 *      ALTERA_NSTATUS = 1 (input)
305
 */
306
 
307
static void
308
clock_out_config_byte(const uint8_t bits) _naked
309
{
310
    _asm
311
        mov     a, dpl
312
 
313
        rrc     a
314
        mov     _bitALTERA_DATA0,c
315
        setb    _bitALTERA_DCLK
316
        clr     _bitALTERA_DCLK
317
 
318
        rrc     a
319
        mov     _bitALTERA_DATA0,c
320
        setb    _bitALTERA_DCLK
321
        clr     _bitALTERA_DCLK
322
 
323
        rrc     a
324
        mov     _bitALTERA_DATA0,c
325
        setb    _bitALTERA_DCLK
326
        clr     _bitALTERA_DCLK
327
 
328
        rrc     a
329
        mov     _bitALTERA_DATA0,c
330
        setb    _bitALTERA_DCLK
331
        clr     _bitALTERA_DCLK
332
 
333
        rrc     a
334
        mov     _bitALTERA_DATA0,c
335
        setb    _bitALTERA_DCLK
336
        clr     _bitALTERA_DCLK
337
 
338
        rrc     a
339
        mov     _bitALTERA_DATA0,c
340
        setb    _bitALTERA_DCLK
341
        clr     _bitALTERA_DCLK
342
 
343
        rrc     a
344
        mov     _bitALTERA_DATA0,c
345
        setb    _bitALTERA_DCLK
346
        clr     _bitALTERA_DCLK
347
 
348
        rrc     a
349
        mov     _bitALTERA_DATA0,c
350
        setb    _bitALTERA_DCLK
351
        clr     _bitALTERA_DCLK
352
 
353
        ret
354
 
355
    _endasm;
356
}
357
 
358
static void
359
clock_out_bytes(const uint8_t bytecount,
360
                 uint8_t xdata *p)
361
{
362
  while (bytecount-- > 0)
363
    clock_out_config_byte (*p++);
364
}
365
 
366
/*
367
 * Transfer block of bytes from packet to FPGA serial configuration port
368
 *
369
 * On entry:
370
 *      ALTERA_DCLK    = 0
371
 *      ALTERA_NCONFIG = 1
372
 *      ALTERA_NSTATUS = 1 (input)
373
 *
374
 * On exit:
375
 *      ALTERA_DCLK    = 0
376
 *      ALTERA_NCONFIG = 1
377
 *      ALTERA_NSTATUS = 1 (input)
378
 */
379
uint8_t
380
fpga_load_xfer(const xdata uint8_t *p, const uint8_t bytecount)
381
{
382
  clock_out_bytes (bytecount, p);
383
  return 1;
384
}
385
 
386
/*
387
 * check for successful load...
388
 */
389
uint8_t
390
fpga_load_end(void)
391
{
392
  uint8_t status = ALTERA_CONFIG;
393
 
394
  if (!UC_BOARD_HAS_FPGA)                       // always true if we don't have FPGA
395
    return 1;
396
 
397
  if ((status & bmALTERA_NSTATUS) == 0)          // failed to program
398
    return 0;
399
 
400
  if ((status & bmALTERA_CONF_DONE) == bmALTERA_CONF_DONE)
401
    return 1;                                   // everything's cool
402
 
403
  // I don't think this should happen.  It indicates that
404
  // programming is still in progress.
405
 
406
  return 0;
407
}
408
 
409
#endif /* ALTERA */

powered by: WebSVN 2.1.0

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