change NUM_NOISE_INPUTS, no SYSTICK, batch mode
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 27 Sep 2012 02:26:34 +0000 (11:26 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 27 Sep 2012 02:26:34 +0000 (11:26 +0900)
ChangeLog
NEWS [new file with mode: 0644]
README
src/main.c
src/random.c
tool/neug_upgrade.py

index e2a1ada..a1333be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-09-27  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/main.c (RANDOM_BYTES_LENGTH): 32 is best for SHA-256
+       construct.
+
+       * src/random.c (adc2_stop, ep_process): New.
+       (rng_gen): Call ep_process.
+
 2012-09-26  Niibe Yutaka  <gniibe@fsij.org>
 
        * boards/STM8S_DISCOVERY/mcuconf.h (STM32_PPRE2, STM32_ADCPRE):
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..1e68669
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,38 @@
+* Major changes in NeuG 0.02
+
+  Released 2012-08-30, by NIIBE Yutaka
+
+** Change RNG constuct.
+We replace all basic components.  Now, we use WELL 512a structure
+for Physical-based RNG.
+
+** New USB stack.
+Now, we use our own USB stack (taken from Gnuk).
+
+
+* Major changes in NeuG 0.01
+
+  Released 2011-11-14, by NIIBE Yutaka
+
+** Support more boards
+NeuG now supports FST-01, STM8S DISCOVERY, CQ-STARM and STBee, too.
+
+** Change RNG construct.
+Basic technology is basically same (CRC-16, TinyMT), but we add
+FNV32 hash as an output function, and give a seed to TinyMT from
+Physical-based RNG.
+
+** Add Test results.
+Under test-results directory, we put results of RNG test by rng-tools,
+NIST STS 2.1.1, and Dieharder 3.31.1.
+
+
+* Major changes in NeuG 0.00
+
+  Released 2011-07-14, by NIIBE Yutaka
+
+** This is initial release.
+
+Local Variables:
+mode: outline
+End:
diff --git a/README b/README
index c3615e3..9928c24 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
 NeuG - a random number generator implementation (for STM32F103)
 
-                                                          Version 0.02
-                                                            2012-08-30
+                                                          Version 0.03
+                                                            2012-09-27
                                                           Niibe Yutaka
                                      Free Software Initiative of Japan
 
@@ -21,12 +21,16 @@ My primary intention was to incorporate NeuG routines into Gnuk for
 random number generation, but the stand alone version could be useful
 too.
 
+Gnuk was named after my son who loved the pacifier when he was baby.
+NeuG was named after my daughter, but I don't say she is noisy.
+
 
 Release notes
 =============
 
-This is the third release of NeuG, which is still experimental.  You
-can enjoy NeuG device, but I'm not sure how it is good yet.  Note that
+This is the fourth release of NeuG, which is still experimental.
+Basic features (generating random numbers) are stable, but newly added
+things like reGNUal support should be considered unstable.  Note that
 you need the snapshot of ChibiOS/RT (from trunk).  This means that it
 is covered by GNU GPL.  No "linking exception" option is available for
 the snapshot.
@@ -41,10 +45,6 @@ A0: I believe it's good enough if we compare to other hardware RNGs.
     computer simulations, I think that it's good enough.  I evaluated
     it with rngtest of RNG-tools, NIST STS test suite and Dieharder.
     See the directory neug/test-results/.
-    For important cryptographic usage, such as generating keys or use
-    for ECC, I think that we need more evaluations under severe
-    condition (e.g., lower ALPHA (say, 0.001) in NIST STS test suite
-    and more number of streams (say, 10000)).
 A0-dash: For better entropy device with embedded test, you could get
          EntropyKey.  See http://www.entropykey.co.uk/
 A0-double-dash: STM32F2xx and STM32F4xx have built-in TRNG, it would
@@ -55,9 +55,12 @@ Q1: How fast is NeuG device?
 A1: It's something around 30 Ki-byte/second.
 
 Q2: Should we check condition of noise sources?
-A2: Yes, we should.  It's not implemented yet, and I don't have an
-    good idea how to implement such a feature with limited resource
-    of STM32F103.  Please let me know your idea.
+A2: Yes, we should.  Three continuous tests are implemented, following
+    (Draft of) NIST SP 800-90B.  Those are Repetition Count Test,
+    Adaptive Proportion Test (for 64 samples), and another Adaptive
+    Proportion Test (for 4096 samples).  When it detect an error (it
+    is really rare, but it could occur even for normal condition), the
+    generation of random bits restart again.
 
 
 Targets
@@ -157,6 +160,13 @@ Before using /dev/ttyACM0, you need to configure its TTY discipline.
 
 Then, you can use output of /dev/ttyACM0.
 
+When you want to get raw output (not conditioned), you can configure:
+
+  $ stty -F /dev/ttyACM0 parenb
+
+And you can get conditioned output by configuring:
+
+  $ stty -F /dev/ttyACM0 -parenb
 
 
 Structure of the NeuG
@@ -165,43 +175,59 @@ Structure of the NeuG
 Here is a figure of the circuit.
 
 
-             Entropy Pool (64-byte)
-            +----------------+
-            |                |
-            | 16-word        |       8  ||<-- [ Vref ]
-      +---- | registers      |   |<--/--||
-      |     |   in           | 32 |      ||<-- [ Temperature Sensor ]
-      |     | WELL512a       |<-/-|
-      |     |  structure     |   |<----/------ SysTick
-      |     +----------------+          1
-      |     Physical-based RNG
+           Physical-based RNG
+           
+            +--------------+              Noise sources 
+            |              |
+            | Conditioning |   1112 ||<-- LSB of result of [ IN10 ]
+            | Component    |<---/---||
+            |              |        ||<-- LSB of result of [ IN11 ]
+      +-----|  Hash_df     |
+      |     |    by        |
+      |     |  SHA-256     |
+      |     |              |
+      |     |              |   256
+      |     |              |<---/---+
+      |     +--------------+        |
+      |                             |
+      +-----------------------------+
       |
-      / 32
+      / 256
       |
       v
  Random Number Output
 
 
-STM32F103 has built-in Vref (voltage reference) and Temperature Sensor
-which are connected to A/D converter of 12-bit resolution.  NeuG uses
-LSBs of A/D converter's outputs as entropy sources.
+STM32F103 has two built-in A/D converters of 12-bit resolution.  NeuG
+uses LSBs of A/D converters' outputs as entropy sources.  It is
+considered noise of quantization error, plus noise from power supply,
+etc.
+
+We chose analog inputs of IN10 and IN11, which is not connected to
+external pin (for the version of 36-pin or 48-pin STM32F103).  The
+input is configured as digital output 50MHz to get maximum noise of
+environment.
 
-By four samplings of two channels, we can get 8-bit, as we can get two
-bits (LSB of Vref and LSB of Temperature Sensor) from one sampling.
-We put this 8-bit noise and SysTick to entropy pool.  Entropy pool
-consist of 16-word buffer, which has WELL 512a structure.
+By 556 samplings of two channels, we can get 1112-bit, as we can get
+two bits (LSB of IN10 and LSB of IN11) from one sampling.  We put this
+1112-bit and previous output of 256-bit to conditioning component.
 
-Since the noise source is not "white", signal is whiten by this WELL
-512a structure.  An experiment shows that raw noise source of LSBs has
-more than 6 bit/byte entropy.  So, we put 6-byte (36-bit) to get
-4-byte (32-bit) output.
+Conditioning component is implemented by Hash_df function by SHA-256.
+Since the noise source is not "white", signal is whiten by this
+Conditioning component.
 
-I don't know how stable the noise source is.  My experience with
-STM32F103 and NeuG shows that it's stable at least for a year.
+Experiments show that raw noise source of LSBs has more than 6.0
+bit/byte entropy when it is no computation but just to take samples.
+The entropy varies among different boards.  It seems that a board with
+good power supply and capacitor has smaller entropy (6.2 or so), and
+the one with poor power supply and capacitor has bigger entropy (7.3
+or so).  That is considered noise of quantization error.
 
-For WELL Random Number Generator, please visit:
+When there is some activities of MCU, it's more than 7.0 bit/byte
+entropy for a board even with good power supply and capacitor.
 
-   http://www.iro.umontreal.ca/~panneton/WELLRNG.html
+My experience with STM32F103 and NeuG shows that noise source is
+stable at least for a year.
 
 
 Test results
index 5bad894..88f67c2 100644 (file)
@@ -666,7 +666,7 @@ static msg_t led_blinker (void *arg)
   return 0;
 }
 \f
-#define RANDOM_BYTES_LENGTH 60
+#define RANDOM_BYTES_LENGTH 32
 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
 
 /*
@@ -724,6 +724,9 @@ main (int argc, char **argv)
          chEvtWaitOneTimeout (ALL_EVENTS, MS2ST (5000));
        }
 
+      if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+       break;
+
       /* The connection opened.  */
       count = 0;
       /*
@@ -742,7 +745,7 @@ main (int argc, char **argv)
 
          neug_wait_full ();
 
-         if ((count & 0x00ff) == 0)
+         if ((count & 0x03ff) == 0)
            chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
 
          usb_lld_txcpy (random_word, ENDP1, 0, RANDOM_BYTES_LENGTH);
@@ -767,14 +770,14 @@ main (int argc, char **argv)
        }
     }
 
+  chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
+  chThdWait (led_thread);
+
   /*
    * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED.
    */
   neug_fini ();
 
-  chEvtSignalFlags (led_thread, LED_ONESHOT_SHORT);
-  chThdWait (led_thread);
-
   fsij_device_state = FSIJ_DEVICE_EXITED;
 
   while (fsij_device_state == FSIJ_DEVICE_EXITED)
index fc56e6d..0dad9fd 100644 (file)
@@ -5,7 +5,7 @@
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of NeuG, a Random Number Generator
- * implementation (for STM32F103).
+ * implementation based on quantization error of ADC (for STM32F103).
  *
  * NeuG is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
@@ -35,11 +35,11 @@ static Thread *rng_thread;
 #define ADC_GRP1_NUM_CHANNELS   1
  
 /* Depth of the conversion buffer, channels are sampled one time each.*/
-#define ADC_GRP1_BUF_DEPTH      16
+#define ADC_GRP1_BUF_DEPTH      256
 
 static void adc2_start (void)
 {
-  rccEnableAPB2(RCC_APB2ENR_ADC2EN, FALSE);
+  rccEnableAPB2 (RCC_APB2ENR_ADC2EN, FALSE);
   ADC2->CR1 = 0;
   ADC2->CR2 = ADC_CR2_ADON;
   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
@@ -61,6 +61,11 @@ static void adc2_start (void)
   ADC2->CR2 |= ADC_CR2_EXTTRIG | ADC_CR2_SWSTART;
 }
 
+static void adc2_stop (void)
+{
+  rccDisableAPB2 (RCC_APB2ENR_ADC2EN, FALSE);
+}
+
 /*
  * ADC samples buffer.
  */
@@ -102,7 +107,7 @@ static void adccb (ADCDriver *adcp, adcsample_t *buffer, size_t n)
   (void) buffer; (void) n;
 
   chSysLockFromIsr();
-  if (adcp->state == ADC_COMPLETE)
+  if (adcp->state == ADC_COMPLETE && rng_thread)
     chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE);
   chSysUnlockFromIsr();
 }
@@ -111,7 +116,6 @@ static void adccb_err (ADCDriver *adcp, adcerror_t err)
 {
   (void)adcp;  (void)err;
 }
-
 \f
 #include "sha256.h"
 
@@ -141,51 +145,158 @@ static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
  * For us, cryptographic primitive is SHA-256 and its blocksize is 512-bit
  * (64-byte), N >= 128.
  *
- * We chose N=131, since we love prime number, and we have "additional bits"
+ * We chose N=139, since we love prime number, and we have "additional bits"
  * of 32-byte for last block (feedback from previous output of SHA-256).
  *
- * This corresponds to min-entropy >= 3.91.
+ * This corresponds to min-entropy >= 3.68.
  *
  */
-#define NUM_NOISE_INPUTS 131
+#define NUM_NOISE_INPUTS 139
 
-static const uint8_t hash_df_initial_string[5] = {
-  1,          /* counter = 1 */
-  0, 0, 1, 0  /* no_of_bits_returned (big endian) */
-};
+#define EP_ROUND_0 0 /* initial-five-byte and 59-sample-input */
+#define EP_ROUND_1 1 /* 64-sample-input */
+#define EP_ROUND_2 2 /* 8-sample-input */
+#define EP_ROUND_RAW 3 /* 8-sample-input */
+
+#define EP_ROUND_0_INPUTS 59
+#define EP_ROUND_1_INPUTS 64
+#define EP_ROUND_2_INPUTS 16
+#define EP_ROUND_RAW_INPUTS 32
+
+static uint8_t ep_round;
+
+/*
+ * Hash_df initial string:
+ *
+ *  1,          : counter = 1
+ *  0, 0, 1, 0  : no_of_bits_returned (in big endian)
+ */
+static void ep_fill_initial_string (void)
+{
+  memset (samp, 0, 5 * 8 * sizeof (adcsample_t));
+  samp[0] = 1;
+  samp[3*8] = 1;
+}
 
-static void ep_init (void)
+static void ep_init (int raw)
 {
-  sha256_start (&sha256_ctx_data);
-  sha256_update (&sha256_ctx_data, hash_df_initial_string, 5);
+  chEvtClearFlags (ADC_DATA_AVAILABLE);
+  if (raw)
+    {
+      ep_round = EP_ROUND_RAW;
+      adcStartConversion (&ADCD1, &adcgrpcfg, samp, EP_ROUND_RAW_INPUTS*8/2);
+    }
+  else
+    {
+      ep_round = EP_ROUND_0;
+      ep_fill_initial_string ();
+      /*
+       * We get two samples for a single transaction of DMA.
+       * We take LSBs of each samples.
+       * Thus, we need tansactions of: required_number_of_input_in_byte*8/2 
+       */
+      adcStartConversion (&ADCD1, &adcgrpcfg,
+                         &samp[5*8], EP_ROUND_0_INPUTS*8/2);
+    }
 }
 
-static void ep_add (uint8_t entropy_bits)
+static uint8_t ep_get_byte_from_samples (int i)
 {
-  sha256_update (&sha256_ctx_data, &entropy_bits, 1);
+  return (  ((samp[i*8+0] & 1) << 0) | ((samp[i*8+1] & 1) << 1)
+         | ((samp[i*8+2] & 1) << 2) | ((samp[i*8+3] & 1) << 3)
+         | ((samp[i*8+4] & 1) << 4) | ((samp[i*8+5] & 1) << 5)
+         | ((samp[i*8+6] & 1) << 6) | ((samp[i*8+7] & 1) << 7));
 }
 
-#define PROBABILITY_50_BY_TICK() ((SysTick->VAL & 0x02) != 0)
+static void noise_source_continuous_test (uint8_t noise);
+
+static void ep_fill_wbuf (int i, int flip)
+{
+  uint8_t b0, b1, b2, b3;
+
+  b0 = ep_get_byte_from_samples (i*4 + 0);
+  b1 = ep_get_byte_from_samples (i*4 + 1);
+  b2 = ep_get_byte_from_samples (i*4 + 2);
+  b3 = ep_get_byte_from_samples (i*4 + 3);
+  noise_source_continuous_test (b0);
+  noise_source_continuous_test (b1);
+  noise_source_continuous_test (b2);
+  noise_source_continuous_test (b3);
+
+  if (flip)
+    sha256_ctx_data.wbuf[i] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+  else
+    sha256_ctx_data.wbuf[i] = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+}
 
-static const uint32_t *ep_output (void)
+/* Here assumes little endian architecture.  */
+static int ep_process (int raw)
 {
-#if ((SHA256_BLOCK_SIZE - 9) - ((5 + NUM_NOISE_INPUTS) % SHA256_BLOCK_SIZE)) \
-    > SHA256_DIGEST_SIZE
-  int n = SHA256_DIGEST_SIZE;
-#else
-  int n = (SHA256_BLOCK_SIZE - 9)
-    - ((5 + NUM_NOISE_INPUTS) % SHA256_BLOCK_SIZE);
-#endif
-
-  if (PROBABILITY_50_BY_TICK ())
-    n = n - 3;
-
-  sha256_update (&sha256_ctx_data, (uint8_t *)sha256_output, n);
-  sha256_finish (&sha256_ctx_data, (uint8_t *)sha256_output);
-  ep_init ();
-  return sha256_output;
+  int i, n, flip;
+
+  if (ep_round == EP_ROUND_0 || ep_round == EP_ROUND_1)
+    {
+      n = 64 / 4;
+      flip = 1;
+    }
+  else if (ep_round == EP_ROUND_2)
+    {
+      n = EP_ROUND_2_INPUTS / 4;
+      flip = 0;
+    }
+  else /* ep_round == EP_ROUND_RAW */
+    {
+      n = EP_ROUND_RAW_INPUTS / 4;
+      flip = 0;
+    }
+
+  for (i = 0; i < n; i++)
+    ep_fill_wbuf (i, flip);
+
+  if (raw)
+    {
+      ep_init (1);
+      return n;
+    }
+  else
+    {
+      if (ep_round == EP_ROUND_0)
+       {
+         adcStartConversion (&ADCD1, &adcgrpcfg, samp, EP_ROUND_1_INPUTS*8/2);
+         sha256_start (&sha256_ctx_data);
+         sha256_process (&sha256_ctx_data);
+         ep_round++;
+         return 0;
+       }
+      else if (ep_round == EP_ROUND_1)
+       {
+         adcStartConversion (&ADCD1, &adcgrpcfg, samp, EP_ROUND_2_INPUTS*8/2);
+         sha256_process (&sha256_ctx_data);
+         ep_round++;
+         return 0;
+       }
+      else
+       {
+         n = SHA256_DIGEST_SIZE;
+         ep_init (0);
+         memcpy (((uint8_t *)sha256_ctx_data.wbuf)+EP_ROUND_2_INPUTS,
+                 sha256_output, n);
+         sha256_ctx_data.total[0] = 5 + NUM_NOISE_INPUTS + n;
+         sha256_finish (&sha256_ctx_data, (uint8_t *)sha256_output);
+         return SHA256_DIGEST_SIZE / sizeof (uint32_t);
+       }
+    }
 }
 
+
+static const uint32_t *ep_output (int raw)
+{
+  if (raw)
+    return sha256_ctx_data.wbuf;
+  else
+    return sha256_output;
+}
+\f
 #define REPETITION_COUNT           1
 #define ADAPTIVE_PROPORTION_64     2
 #define ADAPTIVE_PROPORTION_4096   4
@@ -287,7 +398,7 @@ static void noise_source_continuous_test (uint8_t noise)
   adaptive_proportion_64_test (noise);
   adaptive_proportion_4096_test (noise);
 }
-
+\f
 /*
  * Ring buffer, filled by generator, consumed by neug_get routine.
  */
@@ -348,95 +459,25 @@ static uint8_t neug_raw;
  */
 static int rng_gen (struct rng_rb *rb)
 {
-  uint8_t round = 0;
-  uint32_t v = 0;
+  int n;
+  int raw = neug_raw;
 
   while (1)
     {
-      uint8_t b0, b1, b2, b3;
-
-      chEvtWaitOne (ADC_DATA_AVAILABLE);
-
-      /* Got an ADC sampling data */
-      b0 = (((samp[0] & 0x01) << 0) | ((samp[1] & 0x01) << 1)
-           | ((samp[2] & 0x01) << 2) | ((samp[3] & 0x01) << 3)
-           | ((samp[4] & 0x01) << 4) | ((samp[5] & 0x01) << 5)
-           | ((samp[6] & 0x01) << 6) | ((samp[7] & 0x01) << 7));
-
-      b1 = (((samp[8] & 0x01) << 0) | ((samp[9] & 0x01) << 1)
-          | ((samp[10] & 0x01) << 2) | ((samp[11] & 0x01) << 3)
-          | ((samp[12] & 0x01) << 4) | ((samp[13] & 0x01) << 5)
-          | ((samp[14] & 0x01) << 6) | ((samp[15] & 0x01) << 7));
-
-      b2 = (((samp[16] & 0x01) << 0) | ((samp[17] & 0x01) << 1)
-           | ((samp[18] & 0x01) << 2) | ((samp[19] & 0x01) << 3)
-           | ((samp[20] & 0x01) << 4) | ((samp[21] & 0x01) << 5)
-           | ((samp[22] & 0x01) << 6) | ((samp[23] & 0x01) << 7));
-
-      b3 = (((samp[24] & 0x01) << 0) | ((samp[25] & 0x01) << 1)
-          | ((samp[26] & 0x01) << 2) | ((samp[27] & 0x01) << 3)
-          | ((samp[28] & 0x01) << 4) | ((samp[29] & 0x01) << 5)
-          | ((samp[30] & 0x01) << 6) | ((samp[31] & 0x01) << 7));
-
-      adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH);
+      chEvtWaitOne (ADC_DATA_AVAILABLE); /* Got a series of ADC sampling.  */
 
-      noise_source_continuous_test (b0);
-      noise_source_continuous_test (b1);
-      noise_source_continuous_test (b2);
-      noise_source_continuous_test (b3);
-
-      if (neug_raw)
+      if ((n = ep_process (raw)))
        {
-         v |= (b0 << (round * 8));
-         round++;
-         v |= (b1 << (round * 8));
-         round++;
-         v |= (b2 << (round * 8));
-         round++;
-         v |= (b3 << (round * 8));
-         round++;
-
-         if (round >= 4)
+         int i;
+         const uint32_t *vp;
+
+         vp = ep_output (raw);
+         for (i = 0; i < n; i++)
            {
-             rb_add (rb, v);
+             rb_add (rb, *vp);
+             vp++;
              if (rb->full)
                return 0;
-             v = 0;
-             round = 0;
-           }
-       }
-      else
-       {
-         /*
-          * Put a random byte to entropy pool.
-          */
-         ep_add (b0);
-         round++;
-         ep_add (b1);
-         round++;
-         ep_add (b2);
-         round++;
-         ep_add (b3);
-         round++;
-         if (round >= NUM_NOISE_INPUTS)
-           {
-             /*
-              * We have enough entropy in the pool.
-              * Thus, we pull the random bits from the pool.
-              */
-             int i;
-             const uint32_t *vp = ep_output ();
-
-             /* We get the random bits, add it to the ring buffer.  */
-             for (i = 0; i < SHA256_DIGEST_SIZE / 4; i++)
-               {
-                 rb_add (rb, *vp);
-                 vp++;
-                 if (rb->full)
-                   return 0;
-               }
-
-             round = 0;
            }
        }
     }
@@ -460,7 +501,7 @@ static msg_t rng (void *arg)
     | STM32_DMA_CR_TCIE       | STM32_DMA_CR_TEIE       | STM32_DMA_CR_EN;
   /* Enable ADC2 */
   adc2_start ();
-  adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH);
+  ep_init (0);
 
   while (!chThdShouldTerminate ())
     {
@@ -472,8 +513,9 @@ static msg_t rng (void *arg)
          rng_gen (rb);
          if (neug_err_state != 0)
            {
-             while (!rb->empty)
-               (void)rb_del (rb);
+             if (!neug_raw)
+               while (!rb->empty)
+                 (void)rb_del (rb);
              noise_source_error_reset ();
            }
          else
@@ -483,11 +525,14 @@ static msg_t rng (void *arg)
       chMtxUnlock ();
     }
 
+  adc2_stop ();
+  adcStop (&ADCD1);
+
   return 0;
 }
 
 static struct rng_rb the_ring_buffer;
-static WORKING_AREA(wa_rng, 256);
+static WORKING_AREA(wa_rng, 960);
 
 /**
  * @brief Initialize NeuG.
@@ -498,7 +543,6 @@ neug_init (uint32_t *buf, uint8_t size)
   struct rng_rb *rb = &the_ring_buffer;
 
   neug_raw = 0;
-  ep_init ();
   rb_init (rb, buf, size);
   chThdCreateStatic (wa_rng, sizeof (wa_rng), NORMALPRIO, rng, rb);
 }
@@ -583,6 +627,8 @@ void
 neug_select (uint8_t raw)
 {
   neug_wait_full ();
+  if (neug_raw != raw)
+    ep_init (raw);
   neug_raw = raw;
   neug_flush ();
 }
index 098506c..35e6723 100755 (executable)
@@ -156,7 +156,7 @@ class neug(object):
         if interface.interfaceSubClass != COM_SUBCLASS:
             raise ValueError, "Wrong interface sub class"
         self.__devhandle = device.open()
-        self.__devhandle.detachKernelDriver(interface)
+        self.__devhandle.detachKernelDriver(interface)
         # self.__devhandle.claimInterface(interface)
         # self.__devhandle.setAltInterface(interface)