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 36

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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