Remove intermediate buffer
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 13 Aug 2013 06:46:39 +0000 (15:46 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 13 Aug 2013 06:46:39 +0000 (15:46 +0900)
ChangeLog
src/adc.h
src/adc_stm32f103.c
src/neug.c

index ca030da..c9fd9a3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2013-08-13  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/neug.c (adc_buf): Remove.
+       (ep_fill_initial_string): Call noise_source_continuous_test.
+       (ep_init): Follow the change of adc_start_conversion.
+       (ep_fill_wbuf_v): New name and new argument V, remove FLIP.
+       (ep_process): Access CRC unit from here.  Correct calling
+       noise_source_continuous_test for the last byte of output.
+       (rng): Handle error of ADC.
+
+       * src/adc_stm32f103.c (adc_mode, adc_ptr, adc_size): Remove.
+       (adc_buf): Make it public.
+       (adc_start_conversion): Change arguments.
+       (adc_lld_serve_rx_interrupt, adc_wait): Remove.
+       (adc_wait_completion): New with error code.
+
 2013-08-12  Niibe Yutaka  <gniibe@fsij.org>
 
        * src/sys.c (reset): Remove unneeded & for FT0, FT1, and FT2.
index 177ccca..1efefce 100644 (file)
--- a/src/adc.h
+++ b/src/adc.h
@@ -8,6 +8,9 @@ void adc_start (void);
 void adc_stop (void);
 
 #define ADC_SAMPLE_MODE 0
-#define ADC_CRC32_MODE       1
-void adc_start_conversion (int mode, uint32_t *p, int size);
-void adc_wait (chopstx_intr_t *intr);
+#define ADC_CRC32_MODE  1
+
+extern uint32_t adc_buf[64];
+
+void adc_start_conversion (int mode, int offset, int size);
+int adc_wait_completion (chopstx_intr_t *intr);
index db5afe3..7c01e2a 100644 (file)
@@ -172,10 +172,7 @@ void adc_start (void)
 #endif
 }
 
-static int adc_mode;
-static uint32_t *adc_ptr;
-static int adc_size;
-static uint32_t adc_buf[64];
+uint32_t adc_buf[64];
 
 static void adc_start_conversion_internal (void)
 {
@@ -195,28 +192,21 @@ static void adc_start_conversion_internal (void)
 #endif
 }
 
-void adc_start_conversion (int mode, uint32_t *p, int size)
+void adc_start_conversion (int mode, int offset, int size)
 {
-  adc_mode = mode;
-  adc_ptr = p;
-  adc_size = size;
-
+  DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
+  DMA1_Channel1->CMAR = (uint32_t)&adc_buf[offset]; /* SetMemory0 */
  if (mode == ADC_SAMPLE_MODE)
     {
-      DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
-      DMA1_Channel1->CMAR  = (uint32_t)p; /* SetMemory0 */
-      DMA1_Channel1->CNDTR  = (uint32_t)size / 4; /* counter */
-      DMA1_Channel1->CCR  = NEUG_DMA_MODE_SAMPLE; /*mode*/
-      DMA1_Channel1->CCR |= DMA_CCR1_EN;                   /* Enable */
+      DMA1_Channel1->CNDTR = (uint32_t)size / 4; /* counter */
+      DMA1_Channel1->CCR = NEUG_DMA_MODE_SAMPLE; /*mode*/
     }
   else
     {
-      DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
-      DMA1_Channel1->CMAR  = (uint32_t)adc_buf; /* SetMemory0 */
-      DMA1_Channel1->CNDTR  = size; /* counter */
-      DMA1_Channel1->CCR  = NEUG_DMA_MODE_CRC32; /*mode*/
-      DMA1_Channel1->CCR |= DMA_CCR1_EN;                   /* Enable */
+      DMA1_Channel1->CNDTR = size; /* counter */
+      DMA1_Channel1->CCR = NEUG_DMA_MODE_CRC32; /*mode*/
     }
+ DMA1_Channel1->CCR |= DMA_CCR1_EN;                /* Enable */
 
  adc_start_conversion_internal ();
 }
@@ -248,43 +238,31 @@ void adc_stop (void)
 }
 
 
-static void adc_lld_serve_rx_interrupt (uint32_t flags)
+/*
+ * Return 0 on success.
+ * Return 1 on error.
+ */
+int adc_wait_completion (chopstx_intr_t *intr)
 {
-  if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
-    {
-      /* Should never happened.  If any, it's coding error. */
-      /* Access an unmapped address space or alignment violation.  */
-      adc_stop_conversion ();
-    }
-  else
+  uint32_t flags;
+
+  while (1)
     {
-      if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
+      chopstx_intr_wait (intr);
+      flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause.  */
+      DMA1->IFCR = STM32_DMA_ISR_MASK; /* Clear interrupt of channel 1.  */
+
+      if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
        {
+         /* Should never happened.  If any, it's coding error. */
+         /* Access an unmapped address space or alignment violation.  */
          adc_stop_conversion ();
-
-         if (adc_mode != ADC_SAMPLE_MODE)
-           {
-             int i;
-
-             for (i = 0; i < adc_size;)
-               {
-                 CRC->DR = adc_buf[i++];
-                 CRC->DR = adc_buf[i++];
-                 CRC->DR = adc_buf[i++];
-                 CRC->DR = adc_buf[i++];
-                 *adc_ptr++ = CRC->DR;
-               }
-           }
+         return 1;
+       }
+      else if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
+       {
+         adc_stop_conversion ();
+         return 0;
        }
     }
 }
-
-void adc_wait (chopstx_intr_t *intr)
-{
-  uint32_t flags;
-
-  chopstx_intr_wait (intr);
-  flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause.  */
-  DMA1->IFCR = STM32_DMA_ISR_MASK; /* Clear interrupt of channel 1.  */
-  adc_lld_serve_rx_interrupt (flags);
-}
index 7731c60..9bdd153 100644 (file)
@@ -41,8 +41,6 @@ static chopstx_cond_t  mode_cond;
 #define INTR_REQ_DMA1_Channel1 11
 
 
-static uint32_t adc_buf[SHA256_BLOCK_SIZE/sizeof (uint32_t)];
-
 static sha256_context sha256_ctx_data;
 static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
 
@@ -87,16 +85,35 @@ static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
 
 static uint8_t ep_round;
 
+static void noise_source_continuous_test (uint8_t noise);
+
 /*
  * Hash_df initial string:
  *
- *  1,          : counter = 1
- *  0, 0, 1, 0  : no_of_bits_returned (in big endian)
+ *  Initial five bytes are:
+ *    1,          : counter = 1
+ *    0, 0, 1, 0  : no_of_bits_returned (in big endian)
+ *
+ *  Then, three-byte from noise source follows.
+ *
+ *  One-byte was used in the previous turn, and we have three bytes in
+ *  CRC->DR.
  */
 static void ep_fill_initial_string (void)
 {
-  adc_buf[0] = 0x01000001; /* Regardless of endian */
-  adc_buf[1] = (CRC->DR & 0xffffff00);
+  uint32_t v = CRC->DR;
+  uint8_t b1, b2, b3;
+
+  b3 = v >> 24;
+  b2 = v >> 16;
+  b1 = v >> 8;
+
+  noise_source_continuous_test (b1);
+  noise_source_continuous_test (b2);
+  noise_source_continuous_test (b3);
+
+  adc_buf[0] = 0x01000001;
+  adc_buf[1] = (v & 0xffffff00);
 }
 
 static void ep_init (int mode)
@@ -104,28 +121,24 @@ static void ep_init (int mode)
   if (mode == NEUG_MODE_RAW)
     {
       ep_round = EP_ROUND_RAW;
-      adc_start_conversion (ADC_CRC32_MODE, adc_buf, EP_ROUND_RAW_INPUTS);
+      adc_start_conversion (ADC_CRC32_MODE, 0, EP_ROUND_RAW_INPUTS);
     }
   else if (mode == NEUG_MODE_RAW_DATA)
     {
       ep_round = EP_ROUND_RAW_DATA;
-      adc_start_conversion (ADC_SAMPLE_MODE, adc_buf, EP_ROUND_RAW_DATA_INPUTS);
+      adc_start_conversion (ADC_SAMPLE_MODE, 0, EP_ROUND_RAW_DATA_INPUTS);
     }
   else
     {
       ep_round = EP_ROUND_0;
       ep_fill_initial_string ();
-      adc_start_conversion (ADC_CRC32_MODE,
-                           &adc_buf[2], EP_ROUND_0_INPUTS);
+      adc_start_conversion (ADC_CRC32_MODE, 2, EP_ROUND_0_INPUTS);
     }
 }
 
-static void noise_source_continuous_test (uint8_t noise);
 
-static void ep_fill_wbuf (int i, int flip, int test)
+static void ep_fill_wbuf_v (int i, int test, uint32_t v)
 {
-  uint32_t v = adc_buf[i];
-
   if (test)
     {
       uint8_t b0, b1, b2, b3;
@@ -141,9 +154,6 @@ static void ep_fill_wbuf (int i, int flip, int test)
       noise_source_continuous_test (b3);
     }
 
-  if (flip)
-    v = __builtin_bswap32 (v);
-
   sha256_ctx_data.wbuf[i] = v;
 }
 
@@ -151,11 +161,19 @@ static void ep_fill_wbuf (int i, int flip, int test)
 static int ep_process (int mode)
 {
   int i, n;
+  uint32_t v;
 
   if (ep_round == EP_ROUND_RAW)
     {
       for (i = 0; i < EP_ROUND_RAW_INPUTS / 4; i++)
-       ep_fill_wbuf (i, 0, 1);
+       {
+         CRC->DR = adc_buf[i*4];
+         CRC->DR = adc_buf[i*4 + 1];
+         CRC->DR = adc_buf[i*4 + 2];
+         CRC->DR = adc_buf[i*4 + 3];
+         v = CRC->DR;
+         ep_fill_wbuf_v (i, 1, v);
+       }
 
       ep_init (mode);
       return EP_ROUND_RAW_INPUTS / 4;
@@ -163,7 +181,10 @@ static int ep_process (int mode)
   else if (ep_round == EP_ROUND_RAW_DATA)
     {
       for (i = 0; i < EP_ROUND_RAW_DATA_INPUTS / 4; i++)
-       ep_fill_wbuf (i, 0, 0);
+       {
+         v = adc_buf[i];
+         ep_fill_wbuf_v (i, 0, v);
+       }
 
       ep_init (mode);
       return EP_ROUND_RAW_DATA_INPUTS / 4;
@@ -171,35 +192,65 @@ static int ep_process (int mode)
 
   if (ep_round == EP_ROUND_0)
     {
-      for (i = 0; i < 64 / 4; i++)
-       ep_fill_wbuf (i, 1, 1);
-
-      adc_start_conversion (ADC_CRC32_MODE, adc_buf, EP_ROUND_1_INPUTS);
       sha256_start (&sha256_ctx_data);
+      sha256_ctx_data.wbuf[0] = adc_buf[0];
+      sha256_ctx_data.wbuf[1] = adc_buf[1];
+      for (i = 0; i < EP_ROUND_0_INPUTS / 4; i++)
+       {
+         CRC->DR = adc_buf[i*4 + 2];
+         CRC->DR = adc_buf[i*4 + 3];
+         CRC->DR = adc_buf[i*4 + 4];
+         CRC->DR = adc_buf[i*4 + 5];
+         v = CRC->DR;
+         ep_fill_wbuf_v (i+2, 1, v);
+       }
+
+      adc_start_conversion (ADC_CRC32_MODE, 0, EP_ROUND_1_INPUTS);
       sha256_process (&sha256_ctx_data);
       ep_round++;
       return 0;
     }
   else if (ep_round == EP_ROUND_1)
     {
-      for (i = 0; i < 64 / 4; i++)
-       ep_fill_wbuf (i, 1, 1);
+      for (i = 0; i < EP_ROUND_1_INPUTS / 4; i++)
+       {
+         CRC->DR = adc_buf[i*4];
+         CRC->DR = adc_buf[i*4 + 1];
+         CRC->DR = adc_buf[i*4 + 2];
+         CRC->DR = adc_buf[i*4 + 3];
+         v = CRC->DR;
+         ep_fill_wbuf_v (i, 1, v);
+       }
 
-      adc_start_conversion (ADC_CRC32_MODE, adc_buf, EP_ROUND_2_INPUTS);
+      adc_start_conversion (ADC_CRC32_MODE, 0, EP_ROUND_2_INPUTS + 3);
       sha256_process (&sha256_ctx_data);
       ep_round++;
       return 0;
     }
   else
     {
-      for (i = 0; i < (EP_ROUND_2_INPUTS + 3) / 4; i++)
-       ep_fill_wbuf (i, 0, 1);
+      for (i = 0; i < EP_ROUND_2_INPUTS / 4; i++)
+       {
+         CRC->DR = adc_buf[i*4];
+         CRC->DR = adc_buf[i*4 + 1];
+         CRC->DR = adc_buf[i*4 + 2];
+         CRC->DR = adc_buf[i*4 + 3];
+         v = CRC->DR;
+         ep_fill_wbuf_v (i, 1, v);
+       }
 
+      CRC->DR = adc_buf[i*4];
+      CRC->DR = adc_buf[i*4 + 1];
+      CRC->DR = adc_buf[i*4 + 2];
+      CRC->DR = adc_buf[i*4 + 3];
+      v = CRC->DR & 0xff;
+      noise_source_continuous_test (v);
+      sha256_ctx_data.wbuf[i] = v;
+      ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
+                                         CRC->DR is used here.  */
       n = SHA256_DIGEST_SIZE / 2;
-      ep_init (NEUG_MODE_CONDITIONED); /* The three-byte is used here.  */
-      memcpy (((uint8_t *)sha256_ctx_data.wbuf)
-             + ((NUM_NOISE_INPUTS+5)%SHA256_BLOCK_SIZE),
-             sha256_output, n); /* Don't use the last three-byte.  */
+      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);
@@ -431,12 +482,13 @@ rng (void *arg)
   ep_init (mode);
   while (!rng_should_terminate)
     {
+      int err;
       int n;
 
-      adc_wait (&adc_intr);
+      err = adc_wait_completion (&adc_intr);
 
       chopstx_mutex_lock (&mode_mtx);
-      if (mode != neug_mode)
+      if (err || mode != neug_mode)
        {
          mode = neug_mode;
 
@@ -445,8 +497,11 @@ rng (void *arg)
          /* Discarding data available, re-initiate from the start.  */
          ep_init (mode);
          chopstx_cond_signal (&mode_cond);
+         chopstx_mutex_unlock (&mode_mtx);
+         continue;
        }
-      chopstx_mutex_unlock (&mode_mtx);
+      else
+       chopstx_mutex_unlock (&mode_mtx);
 
       if ((n = ep_process (mode)))
        {