update new chopstx and use adc_buf for speed
[gnuk/neug.git] / src / main.c
1 /*
2  * main.c - main routine of neug
3  *
4  * Main routine:
5  * Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
6  * Author: NIIBE Yutaka <gniibe@fsij.org>
7  *
8  * This file is a part of NeuG, a True Random Number Generator
9  * implementation.
10  *
11  * NeuG is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * NeuG is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19  * License for more details.
20  *
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
27 #include <stdint.h>
28 #include <string.h>
29 #include <chopstx.h>
30
31 #include "config.h"
32 #include "neug.h"
33 #include "usb_lld.h"
34 #include "sys.h"
35 #include "stm32f103.h"
36 #include "adc.h"
37
38 chopstx_mutex_t usb_mtx;
39 chopstx_cond_t cnd_usb;
40
41 #define ENDP0_RXADDR        (0x40)
42 #define ENDP0_TXADDR        (0x80)
43 #define ENDP1_TXADDR        (0xc0)
44 #define ENDP2_TXADDR        (0x100)
45 #define ENDP3_RXADDR        (0x140)
46
47 #define USB_CDC_REQ_SET_LINE_CODING             0x20
48 #define USB_CDC_REQ_GET_LINE_CODING             0x21
49 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE      0x22
50 #define USB_CDC_REQ_SEND_BREAK                  0x23
51
52 /* USB Device Descriptor */
53 static const uint8_t vcom_device_desc[18] = {
54   18,   /* bLength */
55   USB_DEVICE_DESCRIPTOR_TYPE,   /* bDescriptorType */
56   0x10, 0x01,                   /* bcdUSB = 1.1 */
57   0x02,                         /* bDeviceClass (CDC).              */
58   0x00,                         /* bDeviceSubClass.                 */
59   0x00,                         /* bDeviceProtocol.                 */
60   0x40,                         /* bMaxPacketSize.                  */
61 #include "usb-vid-pid-ver.c.inc"
62   1,                            /* iManufacturer.                   */
63   2,                            /* iProduct.                        */
64   3,                            /* iSerialNumber.                   */
65   1                             /* bNumConfigurations.              */
66 };
67
68 /* Configuration Descriptor tree for a CDC.*/
69 static const uint8_t vcom_configuration_desc[67] = {
70   9,
71   USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
72   /* Configuration Descriptor.*/
73   67, 0x00,                     /* wTotalLength.                    */
74   0x02,                         /* bNumInterfaces.                  */
75   0x01,                         /* bConfigurationValue.             */
76   0,                            /* iConfiguration.                  */
77   0x80,                         /* bmAttributes (bus powered).      */
78   50,                           /* bMaxPower (100mA).               */
79   /* Interface Descriptor.*/
80   9,
81   USB_INTERFACE_DESCRIPTOR_TYPE,
82   0x00,            /* bInterfaceNumber.                */
83   0x00,            /* bAlternateSetting.               */
84   0x01,            /* bNumEndpoints.                   */
85   0x02,            /* bInterfaceClass (Communications Interface Class,
86                       CDC section 4.2).  */
87   0x02,            /* bInterfaceSubClass (Abstract Control Model, CDC
88                       section 4.3).  */
89   0x01,            /* bInterfaceProtocol (AT commands, CDC section
90                       4.4).  */
91   0,               /* iInterface.                      */
92   /* Header Functional Descriptor (CDC section 5.2.3).*/
93   5,          /* bLength.                         */
94   0x24,       /* bDescriptorType (CS_INTERFACE).  */
95   0x00,       /* bDescriptorSubtype (Header Functional Descriptor). */
96   0x10, 0x01, /* bcdCDC.                          */
97   /* Call Management Functional Descriptor. */
98   5,            /* bFunctionLength.                 */
99   0x24,         /* bDescriptorType (CS_INTERFACE).  */
100   0x01,         /* bDescriptorSubtype (Call Management Functional
101                    Descriptor). */
102   0x03,         /* bmCapabilities (D0+D1).          */
103   0x01,         /* bDataInterface.                  */
104   /* ACM Functional Descriptor.*/
105   4,            /* bFunctionLength.                 */
106   0x24,         /* bDescriptorType (CS_INTERFACE).  */
107   0x02,         /* bDescriptorSubtype (Abstract Control Management
108                    Descriptor).  */
109   0x02,         /* bmCapabilities.                  */
110   /* Union Functional Descriptor.*/
111   5,            /* bFunctionLength.                 */
112   0x24,         /* bDescriptorType (CS_INTERFACE).  */
113   0x06,         /* bDescriptorSubtype (Union Functional
114                    Descriptor).  */
115   0x00,         /* bMasterInterface (Communication Class
116                    Interface).  */
117   0x01,         /* bSlaveInterface0 (Data Class Interface).  */
118   /* Endpoint 2 Descriptor.*/
119   7,
120   USB_ENDPOINT_DESCRIPTOR_TYPE,
121   ENDP2|0x80,    /* bEndpointAddress.    */
122   0x03,          /* bmAttributes (Interrupt).        */
123   0x08, 0x00,    /* wMaxPacketSize.                  */
124   0xFF,          /* bInterval.                       */
125   /* Interface Descriptor.*/
126   9,
127   USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
128   0x01,          /* bInterfaceNumber.                */
129   0x00,          /* bAlternateSetting.               */
130   0x02,          /* bNumEndpoints.                   */
131   0x0A,          /* bInterfaceClass (Data Class Interface, CDC section 4.5). */
132   0x00,          /* bInterfaceSubClass (CDC section 4.6). */
133   0x00,          /* bInterfaceProtocol (CDC section 4.7). */
134   0x00,          /* iInterface.                      */
135   /* Endpoint 3 Descriptor.*/
136   7,
137   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
138   ENDP3,    /* bEndpointAddress. */
139   0x02,                         /* bmAttributes (Bulk).             */
140   0x40, 0x00,                   /* wMaxPacketSize.                  */
141   0x00,                         /* bInterval.                       */
142   /* Endpoint 1 Descriptor.*/
143   7,
144   USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
145   ENDP1|0x80,                   /* bEndpointAddress. */
146   0x02,                         /* bmAttributes (Bulk).             */
147   0x40, 0x00,                   /* wMaxPacketSize.                  */
148   0x00                          /* bInterval.                       */
149 };
150
151
152 /*
153  * U.S. English language identifier.
154  */
155 static const uint8_t vcom_string0[4] = {
156   4,                            /* bLength */
157   USB_STRING_DESCRIPTOR_TYPE,
158   0x09, 0x04                    /* LangID = 0x0409: US-English */
159 };
160
161 #define USB_STRINGS_FOR_NEUG 1
162 #include "usb-strings.c.inc"
163
164 /*
165  * Serial Number string.  NOTE: This does not have CONST qualifier.
166  */
167 static uint8_t vcom_string3[28] = {
168   28,                    /* bLength.                         */
169   USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType.                 */
170   '0', 0,  '.', 0,  '0', 0, '6', 0,    /* Version number of NeuG.          */
171   '-', 0,
172   0, 0, 0, 0,   /* Filled by Unique device ID.      */
173   0, 0, 0, 0,
174   0, 0, 0, 0,
175   0, 0, 0, 0,
176 };
177
178
179 #define NUM_INTERFACES 2
180
181 uint32_t bDeviceState = UNCONNECTED; /* USB device status */
182
183 void
184 usb_cb_device_reset (void)
185 {
186   /* Set DEVICE as not configured */
187   usb_lld_set_configuration (0);
188
189   /* Current Feature initialization */
190   usb_lld_set_feature (vcom_configuration_desc[7]);
191
192   usb_lld_reset ();
193
194   /* Initialize Endpoint 0 */
195   usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
196 }
197
198 extern uint8_t _regnual_start, __heap_end__;
199
200 static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
201
202 /* USB vendor requests to control pipe */
203 #define USB_FSIJ_MEMINFO          0
204 #define USB_FSIJ_DOWNLOAD         1
205 #define USB_FSIJ_EXEC             2
206 #define USB_NEUG_GET_INFO       254
207 #define USB_NEUG_EXIT           255 /* Ask to exit and to receive reGNUal */
208
209 enum {
210   FSIJ_DEVICE_RUNNING = 0,
211   FSIJ_DEVICE_EXITED,
212   FSIJ_DEVICE_EXEC_REQUESTED,
213   /**/
214   FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
215 }; 
216
217 static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
218
219 static uint32_t rbit (uint32_t v)
220 {
221   uint32_t r;
222
223   asm ("rbit    %0, %1" : "=r" (r) : "r" (v));
224   return r;
225 }
226
227 /* After calling this function, CRC module remain enabled.  */
228 static int download_check_crc32 (const uint32_t *end_p)
229 {
230   uint32_t crc32 = *end_p;
231   const uint32_t *p;
232
233   RCC->AHBENR |= RCC_AHBENR_CRCEN;
234   CRC->CR = CRC_CR_RESET;
235
236   for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
237     CRC->DR = rbit (*p);
238
239   if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
240     return USB_SUCCESS;
241
242   return USB_UNSUPPORT;
243 }
244
245 void
246 usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
247                           uint16_t index, uint16_t len)
248 {
249   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
250
251   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
252       && USB_SETUP_SET (req) && len == 0)
253     {
254       if (req_no == USB_FSIJ_EXEC)
255         {
256           if (fsij_device_state != FSIJ_DEVICE_EXITED)
257             return;
258
259           (void)value; (void)index;
260           usb_lld_prepare_shutdown (); /* No further USB communication */
261           fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
262         }
263       else if (req_no == USB_NEUG_EXIT)
264         {
265           /* Force exit from the main loop.  */
266           chopstx_mutex_lock (&usb_mtx);
267           chopstx_cond_signal (&cnd_usb);
268           chopstx_mutex_unlock (&usb_mtx);
269         }
270     }
271 }
272
273 struct line_coding
274 {
275   uint32_t bitrate;
276   uint8_t format;
277   uint8_t paritytype;
278   uint8_t datatype;
279 };
280
281 static struct line_coding line_coding = {
282   115200, /* baud rate: 115200    */
283   0x00,   /* stop bits: 1         */
284   0x00,   /* parity:    none      */
285   0x08    /* bits:      8         */
286 };
287
288 static uint8_t connected;
289
290 static int
291 vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
292 {
293   if (USB_SETUP_GET (req))
294     {
295       if (req_no == USB_CDC_REQ_GET_LINE_CODING)
296         {
297           usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
298           return USB_SUCCESS;
299         }
300     }
301   else  /* USB_SETUP_SET (req) */
302     {
303       if (req_no == USB_CDC_REQ_SET_LINE_CODING)
304         {
305           usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding));
306           return USB_SUCCESS;
307         }
308       else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
309         {
310           uint8_t connected_saved = connected;
311
312           if (value != 0)
313             {
314               if (connected == 0)
315                 /* It's Open call */
316                 connected++;
317             }
318           else
319             {
320               if (connected)
321                 /* Close call */
322                 connected = 0;
323             }
324
325           chopstx_mutex_lock (&usb_mtx);
326           if (connected != connected_saved)
327             chopstx_cond_signal (&cnd_usb);
328           chopstx_mutex_unlock (&usb_mtx);
329
330           return USB_SUCCESS;
331         }
332     }
333
334   return USB_UNSUPPORT;
335 }
336
337 int
338 usb_cb_setup (uint8_t req, uint8_t req_no,
339                uint16_t value, uint16_t index, uint16_t len)
340 {
341   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
342
343   if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
344     {
345       if (USB_SETUP_GET (req))
346         {
347           if (req_no == USB_FSIJ_MEMINFO)
348             {
349               usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
350               return USB_SUCCESS;
351             }
352           else if (req_no == USB_NEUG_GET_INFO)
353             {
354               if (index == 0)
355                 usb_lld_set_data_to_send (&neug_mode, sizeof (uint8_t));
356               else if (index == 1)
357                 usb_lld_set_data_to_send (&neug_err_cnt, sizeof (uint16_t));
358               else if (index == 2)
359                 usb_lld_set_data_to_send (&neug_err_cnt_rc, sizeof (uint16_t));
360               else if (index == 3)
361                 usb_lld_set_data_to_send (&neug_err_cnt_p64, sizeof (uint16_t));
362               else if (index == 4)
363                 usb_lld_set_data_to_send (&neug_err_cnt_p4k, sizeof (uint16_t));
364               else if (index == 5)
365                 usb_lld_set_data_to_send (&neug_rc_max, sizeof (uint16_t));
366               else if (index == 6)
367                 usb_lld_set_data_to_send (&neug_p64_max, sizeof (uint16_t));
368               else if (index == 7)
369                 usb_lld_set_data_to_send (&neug_p4k_max, sizeof (uint16_t));
370               else
371                 return USB_UNSUPPORT;
372
373               return USB_SUCCESS;
374             }
375         }
376       else /* SETUP_SET */
377         {
378           uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
379
380           if (req_no == USB_FSIJ_DOWNLOAD)
381             {
382               if (fsij_device_state != FSIJ_DEVICE_EXITED)
383                 return USB_UNSUPPORT;
384
385               if (addr < &_regnual_start || addr + len > &__heap_end__)
386                 return USB_UNSUPPORT;
387
388               if (index + len < 256)
389                 memset (addr + index + len, 0, 256 - (index + len));
390
391               usb_lld_set_data_to_recv (addr, len);
392               return USB_SUCCESS;
393             }
394           else if (req_no == USB_FSIJ_EXEC && len == 0)
395             {
396               if (fsij_device_state != FSIJ_DEVICE_EXITED)
397                 return USB_UNSUPPORT;
398
399               if (((uint32_t)addr & 0x03))
400                 return USB_UNSUPPORT;
401
402               return download_check_crc32 ((uint32_t *)addr);
403             }
404           else if (req_no == USB_NEUG_EXIT && len == 0)
405             {
406               if (fsij_device_state != FSIJ_DEVICE_RUNNING)
407                 return USB_UNSUPPORT;
408
409               fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
410               return USB_SUCCESS;
411             }
412         }
413     }
414   else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
415     if (index == 0)
416       return vcom_port_data_setup (req, req_no, value);
417
418   return USB_UNSUPPORT;
419 }
420
421 int
422 usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
423 {
424   (void)index;
425   if (desc_type == DEVICE_DESCRIPTOR)
426     {
427       usb_lld_set_data_to_send (vcom_device_desc, sizeof (vcom_device_desc));
428       return USB_SUCCESS;
429     }
430   else if (desc_type == CONFIG_DESCRIPTOR)
431     {
432       usb_lld_set_data_to_send (vcom_configuration_desc,
433                                 sizeof (vcom_configuration_desc));
434       return USB_SUCCESS;
435     }
436   else if (desc_type == STRING_DESCRIPTOR)
437     {
438       uint8_t desc_index = value & 0xff;
439       const uint8_t *str;
440       int size;
441
442       switch (desc_index)
443         {
444         case 0:
445           str = vcom_string0;
446           size = sizeof (vcom_string0);
447           break;
448         case 1:
449           str = neug_string_vendor;
450           size = sizeof (neug_string_vendor);
451           break;
452         case 2:
453           str = neug_string_product;
454           size = sizeof (neug_string_product);
455           break;
456         case 3:
457           str = vcom_string3;
458           size = sizeof (vcom_string3);
459           break;
460         case 4:
461           str = neug_revision_detail;
462           size = sizeof (neug_revision_detail);
463           break;
464         case 5:
465           str = neug_config_options;
466           size = sizeof (neug_config_options);
467           break;
468         case 6:
469           str = sys_version;
470           size = sizeof (sys_version);
471           break;
472         default:
473           return USB_UNSUPPORT;
474         }
475
476       usb_lld_set_data_to_send (str, size);
477       return USB_SUCCESS;
478     }
479
480   return USB_UNSUPPORT;
481 }
482
483 static void
484 neug_setup_endpoints_for_interface (uint16_t interface, int stop)
485 {
486   if (interface == 0)
487     {
488       if (!stop)
489         usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
490       else
491         usb_lld_stall_tx (ENDP2);
492     }
493   else if (interface == 1)
494     {
495       if (!stop)
496         {
497           usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
498           usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
499         }
500       else
501         {
502           usb_lld_stall_tx (ENDP1);
503           usb_lld_stall_rx (ENDP3);
504         }
505     }
506 }
507
508 int usb_cb_handle_event (uint8_t event_type, uint16_t value)
509 {
510   int i;
511   uint8_t current_conf;
512
513   switch (event_type)
514     {
515     case USB_EVENT_ADDRESS:
516       bDeviceState = ADDRESSED;
517       return USB_SUCCESS;
518     case USB_EVENT_CONFIG:
519       current_conf = usb_lld_current_configuration ();
520       if (current_conf == 0)
521         {
522           if (value != 1)
523             return USB_UNSUPPORT;
524
525           usb_lld_set_configuration (1);
526           for (i = 0; i < NUM_INTERFACES; i++)
527             neug_setup_endpoints_for_interface (i, 0);
528           bDeviceState = CONFIGURED;
529         }
530       else if (current_conf != value)
531         {
532           if (value != 0)
533             return USB_UNSUPPORT;
534
535           usb_lld_set_configuration (0);
536           for (i = 0; i < NUM_INTERFACES; i++)
537             neug_setup_endpoints_for_interface (i, 1);
538           bDeviceState = ADDRESSED;
539         }
540       /* Do nothing when current_conf == value */
541       return USB_SUCCESS;
542
543       return USB_SUCCESS;
544     default:
545       break;
546     }
547
548   return USB_UNSUPPORT;
549 }
550
551
552 int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
553 {
554   static uint8_t zero = 0;
555
556   if (interface >= NUM_INTERFACES)
557     return USB_UNSUPPORT;
558
559   switch (cmd)
560     {
561     case USB_SET_INTERFACE:
562       if (alt != 0)
563         return USB_UNSUPPORT;
564       else
565         {
566           neug_setup_endpoints_for_interface (interface, 0);
567           return USB_SUCCESS;
568         }
569
570     case USB_GET_INTERFACE:
571       usb_lld_set_data_to_send (&zero, 1);
572       return USB_SUCCESS;
573
574     default:
575     case USB_QUERY_INTERFACE:
576       return USB_SUCCESS;
577     }
578 }
579
580 #define INTR_REQ_USB 20
581 #define PRIO_USB 2
582
583 static void *
584 usb_intr (void *arg)
585 {
586   chopstx_intr_t interrupt;
587
588   (void)arg;
589   asm volatile ("cpsid   i" : : : "memory");
590   /* Disable because usb_lld_init assumes interrupt handler.  */
591   usb_lld_init (vcom_configuration_desc[7]);
592   chopstx_claim_irq (&interrupt, INTR_REQ_USB);
593   /* Enable */
594   asm volatile ("cpsie   i" : : : "memory");
595
596   while (1)
597     {
598       chopstx_intr_wait (&interrupt);
599
600       /* Process interrupt. */
601       usb_interrupt_handler ();
602     }
603
604   return NULL;
605 }
606
607
608 static void fill_serial_no_by_unique_id (void)
609 {
610   extern const uint8_t * unique_device_id (void);
611   uint8_t *p = &vcom_string3[12];
612   const uint8_t *u = unique_device_id ();
613   int i;
614
615   for (i = 0; i < 4; i++)
616     {
617       uint8_t b = u[i];
618       uint8_t nibble; 
619
620       nibble = (b >> 4);
621       nibble += (nibble >= 10 ? ('A' - 10) : '0');
622       p[i*4] = nibble;
623       nibble = (b & 0x0f);
624       nibble += (nibble >= 10 ? ('A' - 10) : '0');
625       p[i*4+2] = nibble;
626     }
627 }
628 \f
629 void
630 EP1_IN_Callback (void)
631 {
632   chopstx_mutex_lock (&usb_mtx);
633   chopstx_cond_signal (&cnd_usb);
634   chopstx_mutex_unlock (&usb_mtx);
635 }
636
637 void
638 EP2_IN_Callback (void)
639 {
640 }
641
642 void
643 EP3_OUT_Callback (void)
644 {
645   usb_lld_rx_enable (ENDP3);
646 }
647 \f
648 typedef uint32_t eventmask_t;
649 #define ALL_EVENTS (~0)
650
651 struct event_flag {
652   chopstx_mutex_t mutex;
653   chopstx_cond_t cond;
654   eventmask_t flag;
655 };
656
657 static void event_flag_init (struct event_flag *ev)
658 {
659   ev->flag = 0;
660   chopstx_mutex_init (&ev->mutex);
661   chopstx_cond_init (&ev->cond);
662 }
663
664
665 static eventmask_t event_flag_waitone (struct event_flag *ev, eventmask_t m)
666 {
667   int n;
668
669   chopstx_mutex_lock (&ev->mutex);
670   while (!(ev->flag & m))
671     chopstx_cond_wait (&ev->cond, &ev->mutex);
672
673   n = __builtin_ffs ((ev->flag & m));
674   ev->flag &= ~(1 << (n - 1));
675   chopstx_mutex_unlock (&ev->mutex);
676
677   return (1 << (n - 1));
678 }
679
680 static void event_flag_signal (struct event_flag *ev, eventmask_t m)
681 {
682   chopstx_mutex_lock (&ev->mutex);
683   ev->flag |= m;
684   chopstx_cond_signal (&ev->cond);
685   chopstx_mutex_unlock (&ev->mutex);
686 }
687
688 extern uint8_t __process1_stack_base__, __process1_stack_size__;
689 extern uint8_t __process3_stack_base__, __process3_stack_size__;
690
691 const uint32_t __stackaddr_led = (uint32_t)&__process1_stack_base__;
692 const size_t __stacksize_led = (size_t)&__process1_stack_size__;
693 const uint32_t __stackaddr_usb = (uint32_t)&__process3_stack_base__;
694 const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
695
696
697 #define PRIO_LED 1
698 struct event_flag led_event;
699
700 #define LED_ONESHOT_SHORT       ((eventmask_t)1)
701 #define LED_TWOSHOTS            ((eventmask_t)2)
702 #define LED_ONESHOT_LONG        ((eventmask_t)4)
703
704 /*
705  * LED blinker: When notified, let LED emit for 100ms.
706  */
707 static void *led_blinker (void *arg)
708 {
709   (void)arg;
710
711   set_led (0);
712
713   while (1)
714     {
715       eventmask_t m;
716
717       m = event_flag_waitone (&led_event, ALL_EVENTS);
718       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
719         break;
720
721       set_led (1);
722       if (m == LED_ONESHOT_SHORT)
723         chopstx_usec_wait (100*1000);
724       else if (m == LED_TWOSHOTS)
725         {
726           chopstx_usec_wait (50*1000);
727           set_led (0);
728           chopstx_usec_wait (50*1000);
729           set_led (1);
730           chopstx_usec_wait (50*1000);
731         }
732       else
733         chopstx_usec_wait (250*1000);
734       set_led (0);
735     }
736
737   return 0;
738 }
739 \f
740 #define RANDOM_BYTES_LENGTH 64
741 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
742
743 static void copy_to_tx (uint32_t v, int i)
744 {
745   usb_lld_txcpy (&v, ENDP1, i * 4, 4);
746 }
747
748 /*
749  * In Gnuk 1.0.[12], reGNUal was not relocatable.
750  * Now, it's relocatable, but we need to calculate its entry address
751  * based on it's pre-defined address.
752  */
753 #define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
754 static uint32_t
755 calculate_regnual_entry_address (const uint8_t *addr)
756 {
757   const uint8_t *p = addr + 4;
758   uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
759
760   v -= REGNUAL_START_ADDRESS_COMPATIBLE;
761   v += (uint32_t)addr;
762   return v;
763 }
764
765
766 /*
767  * Entry point.
768  *
769  * NOTE: the main function is already a thread in the system on entry.
770  */
771 int
772 main (int argc, char **argv)
773 {
774   uint32_t entry;
775   chopstx_t led_thread, usb_thd;
776   chopstx_attr_t attr;
777
778   (void)argc;
779   (void)argv;
780
781   fill_serial_no_by_unique_id ();
782
783   adc_init ();
784
785   event_flag_init (&led_event);
786
787   chopstx_attr_init (&attr);
788   chopstx_attr_setschedparam (&attr, PRIO_LED);
789   chopstx_attr_setstack (&attr, __stackaddr_led, __stacksize_led);
790   chopstx_create (&led_thread, &attr, led_blinker, NULL);
791
792   chopstx_mutex_init (&usb_mtx);
793   chopstx_cond_init (&cnd_usb);
794
795   chopstx_attr_setschedparam (&attr, PRIO_USB);
796   chopstx_attr_setstack (&attr, __stackaddr_usb, __stacksize_usb);
797   chopstx_create (&usb_thd, &attr, usb_intr, NULL);
798
799   neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
800
801   while (1)
802     {
803       unsigned int count = 0;
804       int last_was_fullsizepacket = 0;
805
806       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
807         break;
808
809       while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
810         {
811           if (fsij_device_state != FSIJ_DEVICE_RUNNING)
812             break;
813
814           neug_wait_full ();
815           neug_flush ();
816
817           if ((count & 0x0007) == 0)
818             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
819           chopstx_usec_wait (25*1000);
820           count++;
821         }
822
823     waiting_connection:
824       while (connected == 0)
825         {
826           if (fsij_device_state != FSIJ_DEVICE_RUNNING)
827             break;
828
829           neug_flush ();
830           event_flag_signal (&led_event, LED_TWOSHOTS);
831           chopstx_usec_wait (5000*1000);
832         }
833
834       if (fsij_device_state != FSIJ_DEVICE_RUNNING)
835         break;
836
837       /* The connection opened.  */
838       count = 0;
839       /*
840        * No parity is standard.  It means to provide conditioned output.
841        * When parity enabled, it means to provide raw output.
842        */
843       neug_mode_select (line_coding.paritytype); /* 0: None, 1: Odd, 2: Even */
844
845       while (1)
846         {
847           int i;
848
849           if (fsij_device_state != FSIJ_DEVICE_RUNNING)
850             break;
851
852           if (bDeviceState != CONFIGURED)
853             break;
854
855           if ((count & 0x03ff) == 0)
856             event_flag_signal (&led_event, LED_ONESHOT_SHORT);
857
858           i = neug_consume_random (copy_to_tx);
859
860           if (i == 0 && !last_was_fullsizepacket)
861             {    /* Only send ZLP when the last packet was fullsize.  */
862               neug_wait_full ();
863               continue;
864             }
865
866           if (i == 64/4)
867             last_was_fullsizepacket = 1;
868           else
869             last_was_fullsizepacket = 0;
870
871           chopstx_mutex_lock (&usb_mtx);
872           if (connected == 0)
873             {
874               chopstx_mutex_unlock (&usb_mtx);
875               goto waiting_connection;
876             }
877           else
878             {
879               usb_lld_tx_enable (ENDP1, i * 4);
880               chopstx_cond_wait (&cnd_usb, &usb_mtx);
881             }
882           chopstx_mutex_unlock (&usb_mtx);
883
884           count++;
885         }
886     }
887
888   event_flag_signal (&led_event, LED_ONESHOT_SHORT);
889   chopstx_join (led_thread, NULL);
890
891   /*
892    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED.
893    */
894   neug_fini ();
895
896   fsij_device_state = FSIJ_DEVICE_EXITED;
897
898   while (fsij_device_state == FSIJ_DEVICE_EXITED)
899     chopstx_usec_wait (500*1000);
900
901   flash_unlock ();              /* Flash unlock should be done here */
902   set_led (1);
903   usb_lld_shutdown ();
904
905   /* Finish application.  */
906   chopstx_cancel (usb_thd);
907   chopstx_join (usb_thd, NULL);
908
909   /* Set vector */
910   SCB->VTOR = (uint32_t)&_regnual_start;
911   entry = calculate_regnual_entry_address (&_regnual_start);
912 #ifdef DFU_SUPPORT
913 #define FLASH_SYS_START_ADDR 0x08000000
914 #define FLASH_SYS_END_ADDR (0x08000000+0x1000)
915   {
916     extern uint8_t _sys;
917     uint32_t addr;
918     handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
919     void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10];
920
921     /* Kill DFU */
922     for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
923          addr += FLASH_PAGE_SIZE)
924       flash_erase_page (addr);
925
926     /* copy system service routines */
927     flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
928
929     /* Leave NeuG to exec reGNUal */
930     (*func) ((void (*)(void))entry);
931     for (;;);
932   }
933 #else
934   /* Leave NeuG to exec reGNUal */
935   flash_erase_all_and_exec ((void (*)(void))entry);
936 #endif
937
938   /* Never reached */
939   return 0;
940 }