summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Marble <tmarble@info9.net>2015-03-15 20:08:42 -0500
committerTom Marble <tmarble@info9.net>2015-03-15 20:08:42 -0500
commit70e6f60dd471fd64a460b9b42ffd25e7975f2c51 (patch)
tree475cf808f8058223f4a83d743da212f2c4c04010
parent9ae9bea5b59c8f0e012c6b58f95f7a6641ef9bdc (diff)
Call POST / ao_trng_reset() lazily
renamed ao_reset() to ao_trng_reset() and ao_status() to ao_trng_status() moved the failure handling to ao_trng_failure() CAUTION: this version 1.6.3 will fail to load the command processor!
-rw-r--r--src/drivers/ao_trng.c171
-rw-r--r--src/drivers/ao_trng.h3
-rw-r--r--src/usbtrng-v2.0/ao_usbtrng.c2
3 files changed, 72 insertions, 104 deletions
diff --git a/src/drivers/ao_trng.c b/src/drivers/ao_trng.c
index b8e25e28..d3c2823a 100644
--- a/src/drivers/ao_trng.c
+++ b/src/drivers/ao_trng.c
@@ -20,23 +20,6 @@
#include <ao_crc.h>
#include <ao_trng.h>
-
-static struct ao_task ao_blink_red_task;
-static uint8_t ao_failed = 0;
-
-static void
-ao_blink_red(void)
-{
- for (;;) {
- while (!ao_failed)
- ao_sleep(&ao_failed);
- while (ao_failed) {
- ao_led_toggle(AO_LED_RED);
- ao_delay(AO_MS_TO_TICKS(500));
- }
- }
-}
-
static struct ao_task ao_blink_green_task;
static uint8_t ao_blinking_green = 0;
@@ -63,86 +46,31 @@ ao_blink_green_toggle(void)
ao_wakeup(&ao_blinking_green);
}
-#define ADC_WORDS (AO_USB_IN_SIZE / sizeof (uint16_t))
-static uint16_t prev16 = 0;
-static uint16_t adc_values[ADC_WORDS];
-static uint8_t adc_i = ADC_WORDS;
-
-static uint16_t
-fetch16(uint8_t initialize)
-{
- uint32_t *rnd;
- uint8_t i;
-
- if (ao_failed)
- return 0;
- if (initialize)
- adc_i = ADC_WORDS;
- if (adc_i == ADC_WORDS) {
- rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */
- adc_i = 0;
- for (i = 0; i < ADC_WORDS; i++) {
- adc_values[i] = ao_crc_in_32_out_16(*rnd++);
- }
- }
- if (initialize)
- prev16 = adc_values[adc_i++];
- if (adc_values[adc_i] == prev16) {
- /* FAILED: how do we prevent spewing bad data? */
- printf("FAILED value %d repeated\n", prev16);
- ao_failed = 1;
- ao_wakeup(&ao_failed);
- return 0;
- }
- prev16 = adc_values[adc_i];
- adc_i++;
- return prev16;
-}
-
-static void
-ao_simulate_failure(void)
-{
- if (adc_i == ADC_WORDS)
- fetch16(0);
- prev16 = adc_values[adc_i];
-}
+static struct ao_task ao_blink_red_task;
+static int8_t ao_failed = -1; /* -1 need POST, 0 NOMINAL, 1 FAILED */
-/* NOTE: the reset function also functions as the Power On Self Test */
+/* On handling failure, keithp said:
+ We could disconnect from USB easily enough, or disconnect and come back
+ with a different setup that the kernel driver could report as an
+ error. Lots of options.
+*/
void
-ao_reset(void)
+ao_trng_failure(void)
{
- uint32_t count;
-
- printf("Power On Self Test\n"); /* DEBUGGING */
- ao_failed = 0;
- ao_led_off(AO_LED_RED);
+ ao_failed = 1;
ao_wakeup(&ao_failed);
- fetch16(1);
- /* get the first 1k bits and ensure there are no duplicates */
- count = 1024 / sizeof (uint16_t);
- while (count-- && !ao_failed) {
- fetch16(0);
- }
- if (ao_failed) { /* show failure */
- printf("FAILED self test\n");
- } else { /* show success */
- printf("PASS - operation NOMINAL\n");
- /* this blocks! */
- ao_led_on(AO_LED_GREEN);
- ao_delay(AO_MS_TO_TICKS(1000));
- ao_led_off(AO_LED_GREEN);
- }
}
static void
-ao_trng_fetch(void)
+ao_trng_fetch(uint32_t kbytes)
{
static uint16_t *buffer[2];
- uint32_t kbytes = 1;
uint32_t count;
int usb_buf_id;
uint16_t i;
uint16_t *buf;
+ uint32_t *rnd;
+ uint32_t prev, cur;
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
@@ -151,11 +79,6 @@ ao_trng_fetch(void)
return;
}
- ao_cmd_decimal();
- if (ao_cmd_status == ao_cmd_success)
- kbytes = ao_cmd_lex_u32;
- else
- ao_cmd_status = ao_cmd_success;
usb_buf_id = 0;
count = kbytes * (1024/AO_USB_IN_SIZE);
@@ -163,9 +86,17 @@ ao_trng_fetch(void)
ao_led_on(AO_LED_TRNG_READ);
while (count--) {
+ /* one 16-bit value per output byte */
+ rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE + 2);
buf = buffer[usb_buf_id];
- for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++)
- *buf++ = fetch16(0);
+ prev = *rnd++;
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ cur = *rnd++;
+ if (cur == prev)
+ ao_trng_failure();
+ *buf++ = ao_crc_in_32_out_16(cur);
+ prev = cur;
+ }
ao_adc_ack(AO_USB_IN_SIZE);
ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
@@ -177,13 +108,56 @@ ao_trng_fetch(void)
}
static void
-ao_trng_word(void)
+ao_trng_fetch_cmd(void)
{
- printf("%d\n", fetch16(0));
+ uint32_t kbytes = 1;
+
+ ao_cmd_decimal();
+ if (ao_cmd_status == ao_cmd_success)
+ kbytes = ao_cmd_lex_u32;
+ else
+ ao_cmd_status = ao_cmd_success;
+ ao_trng_fetch(kbytes);
+}
+
+/* NOTE: the reset function also functions as the Power On Self Test */
+void
+ao_trng_reset(void)
+{
+ printf("Power On Self Test\n"); /* DEBUGGING */
+ ao_failed = 0;
+ ao_led_off(AO_LED_RED);
+ ao_wakeup(&ao_failed);
+ /* get the first 1k bits and ensure there are no duplicates */
+ ao_trng_fetch(1);
+ if (ao_failed) { /* show failure */
+ printf("FAILED self test\n");
+ } else { /* show success */
+ printf("PASS - operation NOMINAL\n");
+ /* this blocks! */
+ ao_led_on(AO_LED_GREEN);
+ ao_delay(AO_MS_TO_TICKS(1000));
+ ao_led_off(AO_LED_GREEN);
+ }
+}
+
+static void
+ao_blink_red(void)
+{
+ if (ao_failed < 0)
+ ao_trng_reset(); /* lazy POST */
+ for (;;) {
+ while (!ao_failed)
+ ao_sleep(&ao_failed);
+ while (ao_failed) {
+ ao_led_toggle(AO_LED_RED);
+ ao_delay(AO_MS_TO_TICKS(500));
+ }
+ }
}
static void
-ao_status(void)
+ao_trng_status(void)
{
if (ao_failed)
printf("FAILED\n");
@@ -192,12 +166,11 @@ ao_status(void)
}
static const struct ao_cmds ao_trng_cmds[] = {
- { ao_trng_fetch, "f <kbytes>\0Fetch a block of numbers" },
- { ao_trng_word, "F\0Fetch 16 bit unsigned int" },
- { ao_reset, "R\0reset" },
+ { ao_trng_fetch_cmd, "f <kbytes>\0Fetch a block of numbers" },
+ { ao_trng_reset, "R\0Reset" },
{ ao_blink_green_toggle, "G\0Toggle green LED blinking" },
- { ao_status, "s\0show status" },
- { ao_simulate_failure, "z\0simulate failure" },
+ { ao_trng_status, "s\0Show status" },
+ { ao_trng_failure, "z\0Simulate failure" },
{ 0, NULL },
};
diff --git a/src/drivers/ao_trng.h b/src/drivers/ao_trng.h
index 089c70c6..78577428 100644
--- a/src/drivers/ao_trng.h
+++ b/src/drivers/ao_trng.h
@@ -21,7 +21,4 @@
void
ao_trng_init(void);
-void
-ao_reset(void);
-
#endif /* _AO_TRNG_H_ */
diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c
index d4a75197..42713b6e 100644
--- a/src/usbtrng-v2.0/ao_usbtrng.c
+++ b/src/usbtrng-v2.0/ao_usbtrng.c
@@ -40,6 +40,4 @@ void main(void)
ao_led_off(AO_LED_RED);
ao_start_scheduler();
-
- ao_reset(); /* Power On Self Test */
}