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

Subversion Repositories gecko3

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

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     gecko3com_main.c
27
 *********************************************************************
28
 * \brief     main file for the GECKO3COM project
29
 *
30
 * \author    Christoph Zimmermann bfh.ch
31
 * \date      2009-1-22
32
 *
33
*/
34
 
35
/** enable DFU class support */
36
#define USB_DFU_SUPPORT
37
 
38
#include <string.h>
39
#include <stdint.h>
40
 
41
#include "fx2utils.h"
42
#include "timer.h"
43
#include "spi_flash.h"
44
#include "i2c.h"
45
#include "isr.h"
46
#include "eeprom_io.h"
47
#include "delay.h"
48
 
49
#include "gecko3com_i2c.h"
50
#include "gecko3com_spi.h"
51
#include "gecko3com_common.h"
52
#include "gecko3com_interfaces.h"
53
#include "gecko3com_commands.h"
54
#include "fpga_load.h"
55
 
56
#include "gecko3com_gpif.h"
57
#include "gpif_data.h"
58
 
59
#include "usb_common.h"
60
#include "usb_requests.h"
61
#include "usb_descriptors.h"
62
#include "usb_dfu.h"
63
#include "usb_tmc.h"
64
#include "scpi_parser.h"
65
 
66
#include "firmware_version.h"
67
#include "debugprint.h"
68
#ifdef DEBUG_LEVEL_ERROR
69
#include "ser.h"
70
#endif
71
 
72 32 nussgipfel
/* -------------------------------------------------------------------------- */
73 9 nussgipfel
 
74
#define WATCHDOG_TIME           100 /**< time until the watchdog times out, 100 equals 1 second */
75
 
76
 
77 32 nussgipfel
/* Global variables --------------------------------------------------------- */
78 9 nussgipfel
 
79 32 nussgipfel
/** watchdog counter variable (UNUSED) */
80
volatile uint8_t watchdog_count = WATCHDOG_TIME;
81
 
82
/** the filesize of an fpga configuration file, read from the bit file header */
83
idata int32_t file_size;
84
 
85
/** stores the current used addres for spi flash access */
86
xdata uint32_t flash_adress;
87
/** general pointer to pass the place where to read data to different
88
functions (normally endpoint buffer) */
89
xdata unsigned char *buffer;
90
 
91
xdata TMC_Response_Queue response_queue; /**< buffer to hold the TMC response */
92
 
93
 
94 9 nussgipfel
/** \brief with executing this function, we confirm that we handled the
95
 *  endpoint 0 data and that we are ready to get new data (rearm the endpoint).
96
 */
97
static void get_ep0_data (void)
98
{
99
  EP0BCL = 0;            /* arm EP0 for OUT xfer.  This sets the busy bit */
100
 
101
  while (EP0CS & bmEPBUSY)      /* wait for busy to clear */
102
    ;
103
}
104
 
105
 
106
/*
107
 * enable debug output through the serial uart
108
 */
109
#ifdef DEBUG_LEVEL_ERROR
110
 
111
/** \brief simple wraper to provide putchar function over serial line */
112
void putchar (char p)
113
{
114
  ser_putc((unsigned char) p);
115
}
116
 
117
 
118
/** \brief simple wraper to provide getchar function over serial line */
119
char getchar (void)
120
{
121
  return (char) ser_getc();
122
}
123
#endif
124
 
125
 
126
#ifdef USB_DFU_SUPPORT
127 32 nussgipfel
/** \brief this function writes the new firmware data in endpoint 0 to the I2C \
128
 *  eeprom.
129
 * \note this function is only available when the DFU (device firware upgrade) \
130
 * class support is enabled.
131 9 nussgipfel
 */
132
uint8_t app_firmware_write (void)
133
{
134
  static uint16_t eeprom_offset;
135
 
136
  get_ep0_data();
137
 
138
  if(usb_dfu_state == DFU_STATE_dfuIDLE){
139
    eeprom_offset = 0;
140
  }
141
 
142
  //  if(!eeprom_write(I2C_ADDR_BOOT, eeprom_offset, EP0BUF, wLengthL)){
143
  if(!eeprom_write(eeprom_offset, EP0BUF, wLengthL)){
144
    usb_dfu_status = DFU_STATUS_errWRITE;
145
    return 0;
146
  }
147
 
148
  eeprom_offset += wLengthL;
149
  return 1;
150
}
151
#endif
152
 
153
 
154
/** \brief analyze the header from the fpga configuration file and compares the
155
 *  the fpga type with the on board fpga and returs the configuration file size.
156
 *
157 32 nussgipfel
 * \param[in] *offset pointer to the offset, buffer[offset]
158 9 nussgipfel
 *            is the current position, anything before this is already consumed.
159 32 nussgipfel
 * \param[in] *byte_count pointer to the length of the whole buffer.
160 9 nussgipfel
 * \return    returns non-zero if successful, else 0
161
 */
162 32 nussgipfel
uint8_t app_check_fpga_type_from_header(idata uint16_t *offset,         \
163 9 nussgipfel
                                        idata uint16_t *byte_count)
164
{
165
  static xdata Fpga_Info fpga_file_header;
166
  xdata char fpga_type[FPGA_TYPE_LEN];
167
  static int8_t continue_analyse;
168
 
169
  /* check if this is the first attempt to analyse the bit file header*/
170
  if(usb_tmc_transfer.new_transfer == NEWTRANSFER) {
171
    continue_analyse = 0;
172
    fpga_file_header.type = FPGA_TYPE;
173 33 nussgipfel
    usb_tmc_transfer.transfer_size += USB_TMC_HEADER_SIZE;
174 9 nussgipfel
  }
175 33 nussgipfel
 
176 9 nussgipfel
  /* first value to read from the header file is the fpga type */
177
  if(fpga_file_header.type == FPGA_TYPE){
178 33 nussgipfel
 
179 9 nussgipfel
    if(fpga_scan_file(buffer, offset, byte_count, &fpga_file_header)    \
180
       == FPGA_INFO_COMPLETE) {
181
      /* compare fpga type from header with value in eeprom */
182
      if(!eeprom_read(FPGA_TYPE_OFFSET, fpga_type, FPGA_TYPE_LEN)){
183
        return 0;
184
      }
185
 
186
      if(strncmp(fpga_file_header.info, fpga_type, FPGA_TYPE_LEN)) {
187
        //print_err("!FPGA\n");
188
        return 0;
189
      }
190
 
191
      /* next value to read from the header is the file length */
192
      fpga_file_header.type = FILE_LENGTH;
193
      continue_analyse = FPGA_INFO_COMPLETE;
194
    }
195
    else {
196
      continue_analyse = FPGA_INFO_NOT_COMPLETE;
197
    }
198
  }
199
 
200
  /* second value to read from the header file is the file length */
201
  if(fpga_file_header.type == FILE_LENGTH){
202 33 nussgipfel
 
203 9 nussgipfel
    if(fpga_scan_file(buffer, offset, byte_count, &fpga_file_header)    \
204
       == FPGA_INFO_COMPLETE) {
205
      ((uint8_t*)&file_size)[0] = fpga_file_header.info[2];
206
      ((uint8_t*)&file_size)[1] = fpga_file_header.info[1];
207
      ((uint8_t*)&file_size)[2] = fpga_file_header.info[0];
208
      ((uint8_t*)&file_size)[3] = 0;
209
 
210
      continue_analyse = FPGA_INFO_COMPLETE;
211
    }
212
    else {
213
      continue_analyse = FPGA_INFO_NOT_COMPLETE;
214
    }
215
  }
216
 
217
  /* adjust the offset and byte_count variables to point to the
218
   * binary data after the header */
219
  usb_tmc_transfer.transfer_size -= *offset;
220
 
221
  return continue_analyse;
222
}
223
 
224
 
225
/** \brief function to configure an fpga with data from usb
226
 *
227 32 nussgipfel
 * \param[in] *offset pointer to the offset, buffer[offset]
228 9 nussgipfel
 *            is the current position, anything before this is already consumed.
229 32 nussgipfel
 * \param[in] *byte_count pointer to the length of the whole buffer.
230 9 nussgipfel
 * \return    returns non-zero if successful, else 0
231
 */
232 32 nussgipfel
uint8_t app_configure_fpga(idata uint16_t *offset,      \
233 9 nussgipfel
                           idata uint16_t *byte_count)
234
{
235
  /* Is this the first part of configuration? */
236
  if(usb_tmc_transfer.nbytes_rxd == 0) {
237
    /* setup all stuff */
238
    file_size = 0;
239
  }
240
 
241
  /* do we still analyze the file header? */
242
  if(file_size == 0) {
243
    if(!app_check_fpga_type_from_header(offset, byte_count)) {
244 33 nussgipfel
      //print_err("bad\n");
245 9 nussgipfel
      return 0;
246
    }
247
 
248
    /* are we now finished analyzing? */
249
    if(file_size != 0) {
250
      /* if yes, intialize fpga for configuration */
251
      //print_info("begin\n");
252
      fpga_load_begin();
253
    }
254
  }
255
 
256
  /* anything ready, transfer data to fpga */
257
  if(file_size != 0) {
258
    /* transmitt config data to fpga */
259
    usb_tmc_transfer.transfer_size -= *byte_count;
260
    usb_tmc_transfer.transfer_size += *offset;
261
    file_size -= *byte_count;
262
    file_size += *offset;
263
 
264
    fpga_load_xfer(buffer, offset, byte_count);
265
 
266
    //printf_tiny("buffer[0], %d\n",buffer[0]);
267
 
268
    /* transfer finished, finishing configuration */
269
    if(file_size == 0) {
270 33 nussgipfel
      //print_info("end\n");
271 9 nussgipfel
      if(!fpga_load_end()) {
272
        return 0;
273
      }
274
      usb_tmc_state = TMC_STATE_IDLE;
275
    }
276
  }
277
 
278
  return 1;
279
}
280
 
281
 
282
/** \brief function to write an fpga configuration from usb to the spi flash
283
 *
284 32 nussgipfel
 * The SPI flash is big enough to hold store two different fpga
285 9 nussgipfel
 * configuration files. To handle this, we split the SPI flash address
286
 * space simply at the half. \n
287
 * The data structure in the SPI flash is really simple:\n
288
 * \li 32bit file size value (little endian, as used by the fx2)
289
 * \li binary data from the fpga configuration file
290
 *
291 32 nussgipfel
 * \param[in] *offset pointer to the offset, buffer[offset]
292 9 nussgipfel
 *            is the current position, anything before this is already consumed.
293 32 nussgipfel
 * \param[in] *byte_count pointer to the length of the whole buffer.
294 9 nussgipfel
 * \return    returns non-zero if successful, else 0
295
 */
296 32 nussgipfel
uint8_t app_write_conf_to_flash(idata uint16_t *offset, \
297 9 nussgipfel
                                idata uint16_t *byte_count)
298
{
299
  idata uint16_t length;
300
  xdata uint32_t local_uint32_var;
301
  xdata unsigned char *local_buffer_ptr;
302
 
303
  /* Is this the first part of configuration? */
304
  if(usb_tmc_transfer.nbytes_rxd == 0) {
305
    /* setup all stuff */
306
    file_size = 0;
307
 
308
    /* select which file slot we have to delete */
309
    if(buffer[*offset] == '0') {
310 13 nussgipfel
      flash_adress = start_adress_slot0(flash_dr);
311 9 nussgipfel
    }
312
    else if(buffer[*offset] == '1'){
313 13 nussgipfel
      flash_adress = start_adress_slot1(flash_dr);
314 9 nussgipfel
    }
315
    else {
316
      //print_err("slot\n");
317
      ieee488_status.EventStatusRegister |= bmCOMMAND_ERROR;
318
      usb_tmc_state = TMC_STATE_IDLE;
319
      return 0;
320
    }
321
 
322
    *offset += 2;
323
  }
324
 
325
  /* do we still analyze the file header? */
326
  if(file_size == 0) {
327
    if(!app_check_fpga_type_from_header(offset, byte_count)) {
328
      return 0;
329
    }
330
 
331
    /* are we now finished analyzing? */
332
    if(file_size != 0) {
333
      /* if yes, write file size information to the SPI flash */
334
      //print_info("begin\n");
335
      spiflash_erase(&flash_dr, &flash_adress);
336
      local_uint32_var = file_size;
337
      spiflash_write(&flash_dr, &flash_adress, (uint8_t*)&local_uint32_var, \
338
        sizeof(file_size));
339
    }
340
  }
341
 
342
  /* anything ready, write data to the SPI flash */
343
  if(file_size != 0) {
344
    //printf_tiny("off: %d\n",*offset);
345
    //printf_tiny("ad: %x,",((uint8_t*)&flash_adress)[3]);
346
    //printf_tiny("%x,",((uint8_t*)&flash_adress)[2]);
347
    //printf_tiny("%x,",((uint8_t*)&flash_adress)[1]);
348
    //printf_tiny("%x\n",((uint8_t*)&flash_adress)[0]);
349
 
350
 
351
    length = *byte_count - *offset;
352
 
353
    /* check if we have data to be written to the next flash sector: */
354
    local_uint32_var = flash_adress + *byte_count;
355
    if(sectorStart(local_uint32_var) != sectorStart(flash_adress)) {
356
      /* before we can write to the next flash sector, we have to erase it */
357
      spiflash_erase(&flash_dr, &local_uint32_var);
358
    }
359
 
360
    /* write data to the SPI flash */
361
    local_buffer_ptr = buffer;
362
    local_buffer_ptr += *offset;
363
    spiflash_write(&flash_dr, &flash_adress, local_buffer_ptr, length);
364
 
365
    /* adjust the file- and transfersize */
366
    usb_tmc_transfer.transfer_size -= length;
367
    file_size -= length;
368
 
369
    //printf_tiny("le, %d\n",length);    
370
 
371
    /* if transfer finished, back to TMC idle state */
372
    if(file_size <= 0) {
373
      file_size = 0;
374
      usb_tmc_state = TMC_STATE_IDLE;
375
    }
376
  }
377
 
378
  return 1;
379
}
380
 
381
 
382
/** \brief  erases the desired file slot in spi flash
383 32 nussgipfel
 *
384
 *  send the erase command for one spi flash memory block and loop
385
 *  through the main_loop untill we finished erasing the whole fpga
386
 *  configuration file slot.
387 9 nussgipfel
 *
388 32 nussgipfel
 * \param[in] *offset pointer to the offset, buffer[offset]
389 9 nussgipfel
 *            is the current position, anything before this is already consumed.
390
 * \return    returns non-zero if successful, else 0
391
 *
392
 * \todo   uncomment this function after finishing debuging, else no space left!
393
 */
394 32 nussgipfel
uint8_t app_gecko3com_flash_delete(idata uint16_t *offset) {
395 9 nussgipfel
 
396
  xdata uint32_t flash_adress;
397
  xdata uint32_t local_uint32_var;
398
  char slot;
399
 
400
  /* send the delete command for each block and loop through the main_loop */
401
  /* check busy and set usb_tmc_state back to idle when finished file delete */
402
  if(usb_tmc_transfer.new_transfer == NEWTRANSFER) {
403
    //print_info("new\n");
404
 
405
    /* select which file slot we have to delete */
406
    slot = buffer[*offset];
407
    if(slot == '0') {
408 13 nussgipfel
      flash_adress = start_adress_slot0(flash_dr);
409 9 nussgipfel
    }
410
    else if(slot == '1'){
411 13 nussgipfel
      flash_adress = start_adress_slot1(flash_dr);
412 9 nussgipfel
    }
413
    else {
414
      //print_err("del\n");
415
      ieee488_status.EventStatusRegister |= bmCOMMAND_ERROR;
416
      usb_tmc_state = TMC_STATE_IDLE;
417
      return 0;
418
    }
419
  }
420
 
421 33 nussgipfel
  /* to "delete" means to set the file_size at the beginning of the confguration
422
   * file slot to zero */
423 9 nussgipfel
  local_uint32_var = 0;
424
  spiflash_write(&flash_dr, &flash_adress, (uint8_t*)&local_uint32_var,4);
425
  usb_tmc_state = TMC_STATE_IDLE;
426
 
427
  return 1;
428
}
429
 
430
 
431
/** \brief Handle the class commands on endpoint 0.
432
 *
433
 * \return If we handle this one, return non-zero.
434
 */
435
unsigned char app_class_cmd (void)
436
{
437
#ifdef USB_DFU_SUPPORT
438
  if (usb_dfu_request()){
439
    if(!usb_handle_dfu_packet()){
440
      //print_err("dfu request\n");
441
      return 0;
442
    }
443
  }
444
 
445
  else
446
#endif 
447
  if (usb_tmc_request()){
448
    if(!usb_handle_tmc_packet()){
449
      //print_err("tmc request\n");
450
      return 0;
451
    }
452
  }
453
  else {
454
    //print_err("invalid class request\n");
455
    return 0; /* invalid class request */
456
  }
457
 
458
  return 1;
459
}
460
 
461
 
462
/** \brief Handle our "Vendor Extension" commands on endpoint 0.
463
 *
464
 * \return If we handle this one, return non-zero.
465
 */
466
unsigned char app_vendor_cmd (void)
467
{
468
 /* vendor commands are only used after production
469
   * starting with firmware version 0.4 we remove the vendor commands
470
   * to save memory for more importand functions!
471
 
472
  if (bRequestType == VRT_VENDOR_IN){ */
473
    /*********************************
474
     *    handle the IN requests
475
     ********************************/
476
  /*
477
    switch (bRequest){
478
 
479
    default:
480
      return 0;
481
    }
482
  }
483
 
484
   else if (bRequestType == VRT_VENDOR_OUT){ */
485
    /***********************************
486
     *    handle the OUT requests
487
     **********************************/
488
  /*
489
    switch (bRequest){
490
    case VRQ_SET_SERIAL:
491
      get_ep0_data();
492
      if(wLengthL > SERIAL_NO_LEN){
493
        return 0;
494
      }
495
      if(!eeprom_write(I2C_ADDR_BOOT, SERIAL_NO_OFFSET, EP0BUF, wLengthL)){
496
        return 0;
497
      }
498
      break;
499
 
500
    case VRQ_SET_HW_REV:
501
      get_ep0_data();
502
      if(!eeprom_write(I2C_ADDR_BOOT, HW_REV_OFFSET, EP0BUF, 1)){
503
        return 0;
504
      }
505
      break;
506
 
507
    case VRQ_SET_FPGA_TYPE:
508
      get_ep0_data();
509
      if(wLengthL > FPGA_TYPE_LEN){
510
        return 0;
511
      }
512
      if(!eeprom_write(I2C_ADDR_BOOT, FPGA_TYPE_OFFSET, EP0BUF, wLengthL)){
513
        return 0;
514
      }
515
      break;
516
 
517
    case VRQ_SET_FPGA_IDCODE:
518
      get_ep0_data();
519
      if(!eeprom_write(I2C_ADDR_BOOT, FPGA_IDCODE_OFFSET, EP0BUF, FPGA_IDCODE_LEN)){
520
        return 0;
521
      }
522
      break;
523
 
524
    default:
525
      return 0;
526
 
527
    }
528
  }
529
 
530
  else */
531
    return 0;    /* invalid bRequestType */
532
 
533
  //return 1;
534
}
535
 
536
 
537
/** \brief Read h/w rev code and serial number out of boot eeprom and
538
 * patch the usb descriptors with these values.
539
 */
540
void patch_usb_descriptors(void)
541
{
542
  xdata uint8_t hw_rev;
543
  xdata unsigned char serial_no[SERIAL_NO_LEN];
544
  unsigned char ch;
545
  uint8_t i,j;
546
 
547
  /* hardware revision */
548
  eeprom_read(HW_REV_OFFSET, &hw_rev, 1);       /* LSB of device id */
549
  usb_desc_hw_rev_binary_patch_location_0[0] = hw_rev;
550
  usb_desc_hw_rev_binary_patch_location_1[0] = hw_rev;
551
 
552
  /* serial number */
553
  eeprom_read(SERIAL_NO_OFFSET, serial_no, SERIAL_NO_LEN);
554
 
555
  for (i = 0; i < SERIAL_NO_LEN; i++){
556
    ch = serial_no[i];
557
    if (ch == 0xff)     /* make unprogrammed EEPROM default to '0' */
558
      ch = '0';
559
 
560
    j = i << 1;
561
    usb_desc_serial_number_ascii[j] = ch;
562
  }
563
}
564
 
565
 
566
/** \brief  we do all the work here. infinite loop */
567
static void main_loop (void)
568
{
569
  tHeader *tmc_header, *tmc_response_header;
570
  idata uint16_t offset, byte_count;
571
  static idata uint32_t transfer_size;
572
  xdata Scanner scpi_scanner;
573
 
574
  uint16_t index;
575
 
576
  buffer = EP2FIFOBUF;
577
  scpi_scanner.action = NOACTION;
578 13 nussgipfel
  index = 0;
579 9 nussgipfel
 
580
  while (1){
581
 
582
    usb_tmc_transfer.new_transfer = 0;
583
 
584
    /* -------------------------------------------------------------------- */
585
    /* SETUP Package on Endpoint 0. Handle if we received one */
586
    if (usb_setup_packet_avail())
587
      usb_handle_setup_packet();
588
 
589
    /* -------------------------------------------------------------------- */
590
    /* Let's do some work when an Endpoint has data */
591
    if (!(EP2468STAT & bmEP2EMPTY) && flLOCAL == GECKO3COM_LOCAL){
592
      offset = 0;
593
 
594
      if(usb_tmc_state == TMC_STATE_IDLE || usb_tmc_transfer.transfer_size == 0){
595
 
596 33 nussgipfel
        /* start to analyze the data in Endpoint 2 if it is a correct TMC
597
         * header */
598 9 nussgipfel
        tmc_header = (tHeader*)EP2FIFOBUF;
599
 
600
        /* bTag sanity check. store bTag for correct IN transfer response */
601
        if (tmc_header->bTag == ~tmc_header->bTagInverse) {
602
          usb_tmc_transfer.bTag = tmc_header->bTag;
603
 
604
          /* TMC header is correct. Now find out what we have to do: */
605
 
606
          /* check if this transfer is a DEV_DEP_MSG_OUT message */
607
          if(tmc_header->MsgID == DEV_DEP_MSG_OUT){
608
            usb_tmc_transfer.transfer_size = \
609
              ((DEV_DEP_MSG_OUT_Header*)tmc_header->msg_specific)->TransferSize;
610
            usb_tmc_transfer.new_transfer = NEWTRANSFER;
611
            offset = USB_TMC_HEADER_SIZE;
612
 
613
            /* Decide if we should start the SCPI parser or not
614
             * if not IDLE, the transfer size was 0 and we continue
615
             * to exectue the action and don't try to parse a new command */
616
            if(usb_tmc_state == TMC_STATE_IDLE) {
617
 
618
              /* fresh OUT Transfer: handle device dependent command message */
619
              usb_tmc_state = TMC_STATE_OUT_TRANSFER;
620
              usb_tmc_transfer.nbytes_rxd = 0;
621
 
622 33 nussgipfel
              /* when we receive an new out message before we sent the response,
623 9 nussgipfel
               * we have to clear the response queue first*/
624
              IEEE488_clear_mav();
625
              usb_tmc_transfer.nbytes_txd = 0;
626
              response_queue.length = 0;
627
 
628
 
629
              /* setup variables for scpi parser.
630
               * offset points to first command byte in endpoint buffer */
631
              scpi_scanner.source = EP2FIFOBUF;
632
              scpi_scanner.action = NOACTION;
633
 
634
              /* start SCPI parser */
635
              if(!scpi_scan(&offset, &scpi_scanner, &response_queue)){
636
                /* the parser returned an error. set flags */
637
                ieee488_status.EventStatusRegister |= bmCOMMAND_ERROR;
638
                usb_tmc_state = TMC_STATE_IDLE;
639
                scpi_scanner.action = NOACTION;
640
                usb_tmc_transfer.new_transfer = 0;
641
                //print_err("syntax failure\n");
642
              }
643
            }
644
          }
645
          /* finished handling an DEV_DEP_MSG_OUT message */
646
 
647
          /* ---------------------------------------------------------------- */
648
          /* check if this transfer is a IN request and we have a IN response
649
           * queued */
650
          else if(tmc_header->MsgID == REQUEST_DEV_DEP_MSG_IN \
651
                  && response_queue.length > 0) {
652
 
653
            /* IN Transfer: Handle response message to a device dependent
654
             * command message. For this we change the TMC state.
655
             * Sending the requested data to the IN endpoint
656
             * happens further below */
657
            usb_tmc_state = TMC_STATE_IN_TRANSFER;
658
            usb_tmc_transfer.transfer_size = \
659
              ((REQUEST_DEV_DEP_MSG_IN_Header*) tmc_header->msg_specific)\
660
              ->TransferSize;
661
            usb_tmc_transfer.nbytes_txd = 0;
662
 
663
          }
664
          else {
665
            /* TMC header error: unknown message ID */
666
            EP2CS |= bmEPSTALL;
667
            //print_err("ID\n");
668
          }
669
        }
670
 
671
        else {
672
          /* TMC header error: bTag and bTagInverse don't match */
673
          EP2CS |= bmEPSTALL;
674
          //print_err("bTag\n");
675
        }
676
      }
677
 
678
      /* -------------------------------------------------------------------- */
679
      /* OUT Transfer: The SCPI parser has detected a application specific
680
       * command. Here we execute the desired functions for these commands: */
681
      if(usb_tmc_state == TMC_STATE_OUT_TRANSFER){
682
 
683
        /* set the correct byte_count value */
684
        /* read byte counter register of EP2FIFOBUF */
685
        byte_count = (EP2BCH << 8) + EP2BCL;
686
 
687
        /* decide which value is the smaller one */
688
        if((byte_count - offset) > usb_tmc_transfer.transfer_size) {
689
          byte_count = usb_tmc_transfer.transfer_size;
690
          /* transfer_size does not includ the header length: */
691
          byte_count += offset;
692
        }
693
 
694
        /* select what we have to to according to the parsed scpi command */
695
        switch (scpi_scanner.action) {
696
 
697
        case SYSTEM_RESET:
698
          /* Send a global reset signal to the FPGA and all connected modules */
699
          gecko3com_system_reset();
700
          usb_tmc_state = TMC_STATE_IDLE;
701
          break;
702
 
703
        case rqFPGA_IDCODE:
704
          /* Request to read the FPGA JTAG ID code */
705
          eeprom_read(FPGA_IDCODE_OFFSET, response_queue.buf, FPGA_IDCODE_LEN);
706
          response_queue.buf[FPGA_IDCODE_LEN] = '\n';
707
          response_queue.length = FPGA_IDCODE_LEN+1;
708
          IEEE488_set_mav();
709
          usb_tmc_state = TMC_STATE_IDLE;
710
          break;
711
 
712
        case rqFPGA_TYPE:
713
          /* Request to read the FPGA type string */
714
          eeprom_read(FPGA_TYPE_OFFSET, response_queue.buf, FPGA_TYPE_LEN);
715
          response_queue.buf[FPGA_TYPE_LEN] = '\n';
716
          response_queue.length = FPGA_TYPE_LEN+1;
717
          IEEE488_set_mav();
718
          usb_tmc_state = TMC_STATE_IDLE;
719
          break;
720
 
721
        case rqFPGA_DONE:
722
          /* Is the FPGA configured or not? Check the "done" pin*/
723
          if(fpga_done()) {
724
            response_queue.buf[0] = '1';
725
          }
726
          else {
727
            response_queue.buf[0] = '0';
728
          }
729
          response_queue.buf[1] = '\n';
730
          response_queue.length = 2;
731
          usb_tmc_state = TMC_STATE_IDLE;
732
          break;
733
 
734
        case FPGA_CONFIGURE:
735
          /* Configure the FPGA directly */
736
          if(!app_configure_fpga(&offset, &byte_count)) {
737
            //print_err("conf\n");
738
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
739
            usb_tmc_state = TMC_STATE_IDLE;
740
          }
741
          break;
742
 
743
        case FPGA_COMMUNICATION:
744
          /* Switch the context from the FX2 to the FPGA.
745
           * After this command all endpoint 2 and 6 data goes directly to the
746
           * FPGA, the FX2 doesn't parse commands anymore. Use endpoint 0 TMC
747
           * commands to switch back */
748 20 nussgipfel
          if(fpga_done()) {
749
            init_gpif();
750
            flLOCAL = GECKO3COM_REMOTE;
751
          }
752
          else {
753
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
754
          }
755 9 nussgipfel
          usb_tmc_state = TMC_STATE_IDLE;
756
          break;
757
 
758
        case SPI_DELETE:
759
          /* Erases one of the file spaces in the SPI flash  */
760
          if(!app_gecko3com_flash_delete(&offset)) {
761
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
762
          }
763
          usb_tmc_state = TMC_STATE_IDLE;
764
          break;
765
 
766
        case SPI_WRITE:
767
          /* Writes a FPGA configuration file into a file space in the
768
           * SPI flash. */
769
          if(!app_write_conf_to_flash(&offset, &byte_count)) {
770
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
771
            usb_tmc_state = TMC_STATE_IDLE;
772
          }
773
          break;
774
 
775
        default:
776
 
777
          usb_tmc_state = TMC_STATE_IDLE;
778
        }
779
      }
780
 
781 33 nussgipfel
      usb_tmc_transfer.nbytes_rxd += ((EP2BCH << 8) + EP2BCL - \
782
                                      USB_TMC_HEADER_SIZE);
783 9 nussgipfel
 
784
      /* finished handling usb package.
785
       * rearm OUT endpoint to receive new data */
786
      OUTPKTEND = bmSKIP | USB_TMC_EP_OUT;
787
 
788
    } /* end of OUT Transfer clause */
789
 
790
 
791
    /* -------------------------------------------------------------------- */
792
    /* Let's continue to send data when an Endpoint is free */
793
    /* IN Transfer: Generate a valid TMC IN header and send the response
794
     * message data to the endpoint */
795
    if (!(EP2468STAT & bmEP6FULL) && usb_tmc_state == TMC_STATE_IN_TRANSFER){
796
 
797
      /* fresh IN transfer, send first header */
798
      if(usb_tmc_transfer.nbytes_txd == 0) {
799
        index = 0;
800
        tmc_response_header = (tHeader*)EP6FIFOBUF;
801
        tmc_response_header->MsgID = REQUEST_DEV_DEP_MSG_IN;
802
        tmc_response_header->bTag = usb_tmc_transfer.bTag;
803
        tmc_response_header->bTagInverse = ~usb_tmc_transfer.bTag;
804
        tmc_response_header->Reserved = 0;
805
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)-> \
806
          TransferSize = response_queue.length;
807
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
808
          Reserved[0] = 0;
809
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
810
          Reserved[1] = 0;
811
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
812
          Reserved[2] = 0;
813
 
814
        /* if we can send all data in one usb packet,
815
           set EOM (end of message) bit */
816
        /* WARNING: set EOM bit in the LAST tmc transfer.
817
         * we transmitt anything in one transfer so we set this bit always. */
818
        /*if(USBCS & bmHSM && response_queue.length <= 500 | \
819
          response_queue.length <= 56)*/
820
          ((DEV_DEP_MSG_OUT_Header*)tmc_response_header->msg_specific)->\
821
            bmTransferAttributes = bmTA_EOM;
822
          /*else
823
          ((DEV_DEP_MSG_OUT_Header*)tmc_response_header->msg_specific)->\
824
          bmTransferAttributes = 0;*/
825
 
826
        index = USB_TMC_HEADER_SIZE;
827
      } /* finished writing header */
828
 
829
 
830
      /* Transmit data */
831
      for(usb_tmc_transfer.nbytes_txd; \
832
          usb_tmc_transfer.nbytes_txd <= response_queue.length; \
833
          usb_tmc_transfer.nbytes_txd++){
834
 
835
        /* copy the data from the response queue to the IN endpoint */
836
        EP6FIFOBUF[index++] = response_queue.buf[usb_tmc_transfer.nbytes_txd];
837
 
838
        /* we send any response in one packet so we don't have to check if
839
         * the endpoint buffer is full */
840
        /*if(!(USBCS & bmHSM) && index == 64 |  \
841
           index == 512)
842
          break;
843
        */
844
      }
845
 
846
      EP6BCH = index >> 8;
847
      EP6BCL = index & 0xFF;
848
      index = 0;
849
 
850
      /* detect end of transfer */
851
      if(usb_tmc_transfer.nbytes_txd >= response_queue.length){
852
        usb_tmc_state = TMC_STATE_IDLE;
853
        IEEE488_clear_mav();
854
        response_queue.length = 0;
855
      }
856
    } /* end of IN Transfer clause */
857
 
858 20 nussgipfel
 
859 21 nussgipfel
 
860
    if(flLOCAL == GECKO3COM_REMOTE) {
861
      /* if we operate in REMOTE mode (means we pass the data to the FPGA)
862
       * continously check the DONE pin from the FPGA, to avoid that bad things
863
       * happen when someone reconfigures the FPGA through JTAG */
864
      if(!fpga_done()) {
865
 
866 28 nussgipfel
        mdelay(50);
867 21 nussgipfel
        if(!fpga_done()) {
868 28 nussgipfel
          set_led_ext(ORANGE);
869 21 nussgipfel
          deactivate_gpif();
870
          flLOCAL = GECKO3COM_LOCAL;
871
        }
872
      }
873
 
874 28 nussgipfel
      //if(!(EP2468STAT & bmEP2EMPTY) && (GPIFTRIG & bmGPIF_IDLE)) {
875
        /* check if there is a active IN transfer */
876
        /*if((GPIFREADYSTAT & bmWRX) != bmWRX) {
877
          flGPIF = 0;
878
          gpif_trigger_write();
879
        }
880
        }*/
881
 
882
      /* check if this is a end of a IN transfer */
883
      /*if(!(EP2468STAT & bmEP6EMPTY) && (GPIFTRIG & bmGPIF_IDLE)) {
884
        INPKTEND = USB_TMC_EP_IN;
885
        flGPIF |= bmGPIF_PENDING_DATA;
886
        gpif_trigger_read();
887
        }*/
888 20 nussgipfel
    }
889
 
890 9 nussgipfel
    /* if the LED flag is set to off, disable the external LED */
891
    if(flLED == LEDS_OFF) {
892
      set_led_ext(LEDS_OFF);
893
    }
894
 
895 20 nussgipfel
 
896 9 nussgipfel
    /* resets the watchdog timer back to the initial value */
897
    watchdog_count = WATCHDOG_TIME;
898
 
899
  } /* end of infinite main loop */
900
}
901
 
902
 
903
/** \brief ISR called at 100 Hz from timer2 interrupt
904
 *
905
 * Toggle led 0
906
 */
907
void isr_tick (void) interrupt
908
{
909
  static uint8_t count = 1;
910
 
911
  if (--count == 0){
912
    count = 50;
913
    toggle_led_0();
914
    flLED = LEDS_OFF;
915
  }
916
 
917
  //  if (--watchdog_count == 0){
918
  //    clear_timer_irq(); 
919
  //  #ifdef DEBUG_LEVEL_ERROR
920
    //  print_err("Watchdog timed out! System reset\n");
921 33 nussgipfel
  //mdelay(100);             /* wait 100 ms to give the uart some time to 
922
  //                          * transmit */
923 9 nussgipfel
  //  #endif
924
 
925 33 nussgipfel
      /* simulate CPU reset */  /* FIXME this stuff here does not work.
926
                                 * no idea how to simulate an CPU reset
927
                                 * instead... */
928 9 nussgipfel
      /* _asm
929
      ljmp    __reset_vector
930
      _endasm;*/
931
  //}
932
 
933
#ifdef USB_DFU_SUPPORT
934
  if (usb_dfu_state == DFU_STATE_appDETACH){
935
    if (--usb_dfu_timeout == 0){
936
      usb_toggle_dfu_handlers();
937
    }
938
  }
939
#endif
940
 
941
  clear_timer_irq();
942
}
943
 
944
 
945
/** \brief starting point of execution.
946
 *
947
 * we initialize all system components here. after that we go to the main_loop
948
 * function there all the work is done.
949
 */
950
void main(void)
951
{
952
  /* variables needed for the stand-alone fpga configuration */
953
  uint8_t led_color;
954
  idata uint16_t i, local_offset;
955
  xdata uint32_t spi_base_adress;
956
 
957
  init_gecko3com();
958
  init_io_ext();
959
  init_usb_tmc();
960
  init_fpga_interface();
961
  init_spiflash(&flash_dr);
962
 
963
  /* disconnect USB, so the host doesn't wait for us during the fpga
964
   *configuration process (takes up to 20s) */
965
  USBCS |= bmDISCON;
966
 
967
#ifdef DEBUG_LEVEL_ERROR
968 33 nussgipfel
  ser_init();
969 21 nussgipfel
  //printf_tiny("hi\n");
970 9 nussgipfel
#endif
971
 
972
  /* set the context switch flag to local operation, not fpga */
973
  flLOCAL = GECKO3COM_LOCAL;
974
 
975
  /* enable GPIF state output for debuging  */
976
  IFCONFIG |= bmGSTATE;
977
 
978
  EA = 0;                /* disable all interrupts */
979
 
980
  patch_usb_descriptors();
981
  setup_autovectors();
982
  usb_install_handlers();
983
  hook_timer_tick((unsigned short) isr_tick);
984
 
985
  EA = 1;               /* global interrupt enable */
986
 
987
  /* finished initializing GECKO3COM system */
988
  /*------------------------------------------------------------------------*/
989
 
990
  /* start to configure the FPGA from the configuration SPI flash */
991
  /* read which configuration, the first or second, we should use */
992
  if(get_switch()){
993
    led_color = GREEN;
994 13 nussgipfel
    spi_base_adress = start_adress_slot0(flash_dr);
995 9 nussgipfel
  }
996
  else {
997
    led_color = RED;
998 13 nussgipfel
    spi_base_adress = start_adress_slot1(flash_dr);
999 9 nussgipfel
  }
1000
 
1001
  /* read the configuration file size from the spi flash */
1002
  spiflash_read(&flash_dr, &spi_base_adress, response_queue.buf, 4);
1003
  ((idata uint8_t*)&file_size)[0] = response_queue.buf[0];
1004
  ((idata uint8_t*)&file_size)[1] = response_queue.buf[1];
1005
  ((idata uint8_t*)&file_size)[2] = response_queue.buf[2];
1006
  ((idata uint8_t*)&file_size)[3] = response_queue.buf[3];
1007
  spi_base_adress += 4;
1008
 
1009 13 nussgipfel
  /* debug stuff */
1010 33 nussgipfel
  //response_queue.buf[0] = init_spiflash(&flash_dr);
1011
  //IEEE488_set_mav();
1012
  //response_queue.length = 1;
1013 13 nussgipfel
 
1014 9 nussgipfel
  /* there is nothing to configure when the filesize is 0 or 0xFFFFFFFF */
1015
  if(file_size == 0 || file_size == 0xFFFFFFFF) {
1016
    /* show that we don't load a config */
1017
    set_led_ext(ORANGE);
1018
  }
1019
  else {
1020
    fpga_load_begin();
1021
    i = TMC_RESPONSE_QUEUE_LENGTH-1;
1022
    while(file_size > 0) {
1023
      set_led_ext(led_color); /* show which config we load */
1024 33 nussgipfel
 
1025 9 nussgipfel
      if(i > file_size) {
1026 33 nussgipfel
        i = (uint8_t)file_size;
1027 9 nussgipfel
      }
1028
      spiflash_read(&flash_dr, &spi_base_adress, response_queue.buf, i);
1029
 
1030
      local_offset = 0;
1031
      fpga_load_xfer(response_queue.buf, &local_offset, &i);
1032
      file_size -= i;
1033
      spi_base_adress += i;
1034
    }
1035
    fpga_load_end();
1036
  }
1037
 
1038
  USBCS &= ~bmDISCON;           /* reconnect USB */
1039
 
1040
  main_loop();
1041
}

powered by: WebSVN 2.1.0

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