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 9

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
/* -------------------------------------------------------------------- */
73
 
74
#define WATCHDOG_TIME           100 /**< time until the watchdog times out, 100 equals 1 second */
75
 
76
/* Global variables */
77
volatile uint8_t watchdog_count = WATCHDOG_TIME;
78
idata int32_t file_size;
79
xdata uint32_t flash_adress;
80
xdata unsigned char *buffer;
81
xdata TMC_Response_Queue response_queue;
82
 
83
 
84
/** \brief with executing this function, we confirm that we handled the
85
 *  endpoint 0 data and that we are ready to get new data (rearm the endpoint).
86
 */
87
static void get_ep0_data (void)
88
{
89
  EP0BCL = 0;            /* arm EP0 for OUT xfer.  This sets the busy bit */
90
 
91
  while (EP0CS & bmEPBUSY)      /* wait for busy to clear */
92
    ;
93
}
94
 
95
 
96
/*
97
 * enable debug output through the serial uart
98
 */
99
#ifdef DEBUG_LEVEL_ERROR
100
 
101
/** \brief simple wraper to provide putchar function over serial line */
102
void putchar (char p)
103
{
104
  ser_putc((unsigned char) p);
105
}
106
 
107
 
108
/** \brief simple wraper to provide getchar function over serial line */
109
char getchar (void)
110
{
111
  return (char) ser_getc();
112
}
113
#endif
114
 
115
 
116
#ifdef USB_DFU_SUPPORT
117
/** \brief this function writes the new firmware data in endpoint 0 to the I2C eeprom
118
 * \note this function is only available when the DFU (device firware upgrade) class
119
 * support is enabled.
120
 */
121
uint8_t app_firmware_write (void)
122
{
123
  static uint16_t eeprom_offset;
124
 
125
  get_ep0_data();
126
 
127
  if(usb_dfu_state == DFU_STATE_dfuIDLE){
128
    eeprom_offset = 0;
129
  }
130
 
131
  //  if(!eeprom_write(I2C_ADDR_BOOT, eeprom_offset, EP0BUF, wLengthL)){
132
  if(!eeprom_write(eeprom_offset, EP0BUF, wLengthL)){
133
    usb_dfu_status = DFU_STATUS_errWRITE;
134
    return 0;
135
  }
136
 
137
  eeprom_offset += wLengthL;
138
  return 1;
139
}
140
#endif
141
 
142
 
143
/** \brief analyze the header from the fpga configuration file and compares the
144
 *  the fpga type with the on board fpga and returs the configuration file size.
145
 *
146
 * \param[in] xdata unsigned char *buffer pointer to the buffer to read from
147
 *            (normally endpoint buffer)
148
 * \param[in] idata uint16_t *offset pointer to the offset, buffer[offset]
149
 *            is the current position, anything before this is already consumed.
150
 * \param[in] idata uint16_t *byte_count pointer to the length of the whole
151
 *            buffer.
152
 * \return    returns non-zero if successful, else 0
153
 */
154
uint8_t app_check_fpga_type_from_header(/*xdata unsigned char *buffer,*/ \
155
                                        idata uint16_t *offset,         \
156
                                        idata uint16_t *byte_count)
157
{
158
  static xdata Fpga_Info fpga_file_header;
159
  xdata char fpga_type[FPGA_TYPE_LEN];
160
  static int8_t continue_analyse;
161
 
162
  /* check if this is the first attempt to analyse the bit file header*/
163
  if(usb_tmc_transfer.new_transfer == NEWTRANSFER) {
164
    continue_analyse = 0;
165
    fpga_file_header.type = FPGA_TYPE;
166
  }
167
 
168
  /* first value to read from the header file is the fpga type */
169
  if(fpga_file_header.type == FPGA_TYPE){
170
    if(fpga_scan_file(buffer, offset, byte_count, &fpga_file_header)    \
171
       == FPGA_INFO_COMPLETE) {
172
 
173
      /* compare fpga type from header with value in eeprom */
174
      if(!eeprom_read(FPGA_TYPE_OFFSET, fpga_type, FPGA_TYPE_LEN)){
175
        return 0;
176
      }
177
 
178
      if(strncmp(fpga_file_header.info, fpga_type, FPGA_TYPE_LEN)) {
179
        //print_err("!FPGA\n");
180
        return 0;
181
      }
182
 
183
      /* next value to read from the header is the file length */
184
      fpga_file_header.type = FILE_LENGTH;
185
      continue_analyse = FPGA_INFO_COMPLETE;
186
    }
187
    else {
188
      continue_analyse = FPGA_INFO_NOT_COMPLETE;
189
    }
190
  }
191
 
192
  /* second value to read from the header file is the file length */
193
  if(fpga_file_header.type == FILE_LENGTH){
194
    if(fpga_scan_file(buffer, offset, byte_count, &fpga_file_header)    \
195
       == FPGA_INFO_COMPLETE) {
196
 
197
      ((uint8_t*)&file_size)[0] = fpga_file_header.info[2];
198
      ((uint8_t*)&file_size)[1] = fpga_file_header.info[1];
199
      ((uint8_t*)&file_size)[2] = fpga_file_header.info[0];
200
      ((uint8_t*)&file_size)[3] = 0;
201
 
202
      continue_analyse = FPGA_INFO_COMPLETE;
203
    }
204
    else {
205
      continue_analyse = FPGA_INFO_NOT_COMPLETE;
206
    }
207
  }
208
 
209
  /* adjust the offset and byte_count variables to point to the
210
   * binary data after the header */
211
  usb_tmc_transfer.transfer_size += USB_TMC_HEADER_SIZE;
212
  usb_tmc_transfer.transfer_size -= *offset;
213
 
214
  return continue_analyse;
215
}
216
 
217
 
218
/** \brief function to configure an fpga with data from usb
219
 *
220
 * \param[in] xdata unsigned char *buffer pointer to the buffer to read from
221
 *            (normally endpoint buffer)
222
 * \param[in] idata uint16_t *offset pointer to the offset, buffer[offset]
223
 *            is the current position, anything before this is already consumed.
224
 * \param[in] idata uint16_t *byte_count pointer to the length of the whole
225
 *            buffer.
226
 * \return    returns non-zero if successful, else 0
227
 */
228
uint8_t app_configure_fpga(/* xdata unsigned char *buffer,*/    \
229
                           idata uint16_t *offset,      \
230
                           idata uint16_t *byte_count)
231
{
232
  /* Is this the first part of configuration? */
233
  if(usb_tmc_transfer.nbytes_rxd == 0) {
234
    /* setup all stuff */
235
    file_size = 0;
236
  }
237
 
238
  /* do we still analyze the file header? */
239
  if(file_size == 0) {
240
    if(!app_check_fpga_type_from_header(offset, byte_count)) {
241
      return 0;
242
    }
243
 
244
    /* are we now finished analyzing? */
245
    if(file_size != 0) {
246
      /* if yes, intialize fpga for configuration */
247
      //print_info("begin\n");
248
      fpga_load_begin();
249
    }
250
  }
251
 
252
  /* anything ready, transfer data to fpga */
253
  if(file_size != 0) {
254
    /* transmitt config data to fpga */
255
    usb_tmc_transfer.transfer_size -= *byte_count;
256
    usb_tmc_transfer.transfer_size += *offset;
257
    file_size -= *byte_count;
258
    file_size += *offset;
259
 
260
    fpga_load_xfer(buffer, offset, byte_count);
261
 
262
    //printf_tiny("buffer[0], %d\n",buffer[0]);
263
 
264
    /* transfer finished, finishing configuration */
265
    if(file_size == 0) {
266
      if(!fpga_load_end()) {
267
        return 0;
268
      }
269
      usb_tmc_state = TMC_STATE_IDLE;
270
    }
271
  }
272
 
273
  return 1;
274
}
275
 
276
 
277
/** \brief function to write an fpga configuration from usb to the spi flash
278
 *
279
 * \detail The SPI flash is big enough to hold store two different fpga
280
 * configuration files. To handle this, we split the SPI flash address
281
 * space simply at the half. \n
282
 * The data structure in the SPI flash is really simple:\n
283
 * \li 32bit file size value (little endian, as used by the fx2)
284
 * \li binary data from the fpga configuration file
285
 *
286
 * \param[in] xdata unsigned char *buffer pointer to the buffer to read from
287
 *            (normally endpoint buffer)
288
 * \param[in] idata uint16_t *offset pointer to the offset, buffer[offset]
289
 *            is the current position, anything before this is already consumed.
290
 * \param[in] idata uint16_t *byte_count pointer to the length of the whole
291
 *            buffer.
292
 * \return    returns non-zero if successful, else 0
293
 */
294
uint8_t app_write_conf_to_flash(/* xdata unsigned char *buffer,*/       \
295
                                idata uint16_t *offset, \
296
                                idata uint16_t *byte_count)
297
{
298
  idata uint16_t length;
299
  xdata uint32_t local_uint32_var;
300
  xdata unsigned char *local_buffer_ptr;
301
 
302
  /* Is this the first part of configuration? */
303
  if(usb_tmc_transfer.nbytes_rxd == 0) {
304
    /* setup all stuff */
305
    file_size = 0;
306
 
307
    /* select which file slot we have to delete */
308
    if(buffer[*offset] == '0') {
309
      flash_adress = START_ADRESS_SLOT0;
310
    }
311
    else if(buffer[*offset] == '1'){
312
      flash_adress = START_ADRESS_SLOT1;
313
    }
314
    else {
315
      //print_err("slot\n");
316
      ieee488_status.EventStatusRegister |= bmCOMMAND_ERROR;
317
      usb_tmc_state = TMC_STATE_IDLE;
318
      return 0;
319
    }
320
 
321
    *offset += 2;
322
  }
323
 
324
  /* do we still analyze the file header? */
325
  if(file_size == 0) {
326
    if(!app_check_fpga_type_from_header(offset, byte_count)) {
327
      return 0;
328
    }
329
 
330
    /* are we now finished analyzing? */
331
    if(file_size != 0) {
332
      /* if yes, write file size information to the SPI flash */
333
      //print_info("begin\n");
334
      spiflash_erase(&flash_dr, &flash_adress);
335
      local_uint32_var = file_size;
336
      spiflash_write(&flash_dr, &flash_adress, (uint8_t*)&local_uint32_var, \
337
        sizeof(file_size));
338
    }
339
  }
340
 
341
  /* anything ready, write data to the SPI flash */
342
  if(file_size != 0) {
343
    //printf_tiny("off: %d\n",*offset);
344
    //printf_tiny("ad: %x,",((uint8_t*)&flash_adress)[3]);
345
    //printf_tiny("%x,",((uint8_t*)&flash_adress)[2]);
346
    //printf_tiny("%x,",((uint8_t*)&flash_adress)[1]);
347
    //printf_tiny("%x\n",((uint8_t*)&flash_adress)[0]);
348
 
349
 
350
    length = *byte_count - *offset;
351
 
352
    /* check if we have data to be written to the next flash sector: */
353
    local_uint32_var = flash_adress + *byte_count;
354
    if(sectorStart(local_uint32_var) != sectorStart(flash_adress)) {
355
      /* before we can write to the next flash sector, we have to erase it */
356
      spiflash_erase(&flash_dr, &local_uint32_var);
357
    }
358
 
359
    /* write data to the SPI flash */
360
    local_buffer_ptr = buffer;
361
    local_buffer_ptr += *offset;
362
    spiflash_write(&flash_dr, &flash_adress, local_buffer_ptr, length);
363
 
364
    /* adjust the file- and transfersize */
365
    usb_tmc_transfer.transfer_size -= length;
366
    file_size -= length;
367
 
368
    //printf_tiny("le, %d\n",length);    
369
 
370
    /* if transfer finished, back to TMC idle state */
371
    if(file_size <= 0) {
372
      file_size = 0;
373
      usb_tmc_state = TMC_STATE_IDLE;
374
    }
375
  }
376
 
377
  return 1;
378
}
379
 
380
 
381
/** \brief  erases the desired file slot in spi flash
382
 * \detail 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
 *
386
 * \param[in] xdata unsigned char *buffer pointer to the buffer to read from
387
 *            (normally endpoint buffer)
388
 * \param[in] idata uint16_t *offset pointer to the offset, buffer[offset]
389
 *            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
uint8_t app_gecko3com_flash_delete(/* uint8_t *buffer,*/ idata uint16_t *offset) {
395
 
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
      flash_adress = START_ADRESS_SLOT0;
409
    }
410
    else if(slot == '1'){
411
      flash_adress = START_ADRESS_SLOT1;
412
    }
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
  /* to "delete" means to set the file_size at the beginning of the confguration
422
     file slot to zero */
423
  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
 
579
  while (1){
580
 
581
    usb_tmc_transfer.new_transfer = 0;
582
 
583
    /* -------------------------------------------------------------------- */
584
    /* SETUP Package on Endpoint 0. Handle if we received one */
585
    if (usb_setup_packet_avail())
586
      usb_handle_setup_packet();
587
 
588
    /* -------------------------------------------------------------------- */
589
    /* Let's do some work when an Endpoint has data */
590
    if (!(EP2468STAT & bmEP2EMPTY) && flLOCAL == GECKO3COM_LOCAL){
591
      offset = 0;
592
 
593
      if(usb_tmc_state == TMC_STATE_IDLE || usb_tmc_transfer.transfer_size == 0){
594
 
595
        /* start to analyze the data in Endpoint 2 if it is a correct TMC header */
596
        tmc_header = (tHeader*)EP2FIFOBUF;
597
 
598
        /* bTag sanity check. store bTag for correct IN transfer response */
599
        if (tmc_header->bTag == ~tmc_header->bTagInverse) {
600
          usb_tmc_transfer.bTag = tmc_header->bTag;
601
 
602
          /* TMC header is correct. Now find out what we have to do: */
603
 
604
          /* check if this transfer is a DEV_DEP_MSG_OUT message */
605
          if(tmc_header->MsgID == DEV_DEP_MSG_OUT){
606
            usb_tmc_transfer.transfer_size = \
607
              ((DEV_DEP_MSG_OUT_Header*)tmc_header->msg_specific)->TransferSize;
608
            usb_tmc_transfer.new_transfer = NEWTRANSFER;
609
            offset = USB_TMC_HEADER_SIZE;
610
 
611
            /* Decide if we should start the SCPI parser or not
612
             * if not IDLE, the transfer size was 0 and we continue
613
             * to exectue the action and don't try to parse a new command */
614
            if(usb_tmc_state == TMC_STATE_IDLE) {
615
 
616
              /* fresh OUT Transfer: handle device dependent command message */
617
              usb_tmc_state = TMC_STATE_OUT_TRANSFER;
618
              usb_tmc_transfer.nbytes_rxd = 0;
619
 
620
              /* when we receive an new out message before we sent the response,
621
               * we have to clear the response queue first*/
622
              IEEE488_clear_mav();
623
              usb_tmc_transfer.nbytes_txd = 0;
624
              response_queue.length = 0;
625
 
626
 
627
              /* setup variables for scpi parser.
628
               * offset points to first command byte in endpoint buffer */
629
              scpi_scanner.source = EP2FIFOBUF;
630
              scpi_scanner.action = NOACTION;
631
 
632
              /* start SCPI parser */
633
              if(!scpi_scan(&offset, &scpi_scanner, &response_queue)){
634
                /* the parser returned an error. set flags */
635
                ieee488_status.EventStatusRegister |= bmCOMMAND_ERROR;
636
                usb_tmc_state = TMC_STATE_IDLE;
637
                scpi_scanner.action = NOACTION;
638
                usb_tmc_transfer.new_transfer = 0;
639
                //print_err("syntax failure\n");
640
              }
641
            }
642
          }
643
          /* finished handling an DEV_DEP_MSG_OUT message */
644
 
645
          /* ---------------------------------------------------------------- */
646
          /* check if this transfer is a IN request and we have a IN response
647
           * queued */
648
          else if(tmc_header->MsgID == REQUEST_DEV_DEP_MSG_IN \
649
                  && response_queue.length > 0) {
650
 
651
            /* IN Transfer: Handle response message to a device dependent
652
             * command message. For this we change the TMC state.
653
             * Sending the requested data to the IN endpoint
654
             * happens further below */
655
            usb_tmc_state = TMC_STATE_IN_TRANSFER;
656
            usb_tmc_transfer.transfer_size = \
657
              ((REQUEST_DEV_DEP_MSG_IN_Header*) tmc_header->msg_specific)\
658
              ->TransferSize;
659
            usb_tmc_transfer.nbytes_txd = 0;
660
 
661
          }
662
          else {
663
            /* TMC header error: unknown message ID */
664
            EP2CS |= bmEPSTALL;
665
            //print_err("ID\n");
666
          }
667
        }
668
 
669
        else {
670
          /* TMC header error: bTag and bTagInverse don't match */
671
          EP2CS |= bmEPSTALL;
672
          //print_err("bTag\n");
673
        }
674
      }
675
 
676
      /* -------------------------------------------------------------------- */
677
      /* OUT Transfer: The SCPI parser has detected a application specific
678
       * command. Here we execute the desired functions for these commands: */
679
      if(usb_tmc_state == TMC_STATE_OUT_TRANSFER){
680
 
681
        /* set the correct byte_count value */
682
        /* read byte counter register of EP2FIFOBUF */
683
        byte_count = (EP2BCH << 8) + EP2BCL;
684
 
685
        /* decide which value is the smaller one */
686
        if((byte_count - offset) > usb_tmc_transfer.transfer_size) {
687
          byte_count = usb_tmc_transfer.transfer_size;
688
          /* transfer_size does not includ the header length: */
689
          byte_count += offset;
690
        }
691
 
692
        /* select what we have to to according to the parsed scpi command */
693
        switch (scpi_scanner.action) {
694
 
695
        case SYSTEM_RESET:
696
          /* Send a global reset signal to the FPGA and all connected modules */
697
          gecko3com_system_reset();
698
          usb_tmc_state = TMC_STATE_IDLE;
699
          break;
700
 
701
        case rqFPGA_IDCODE:
702
          /* Request to read the FPGA JTAG ID code */
703
          eeprom_read(FPGA_IDCODE_OFFSET, response_queue.buf, FPGA_IDCODE_LEN);
704
          response_queue.buf[FPGA_IDCODE_LEN] = '\n';
705
          response_queue.length = FPGA_IDCODE_LEN+1;
706
          IEEE488_set_mav();
707
          usb_tmc_state = TMC_STATE_IDLE;
708
          break;
709
 
710
        case rqFPGA_TYPE:
711
          /* Request to read the FPGA type string */
712
          eeprom_read(FPGA_TYPE_OFFSET, response_queue.buf, FPGA_TYPE_LEN);
713
          response_queue.buf[FPGA_TYPE_LEN] = '\n';
714
          response_queue.length = FPGA_TYPE_LEN+1;
715
          IEEE488_set_mav();
716
          usb_tmc_state = TMC_STATE_IDLE;
717
          break;
718
 
719
        case rqFPGA_DONE:
720
          /* Is the FPGA configured or not? Check the "done" pin*/
721
          if(fpga_done()) {
722
            response_queue.buf[0] = '1';
723
          }
724
          else {
725
            response_queue.buf[0] = '0';
726
          }
727
          response_queue.buf[1] = '\n';
728
          response_queue.length = 2;
729
          usb_tmc_state = TMC_STATE_IDLE;
730
          break;
731
 
732
        case FPGA_CONFIGURE:
733
          /* Configure the FPGA directly */
734
          if(!app_configure_fpga(&offset, &byte_count)) {
735
            //print_err("conf\n");
736
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
737
            usb_tmc_state = TMC_STATE_IDLE;
738
          }
739
          break;
740
 
741
        case FPGA_COMMUNICATION:
742
          /* Switch the context from the FX2 to the FPGA.
743
           * After this command all endpoint 2 and 6 data goes directly to the
744
           * FPGA, the FX2 doesn't parse commands anymore. Use endpoint 0 TMC
745
           * commands to switch back */
746
          init_gpif();
747
          flLOCAL = GECKO3COM_REMOTE;
748
          usb_tmc_state = TMC_STATE_IDLE;
749
          break;
750
 
751
        case SPI_DELETE:
752
          /* Erases one of the file spaces in the SPI flash  */
753
          if(!app_gecko3com_flash_delete(&offset)) {
754
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
755
          }
756
          usb_tmc_state = TMC_STATE_IDLE;
757
          break;
758
 
759
        case SPI_WRITE:
760
          /* Writes a FPGA configuration file into a file space in the
761
           * SPI flash. */
762
          if(!app_write_conf_to_flash(&offset, &byte_count)) {
763
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
764
            usb_tmc_state = TMC_STATE_IDLE;
765
          }
766
          break;
767
 
768
        default:
769
 
770
          usb_tmc_state = TMC_STATE_IDLE;
771
        }
772
      }
773
 
774
      usb_tmc_transfer.nbytes_rxd += ((EP2BCH << 8) + EP2BCL - USB_TMC_HEADER_SIZE);
775
 
776
      /* finished handling usb package.
777
       * rearm OUT endpoint to receive new data */
778
      OUTPKTEND = bmSKIP | USB_TMC_EP_OUT;
779
 
780
    } /* end of OUT Transfer clause */
781
 
782
 
783
    /* -------------------------------------------------------------------- */
784
    /* Let's continue to send data when an Endpoint is free */
785
    /* IN Transfer: Generate a valid TMC IN header and send the response
786
     * message data to the endpoint */
787
    if (!(EP2468STAT & bmEP6FULL) && usb_tmc_state == TMC_STATE_IN_TRANSFER){
788
 
789
      /* fresh IN transfer, send first header */
790
      if(usb_tmc_transfer.nbytes_txd == 0) {
791
        index = 0;
792
        tmc_response_header = (tHeader*)EP6FIFOBUF;
793
        tmc_response_header->MsgID = REQUEST_DEV_DEP_MSG_IN;
794
        tmc_response_header->bTag = usb_tmc_transfer.bTag;
795
        tmc_response_header->bTagInverse = ~usb_tmc_transfer.bTag;
796
        tmc_response_header->Reserved = 0;
797
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)-> \
798
          TransferSize = response_queue.length;
799
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
800
          Reserved[0] = 0;
801
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
802
          Reserved[1] = 0;
803
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
804
          Reserved[2] = 0;
805
 
806
        /* if we can send all data in one usb packet,
807
           set EOM (end of message) bit */
808
        /* WARNING: set EOM bit in the LAST tmc transfer.
809
         * we transmitt anything in one transfer so we set this bit always. */
810
        /*if(USBCS & bmHSM && response_queue.length <= 500 | \
811
          response_queue.length <= 56)*/
812
          ((DEV_DEP_MSG_OUT_Header*)tmc_response_header->msg_specific)->\
813
            bmTransferAttributes = bmTA_EOM;
814
          /*else
815
          ((DEV_DEP_MSG_OUT_Header*)tmc_response_header->msg_specific)->\
816
          bmTransferAttributes = 0;*/
817
 
818
        index = USB_TMC_HEADER_SIZE;
819
      } /* finished writing header */
820
 
821
 
822
      /* Transmit data */
823
      for(usb_tmc_transfer.nbytes_txd; \
824
          usb_tmc_transfer.nbytes_txd <= response_queue.length; \
825
          usb_tmc_transfer.nbytes_txd++){
826
 
827
        /* copy the data from the response queue to the IN endpoint */
828
        EP6FIFOBUF[index++] = response_queue.buf[usb_tmc_transfer.nbytes_txd];
829
 
830
        /* we send any response in one packet so we don't have to check if
831
         * the endpoint buffer is full */
832
        /*if(!(USBCS & bmHSM) && index == 64 |  \
833
           index == 512)
834
          break;
835
        */
836
      }
837
 
838
      EP6BCH = index >> 8;
839
      EP6BCL = index & 0xFF;
840
      index = 0;
841
 
842
      /* detect end of transfer */
843
      if(usb_tmc_transfer.nbytes_txd >= response_queue.length){
844
        usb_tmc_state = TMC_STATE_IDLE;
845
        IEEE488_clear_mav();
846
        response_queue.length = 0;
847
      }
848
    } /* end of IN Transfer clause */
849
 
850
    /* if the LED flag is set to off, disable the external LED */
851
    if(flLED == LEDS_OFF) {
852
      set_led_ext(LEDS_OFF);
853
    }
854
 
855
    /* resets the watchdog timer back to the initial value */
856
    watchdog_count = WATCHDOG_TIME;
857
 
858
  } /* end of infinite main loop */
859
}
860
 
861
 
862
/** \brief ISR called at 100 Hz from timer2 interrupt
863
 *
864
 * Toggle led 0
865
 */
866
void isr_tick (void) interrupt
867
{
868
  static uint8_t count = 1;
869
 
870
  if (--count == 0){
871
    count = 50;
872
    toggle_led_0();
873
    flLED = LEDS_OFF;
874
  }
875
 
876
  //  if (--watchdog_count == 0){
877
  //    clear_timer_irq(); 
878
  //  #ifdef DEBUG_LEVEL_ERROR
879
    //  print_err("Watchdog timed out! System reset\n");
880
  //mdelay(100);             /* wait 100 ms to give the uart some time to transmit */
881
  //  #endif
882
 
883
      /* simulate CPU reset */  /* FIXME this stuff here does not work. no idea how to simulate an CPU reset instead... */
884
      /* _asm
885
      ljmp    __reset_vector
886
      _endasm;*/
887
  //}
888
 
889
#ifdef USB_DFU_SUPPORT
890
  if (usb_dfu_state == DFU_STATE_appDETACH){
891
    if (--usb_dfu_timeout == 0){
892
      usb_toggle_dfu_handlers();
893
    }
894
  }
895
#endif
896
 
897
  clear_timer_irq();
898
}
899
 
900
 
901
/** \brief starting point of execution.
902
 *
903
 * we initialize all system components here. after that we go to the main_loop
904
 * function there all the work is done.
905
 */
906
void main(void)
907
{
908
  /* variables needed for the stand-alone fpga configuration */
909
  uint8_t led_color;
910
  idata uint16_t i, local_offset;
911
  xdata uint32_t spi_base_adress;
912
 
913
  init_gecko3com();
914
  init_io_ext();
915
  init_usb_tmc();
916
  init_fpga_interface();
917
  init_spiflash(&flash_dr);
918
 
919
  /* disconnect USB, so the host doesn't wait for us during the fpga
920
   *configuration process (takes up to 20s) */
921
  USBCS |= bmDISCON;
922
 
923
#ifdef DEBUG_LEVEL_ERROR
924
  ser_init();
925
  printf_tiny("hi\n");
926
#endif
927
 
928
  /* set the context switch flag to local operation, not fpga */
929
  flLOCAL = GECKO3COM_LOCAL;
930
 
931
  /* enable GPIF state output for debuging  */
932
  IFCONFIG |= bmGSTATE;
933
 
934
  EA = 0;                /* disable all interrupts */
935
 
936
  patch_usb_descriptors();
937
  setup_autovectors();
938
  usb_install_handlers();
939
  hook_timer_tick((unsigned short) isr_tick);
940
 
941
  EA = 1;               /* global interrupt enable */
942
 
943
  /* finished initializing GECKO3COM system */
944
  /*------------------------------------------------------------------------*/
945
 
946
  /* start to configure the FPGA from the configuration SPI flash */
947
  /* read which configuration, the first or second, we should use */
948
  if(get_switch()){
949
    led_color = GREEN;
950
    spi_base_adress = START_ADRESS_SLOT0;
951
  }
952
  else {
953
    led_color = RED;
954
    spi_base_adress = START_ADRESS_SLOT1;
955
  }
956
 
957
  /* read the configuration file size from the spi flash */
958
  spiflash_read(&flash_dr, &spi_base_adress, response_queue.buf, 4);
959
  ((idata uint8_t*)&file_size)[0] = response_queue.buf[0];
960
  ((idata uint8_t*)&file_size)[1] = response_queue.buf[1];
961
  ((idata uint8_t*)&file_size)[2] = response_queue.buf[2];
962
  ((idata uint8_t*)&file_size)[3] = response_queue.buf[3];
963
  spi_base_adress += 4;
964
 
965
  /* there is nothing to configure when the filesize is 0 or 0xFFFFFFFF */
966
  if(file_size == 0 || file_size == 0xFFFFFFFF) {
967
    /* show that we don't load a config */
968
    set_led_ext(ORANGE);
969
  }
970
  else {
971
    fpga_load_begin();
972
    i = TMC_RESPONSE_QUEUE_LENGTH-1;
973
    while(file_size > 0) {
974
      set_led_ext(led_color); /* show which config we load */
975
 
976
      if(i > file_size) {
977
        i = (uint8_t)file_size;
978
      }
979
      spiflash_read(&flash_dr, &spi_base_adress, response_queue.buf, i);
980
 
981
      local_offset = 0;
982
      fpga_load_xfer(response_queue.buf, &local_offset, &i);
983
      file_size -= i;
984
      spi_base_adress += i;
985
    }
986
    fpga_load_end();
987
  }
988
 
989
  USBCS &= ~bmDISCON;           /* reconnect USB */
990
 
991
  main_loop();
992
}

powered by: WebSVN 2.1.0

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