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 18

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 13 nussgipfel
      flash_adress = start_adress_slot0(flash_dr);
310 9 nussgipfel
    }
311
    else if(buffer[*offset] == '1'){
312 13 nussgipfel
      flash_adress = start_adress_slot1(flash_dr);
313 9 nussgipfel
    }
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 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
  /* 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 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
        /* start to analyze the data in Endpoint 2 if it is a correct TMC header */
597
        tmc_header = (tHeader*)EP2FIFOBUF;
598
 
599
        /* bTag sanity check. store bTag for correct IN transfer response */
600
        if (tmc_header->bTag == ~tmc_header->bTagInverse) {
601
          usb_tmc_transfer.bTag = tmc_header->bTag;
602
 
603
          /* TMC header is correct. Now find out what we have to do: */
604
 
605
          /* check if this transfer is a DEV_DEP_MSG_OUT message */
606
          if(tmc_header->MsgID == DEV_DEP_MSG_OUT){
607
            usb_tmc_transfer.transfer_size = \
608
              ((DEV_DEP_MSG_OUT_Header*)tmc_header->msg_specific)->TransferSize;
609
            usb_tmc_transfer.new_transfer = NEWTRANSFER;
610
            offset = USB_TMC_HEADER_SIZE;
611
 
612
            /* Decide if we should start the SCPI parser or not
613
             * if not IDLE, the transfer size was 0 and we continue
614
             * to exectue the action and don't try to parse a new command */
615
            if(usb_tmc_state == TMC_STATE_IDLE) {
616
 
617
              /* fresh OUT Transfer: handle device dependent command message */
618
              usb_tmc_state = TMC_STATE_OUT_TRANSFER;
619
              usb_tmc_transfer.nbytes_rxd = 0;
620
 
621
              /* when we receive an new out message before we sent the response,
622
               * we have to clear the response queue first*/
623
              IEEE488_clear_mav();
624
              usb_tmc_transfer.nbytes_txd = 0;
625
              response_queue.length = 0;
626
 
627
 
628
              /* setup variables for scpi parser.
629
               * offset points to first command byte in endpoint buffer */
630
              scpi_scanner.source = EP2FIFOBUF;
631
              scpi_scanner.action = NOACTION;
632
 
633
              /* start SCPI parser */
634
              if(!scpi_scan(&offset, &scpi_scanner, &response_queue)){
635
                /* the parser returned an error. set flags */
636
                ieee488_status.EventStatusRegister |= bmCOMMAND_ERROR;
637
                usb_tmc_state = TMC_STATE_IDLE;
638
                scpi_scanner.action = NOACTION;
639
                usb_tmc_transfer.new_transfer = 0;
640
                //print_err("syntax failure\n");
641
              }
642
            }
643
          }
644
          /* finished handling an DEV_DEP_MSG_OUT message */
645
 
646
          /* ---------------------------------------------------------------- */
647
          /* check if this transfer is a IN request and we have a IN response
648
           * queued */
649
          else if(tmc_header->MsgID == REQUEST_DEV_DEP_MSG_IN \
650
                  && response_queue.length > 0) {
651
 
652
            /* IN Transfer: Handle response message to a device dependent
653
             * command message. For this we change the TMC state.
654
             * Sending the requested data to the IN endpoint
655
             * happens further below */
656
            usb_tmc_state = TMC_STATE_IN_TRANSFER;
657
            usb_tmc_transfer.transfer_size = \
658
              ((REQUEST_DEV_DEP_MSG_IN_Header*) tmc_header->msg_specific)\
659
              ->TransferSize;
660
            usb_tmc_transfer.nbytes_txd = 0;
661
 
662
          }
663
          else {
664
            /* TMC header error: unknown message ID */
665
            EP2CS |= bmEPSTALL;
666
            //print_err("ID\n");
667
          }
668
        }
669
 
670
        else {
671
          /* TMC header error: bTag and bTagInverse don't match */
672
          EP2CS |= bmEPSTALL;
673
          //print_err("bTag\n");
674
        }
675
      }
676
 
677
      /* -------------------------------------------------------------------- */
678
      /* OUT Transfer: The SCPI parser has detected a application specific
679
       * command. Here we execute the desired functions for these commands: */
680
      if(usb_tmc_state == TMC_STATE_OUT_TRANSFER){
681
 
682
        /* set the correct byte_count value */
683
        /* read byte counter register of EP2FIFOBUF */
684
        byte_count = (EP2BCH << 8) + EP2BCL;
685
 
686
        /* decide which value is the smaller one */
687
        if((byte_count - offset) > usb_tmc_transfer.transfer_size) {
688
          byte_count = usb_tmc_transfer.transfer_size;
689
          /* transfer_size does not includ the header length: */
690
          byte_count += offset;
691
        }
692
 
693
        /* select what we have to to according to the parsed scpi command */
694
        switch (scpi_scanner.action) {
695
 
696
        case SYSTEM_RESET:
697
          /* Send a global reset signal to the FPGA and all connected modules */
698
          gecko3com_system_reset();
699
          usb_tmc_state = TMC_STATE_IDLE;
700
          break;
701
 
702
        case rqFPGA_IDCODE:
703
          /* Request to read the FPGA JTAG ID code */
704
          eeprom_read(FPGA_IDCODE_OFFSET, response_queue.buf, FPGA_IDCODE_LEN);
705
          response_queue.buf[FPGA_IDCODE_LEN] = '\n';
706
          response_queue.length = FPGA_IDCODE_LEN+1;
707
          IEEE488_set_mav();
708
          usb_tmc_state = TMC_STATE_IDLE;
709
          break;
710
 
711
        case rqFPGA_TYPE:
712
          /* Request to read the FPGA type string */
713
          eeprom_read(FPGA_TYPE_OFFSET, response_queue.buf, FPGA_TYPE_LEN);
714
          response_queue.buf[FPGA_TYPE_LEN] = '\n';
715
          response_queue.length = FPGA_TYPE_LEN+1;
716
          IEEE488_set_mav();
717
          usb_tmc_state = TMC_STATE_IDLE;
718
          break;
719
 
720
        case rqFPGA_DONE:
721
          /* Is the FPGA configured or not? Check the "done" pin*/
722
          if(fpga_done()) {
723
            response_queue.buf[0] = '1';
724
          }
725
          else {
726
            response_queue.buf[0] = '0';
727
          }
728
          response_queue.buf[1] = '\n';
729
          response_queue.length = 2;
730
          usb_tmc_state = TMC_STATE_IDLE;
731
          break;
732
 
733
        case FPGA_CONFIGURE:
734
          /* Configure the FPGA directly */
735
          if(!app_configure_fpga(&offset, &byte_count)) {
736
            //print_err("conf\n");
737
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
738
            usb_tmc_state = TMC_STATE_IDLE;
739
          }
740
          break;
741
 
742
        case FPGA_COMMUNICATION:
743
          /* Switch the context from the FX2 to the FPGA.
744
           * After this command all endpoint 2 and 6 data goes directly to the
745
           * FPGA, the FX2 doesn't parse commands anymore. Use endpoint 0 TMC
746
           * commands to switch back */
747
          init_gpif();
748
          flLOCAL = GECKO3COM_REMOTE;
749
          usb_tmc_state = TMC_STATE_IDLE;
750
          break;
751
 
752
        case SPI_DELETE:
753
          /* Erases one of the file spaces in the SPI flash  */
754
          if(!app_gecko3com_flash_delete(&offset)) {
755
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
756
          }
757
          usb_tmc_state = TMC_STATE_IDLE;
758
          break;
759
 
760
        case SPI_WRITE:
761
          /* Writes a FPGA configuration file into a file space in the
762
           * SPI flash. */
763
          if(!app_write_conf_to_flash(&offset, &byte_count)) {
764
            ieee488_status.EventStatusRegister |= bmEXECUTION_ERROR;
765
            usb_tmc_state = TMC_STATE_IDLE;
766
          }
767
          break;
768
 
769
        default:
770
 
771
          usb_tmc_state = TMC_STATE_IDLE;
772
        }
773
      }
774
 
775
      usb_tmc_transfer.nbytes_rxd += ((EP2BCH << 8) + EP2BCL - USB_TMC_HEADER_SIZE);
776
 
777
      /* finished handling usb package.
778
       * rearm OUT endpoint to receive new data */
779
      OUTPKTEND = bmSKIP | USB_TMC_EP_OUT;
780
 
781
    } /* end of OUT Transfer clause */
782
 
783
 
784
    /* -------------------------------------------------------------------- */
785
    /* Let's continue to send data when an Endpoint is free */
786
    /* IN Transfer: Generate a valid TMC IN header and send the response
787
     * message data to the endpoint */
788
    if (!(EP2468STAT & bmEP6FULL) && usb_tmc_state == TMC_STATE_IN_TRANSFER){
789
 
790
      /* fresh IN transfer, send first header */
791
      if(usb_tmc_transfer.nbytes_txd == 0) {
792
        index = 0;
793
        tmc_response_header = (tHeader*)EP6FIFOBUF;
794
        tmc_response_header->MsgID = REQUEST_DEV_DEP_MSG_IN;
795
        tmc_response_header->bTag = usb_tmc_transfer.bTag;
796
        tmc_response_header->bTagInverse = ~usb_tmc_transfer.bTag;
797
        tmc_response_header->Reserved = 0;
798
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)-> \
799
          TransferSize = response_queue.length;
800
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
801
          Reserved[0] = 0;
802
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
803
          Reserved[1] = 0;
804
        ((DEV_DEP_MSG_IN_Header*)tmc_response_header->msg_specific)->\
805
          Reserved[2] = 0;
806
 
807
        /* if we can send all data in one usb packet,
808
           set EOM (end of message) bit */
809
        /* WARNING: set EOM bit in the LAST tmc transfer.
810
         * we transmitt anything in one transfer so we set this bit always. */
811
        /*if(USBCS & bmHSM && response_queue.length <= 500 | \
812
          response_queue.length <= 56)*/
813
          ((DEV_DEP_MSG_OUT_Header*)tmc_response_header->msg_specific)->\
814
            bmTransferAttributes = bmTA_EOM;
815
          /*else
816
          ((DEV_DEP_MSG_OUT_Header*)tmc_response_header->msg_specific)->\
817
          bmTransferAttributes = 0;*/
818
 
819
        index = USB_TMC_HEADER_SIZE;
820
      } /* finished writing header */
821
 
822
 
823
      /* Transmit data */
824
      for(usb_tmc_transfer.nbytes_txd; \
825
          usb_tmc_transfer.nbytes_txd <= response_queue.length; \
826
          usb_tmc_transfer.nbytes_txd++){
827
 
828
        /* copy the data from the response queue to the IN endpoint */
829
        EP6FIFOBUF[index++] = response_queue.buf[usb_tmc_transfer.nbytes_txd];
830
 
831
        /* we send any response in one packet so we don't have to check if
832
         * the endpoint buffer is full */
833
        /*if(!(USBCS & bmHSM) && index == 64 |  \
834
           index == 512)
835
          break;
836
        */
837
      }
838
 
839
      EP6BCH = index >> 8;
840
      EP6BCL = index & 0xFF;
841
      index = 0;
842
 
843
      /* detect end of transfer */
844
      if(usb_tmc_transfer.nbytes_txd >= response_queue.length){
845
        usb_tmc_state = TMC_STATE_IDLE;
846
        IEEE488_clear_mav();
847
        response_queue.length = 0;
848
      }
849
    } /* end of IN Transfer clause */
850
 
851 18 nussgipfel
    /* if(!(EP2468STAT & bmEP2EMPTY) && flLOCAL == GECKO3COM_REMOTE) { */
852
    /*   flGPIF &= ~bmGPIF_PENDING_DATA; */
853
    /*   OUTPKTEND = USB_TMC_EP_OUT; */
854
    /*   gpif_trigger_write(); */
855
    /*   EP2FIFOCFG |= bmAUTOOUT; */
856
    /* } */
857
 
858 9 nussgipfel
    /* if the LED flag is set to off, disable the external LED */
859
    if(flLED == LEDS_OFF) {
860
      set_led_ext(LEDS_OFF);
861
    }
862
 
863
    /* resets the watchdog timer back to the initial value */
864
    watchdog_count = WATCHDOG_TIME;
865
 
866
  } /* end of infinite main loop */
867
}
868
 
869
 
870
/** \brief ISR called at 100 Hz from timer2 interrupt
871
 *
872
 * Toggle led 0
873
 */
874
void isr_tick (void) interrupt
875
{
876
  static uint8_t count = 1;
877
 
878
  if (--count == 0){
879
    count = 50;
880
    toggle_led_0();
881
    flLED = LEDS_OFF;
882
  }
883
 
884
  //  if (--watchdog_count == 0){
885
  //    clear_timer_irq(); 
886
  //  #ifdef DEBUG_LEVEL_ERROR
887
    //  print_err("Watchdog timed out! System reset\n");
888
  //mdelay(100);             /* wait 100 ms to give the uart some time to transmit */
889
  //  #endif
890
 
891
      /* simulate CPU reset */  /* FIXME this stuff here does not work. no idea how to simulate an CPU reset instead... */
892
      /* _asm
893
      ljmp    __reset_vector
894
      _endasm;*/
895
  //}
896
 
897
#ifdef USB_DFU_SUPPORT
898
  if (usb_dfu_state == DFU_STATE_appDETACH){
899
    if (--usb_dfu_timeout == 0){
900
      usb_toggle_dfu_handlers();
901
    }
902
  }
903
#endif
904
 
905
  clear_timer_irq();
906
}
907
 
908
 
909
/** \brief starting point of execution.
910
 *
911
 * we initialize all system components here. after that we go to the main_loop
912
 * function there all the work is done.
913
 */
914
void main(void)
915
{
916
  /* variables needed for the stand-alone fpga configuration */
917
  uint8_t led_color;
918
  idata uint16_t i, local_offset;
919
  xdata uint32_t spi_base_adress;
920
 
921
  init_gecko3com();
922
  init_io_ext();
923
  init_usb_tmc();
924
  init_fpga_interface();
925
  init_spiflash(&flash_dr);
926
 
927
  /* disconnect USB, so the host doesn't wait for us during the fpga
928
   *configuration process (takes up to 20s) */
929
  USBCS |= bmDISCON;
930
 
931
#ifdef DEBUG_LEVEL_ERROR
932
  ser_init();
933
  printf_tiny("hi\n");
934
#endif
935
 
936
  /* set the context switch flag to local operation, not fpga */
937
  flLOCAL = GECKO3COM_LOCAL;
938
 
939
  /* enable GPIF state output for debuging  */
940
  IFCONFIG |= bmGSTATE;
941
 
942
  EA = 0;                /* disable all interrupts */
943
 
944
  patch_usb_descriptors();
945
  setup_autovectors();
946
  usb_install_handlers();
947
  hook_timer_tick((unsigned short) isr_tick);
948
 
949
  EA = 1;               /* global interrupt enable */
950
 
951
  /* finished initializing GECKO3COM system */
952
  /*------------------------------------------------------------------------*/
953
 
954
  /* start to configure the FPGA from the configuration SPI flash */
955
  /* read which configuration, the first or second, we should use */
956
  if(get_switch()){
957
    led_color = GREEN;
958 13 nussgipfel
    spi_base_adress = start_adress_slot0(flash_dr);
959 9 nussgipfel
  }
960
  else {
961
    led_color = RED;
962 13 nussgipfel
    spi_base_adress = start_adress_slot1(flash_dr);
963 9 nussgipfel
  }
964
 
965
  /* read the configuration file size from the spi flash */
966
  spiflash_read(&flash_dr, &spi_base_adress, response_queue.buf, 4);
967
  ((idata uint8_t*)&file_size)[0] = response_queue.buf[0];
968
  ((idata uint8_t*)&file_size)[1] = response_queue.buf[1];
969
  ((idata uint8_t*)&file_size)[2] = response_queue.buf[2];
970
  ((idata uint8_t*)&file_size)[3] = response_queue.buf[3];
971
  spi_base_adress += 4;
972
 
973 13 nussgipfel
  /* debug stuff */
974
  response_queue.buf[0] = init_spiflash(&flash_dr);
975
  IEEE488_set_mav();
976
  response_queue.length = 1;
977
 
978 9 nussgipfel
  /* there is nothing to configure when the filesize is 0 or 0xFFFFFFFF */
979
  if(file_size == 0 || file_size == 0xFFFFFFFF) {
980
    /* show that we don't load a config */
981
    set_led_ext(ORANGE);
982
  }
983
  else {
984
    fpga_load_begin();
985
    i = TMC_RESPONSE_QUEUE_LENGTH-1;
986
    while(file_size > 0) {
987
      set_led_ext(led_color); /* show which config we load */
988
 
989
      if(i > file_size) {
990
        i = (uint8_t)file_size;
991
      }
992
      spiflash_read(&flash_dr, &spi_base_adress, response_queue.buf, i);
993
 
994
      local_offset = 0;
995
      fpga_load_xfer(response_queue.buf, &local_offset, &i);
996
      file_size -= i;
997
      spi_base_adress += i;
998
    }
999
    fpga_load_end();
1000
  }
1001
 
1002
  USBCS &= ~bmDISCON;           /* reconnect USB */
1003
 
1004
  main_loop();
1005
}

powered by: WebSVN 2.1.0

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