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 32

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

powered by: WebSVN 2.1.0

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