summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/ao_trng.c207
-rw-r--r--src/drivers/ao_trng_send.c11
-rw-r--r--src/stmf0/ao_adc_fast.c3
-rw-r--r--src/stmf0/ao_adc_fast.h41
4 files changed, 48 insertions, 214 deletions
diff --git a/src/drivers/ao_trng.c b/src/drivers/ao_trng.c
index 496c5ce7..e69cd30b 100644
--- a/src/drivers/ao_trng.c
+++ b/src/drivers/ao_trng.c
@@ -20,80 +20,17 @@
#include <ao_crc.h>
#include <ao_trng.h>
-/* It is difficult to know exactly when we are connected.
- This flag will be set once one of *our* commands has been called */
-static uint8_t ao_connected = 0;
-
-/* note: refactor this with ao_monitor.c? see ao_cmd_put16() */
-static const char xdigit[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-};
-
-#define byte_to_hex(b) ((xdigit[(b) >> 4] << 8 ) | xdigit[(b) & 0xf])
-
-static struct ao_task ao_blink_green_task;
-static uint8_t ao_blinking_green = 0;
-
-static void
-ao_blink_green(void)
-{
- for (;;) {
- while (!ao_blinking_green)
- ao_sleep(&ao_blinking_green);
- while (ao_blinking_green) {
- ao_led_toggle(AO_LED_GREEN);
- ao_delay(AO_MS_TO_TICKS(1000));
- }
- }
-}
-
-
static void
-ao_blink_green_toggle(void)
-{
- ao_connected = 1;
- ao_blinking_green = !ao_blinking_green;
- if (!ao_blinking_green)
- ao_led_off(AO_LED_GREEN);
- ao_wakeup(&ao_blinking_green);
-}
-
-static struct ao_task ao_blink_red_task;
-static uint8_t ao_failed = 0; /* 0 NOMINAL, 1 FAILED */
-static uint8_t ao_post = 0; /* 0 POST needed, 1 powered up */
-
-/* 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_trng_failure()
-{
- ao_failed = 1;
- ao_wakeup(&ao_failed);
-}
-
-void
-ao_trng_failure_cmd(void)
-{
- ao_trng_failure();
-}
-
-static void
-ao_trng_fetch(uint32_t kbytes, uint8_t printhex)
+ao_trng_fetch(void)
{
static uint16_t *buffer[2];
+ uint32_t kbytes = 1;
uint32_t count;
int usb_buf_id;
uint16_t i;
- uint32_t cur;
- uint32_t prev = 0;
- uint32_t prev_set = 0; /* prev has been set */
uint16_t *buf;
- uint32_t *rnd;
- uint16_t r; /* random word */
+ uint16_t t;
+ uint32_t *rnd = (uint32_t *) ao_adc_ring;
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
@@ -102,149 +39,41 @@ ao_trng_fetch(uint32_t kbytes, uint8_t printhex)
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;
- /* if we print in hex each byte requires two bytes output */
- count = (kbytes * (1024/AO_USB_IN_SIZE)) << printhex;
+ count = kbytes * (1024/AO_USB_IN_SIZE);
ao_crc_reset();
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);
+ t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
buf = buffer[usb_buf_id];
for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
- cur = *rnd++;
- if (prev_set && (cur == prev))
- ao_trng_failure();
- r = ao_crc_in_32_out_16(cur);
- if (printhex) {
- *buf++ = byte_to_hex(r >> 8);
- *buf++ = byte_to_hex(r & 0xff);
- i++;
- } else {
- *buf++ = r;
- }
- prev = cur;
- prev_set++;
+ *buf++ = ao_crc_in_32_out_16(rnd[t]);
+ t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
}
ao_adc_ack(AO_USB_IN_SIZE);
- if (ao_connected) {
- ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
- ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
- ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
- }
+ ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
+ ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
usb_buf_id = 1-usb_buf_id;
}
ao_led_off(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE);
- if (ao_connected)
- flush();
-}
-
-static uint32_t
-ao_trng_get_kbytes(void)
-{
- 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;
- return kbytes;
-}
-
-static void
-ao_trng_fetch_cmd(void)
-{
- ao_connected = 1;
- if (!ao_failed)
- ao_trng_fetch(ao_trng_get_kbytes(), 0);
-}
-
-static void
-ao_trng_fetch_hex(void)
-{
- ao_connected = 1;
- if (!ao_failed)
- ao_trng_fetch(ao_trng_get_kbytes(), 1);
- putchar('\n');
-}
-
-/* NOTE: the reset function also functions as the Power On Self Test */
-void
-ao_trng_reset(void)
-{
- if (ao_connected)
- printf("Resetting...\n");
- 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, 1);
- if (ao_connected)
- putchar('\n');
- if (ao_failed) { /* show failure */
- if (ao_connected)
- printf("FAILED self test\n");
- } else { /* show success */
- if (ao_connected)
- 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);
- }
-}
-
-void
-ao_trng_reset_cmd(void)
-{
- ao_connected = 1;
- ao_trng_reset();
-}
-
-static void
-ao_blink_red(void)
-{
- if (!ao_post) {
- ao_trng_reset(); /* POST */
- ao_post = 1;
- }
- 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_trng_status(void)
-{
- ao_connected = 1;
- if (ao_failed)
- printf("FAILED\n");
- else
- printf("NOMINAL\n");
+ flush();
}
static const struct ao_cmds ao_trng_cmds[] = {
- { ao_trng_fetch_cmd, "f <kbytes>\0Fetch a block of numbers" },
- { ao_trng_fetch_hex, "F <kbytes>\0Fetch a block of numbers (in hex)" },
- { ao_trng_reset_cmd, "R\0Reset" },
- { ao_blink_green_toggle, "G\0Toggle green LED blinking" },
- { ao_trng_status, "s\0Show status" },
- { ao_trng_failure_cmd, "z\0Simulate failure" },
+ { ao_trng_fetch, "f <kbytes>\0Fetch a block of numbers" },
{ 0, NULL },
};
void
ao_trng_init(void)
{
- ao_add_task(&ao_blink_red_task, ao_blink_red, "blink_red");
- ao_add_task(&ao_blink_green_task, ao_blink_green, "blink_green");
ao_cmd_register(ao_trng_cmds);
}
diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c
index 34a8a981..bac6035c 100644
--- a/src/drivers/ao_trng_send.c
+++ b/src/drivers/ao_trng_send.c
@@ -27,7 +27,8 @@ ao_trng_send(void)
int usb_buf_id;
uint16_t i;
uint16_t *buf;
- uint32_t *rnd;
+ uint16_t t;
+ uint32_t *rnd = (uint32_t *) ao_adc_ring;
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
@@ -42,10 +43,12 @@ ao_trng_send(void)
for (;;) {
ao_led_on(AO_LED_TRNG_ACTIVE);
- rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */
+ t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
buf = buffer[usb_buf_id];
- for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++)
- *buf++ = ao_crc_in_32_out_16(*rnd++);
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ *buf++ = ao_crc_in_32_out_16(rnd[t]);
+ t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
+ }
ao_adc_ack(AO_USB_IN_SIZE);
ao_led_off(AO_LED_TRNG_ACTIVE);
ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c
index 7d2a4fd7..26e6691c 100644
--- a/src/stmf0/ao_adc_fast.c
+++ b/src/stmf0/ao_adc_fast.c
@@ -23,7 +23,7 @@ uint16_t ao_adc_ring[AO_ADC_RING_SIZE] __attribute__((aligned(4)));
/* Maximum number of samples fetched per _ao_adc_start call */
#define AO_ADC_RING_CHUNK (AO_ADC_RING_SIZE >> 1)
-uint16_t ao_adc_ring_head, ao_adc_ring_tail;
+uint16_t ao_adc_ring_head, ao_adc_ring_remain;
uint16_t ao_adc_running;
/*
@@ -36,6 +36,7 @@ static void ao_adc_dma_done(int index)
{
(void) index;
ao_adc_ring_head += ao_adc_running;
+ ao_adc_ring_remain += ao_adc_running;
if (ao_adc_ring_head == AO_ADC_RING_SIZE)
ao_adc_ring_head = 0;
ao_adc_running = 0;
diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h
index ca5f7fb9..c6903e9f 100644
--- a/src/stmf0/ao_adc_fast.h
+++ b/src/stmf0/ao_adc_fast.h
@@ -31,52 +31,53 @@ extern uint16_t ao_adc_ring[AO_ADC_RING_SIZE];
#define ao_adc_ring_step(pos,inc) (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1))
-extern uint16_t ao_adc_ring_head, ao_adc_ring_tail;
+extern uint16_t ao_adc_ring_head, ao_adc_ring_remain;
extern uint16_t ao_adc_running;
-void
-_ao_adc_start(void);
-
+/*
+ * Place to start fetching values from
+ */
static inline uint16_t
-_ao_adc_remain(void)
+ao_adc_ring_tail(void)
{
- if (ao_adc_ring_tail > ao_adc_ring_head)
- return AO_ADC_RING_SIZE - ao_adc_ring_tail;
- return ao_adc_ring_head - ao_adc_ring_tail;
+ return (ao_adc_ring_head - ao_adc_ring_remain) & (AO_ADC_RING_SIZE - 1);
}
+void
+_ao_adc_start(void);
+
+/*
+ * Space available to write ADC values into
+ */
static inline uint16_t
_ao_adc_space(void)
{
- if (ao_adc_ring_head >= ao_adc_ring_tail)
+ /* Free to end of buffer? */
+ if (ao_adc_ring_remain <= ao_adc_ring_head)
return AO_ADC_RING_SIZE - ao_adc_ring_head;
- return ao_adc_ring_tail - ao_adc_ring_head;
+
+ /* no, return just the unused entries beyond head */
+ return AO_ADC_RING_SIZE - ao_adc_ring_remain;
}
-static inline uint16_t *
+static inline uint16_t
ao_adc_get(uint16_t n)
{
- if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE)
- ao_panic(AO_PANIC_ADC);
ao_arch_block_interrupts();
- while (_ao_adc_remain() < n) {
+ while (ao_adc_ring_remain < n) {
if (!ao_adc_running)
_ao_adc_start();
ao_sleep(&ao_adc_ring_head);
}
ao_arch_release_interrupts();
- return &ao_adc_ring[ao_adc_ring_tail];
+ return ao_adc_ring_tail();
}
static inline void
ao_adc_ack(uint16_t n)
{
- if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE)
- ao_panic(AO_PANIC_ADC);
ao_arch_block_interrupts();
- ao_adc_ring_tail += n;
- if (ao_adc_ring_tail == AO_ADC_RING_SIZE)
- ao_adc_ring_tail = 0;
+ ao_adc_ring_remain -= n;
if (!ao_adc_running)
_ao_adc_start();
ao_arch_release_interrupts();