diff options
-rw-r--r-- | src/drivers/ao_trng.c | 207 | ||||
-rw-r--r-- | src/drivers/ao_trng_send.c | 11 | ||||
-rw-r--r-- | src/stmf0/ao_adc_fast.c | 3 | ||||
-rw-r--r-- | src/stmf0/ao_adc_fast.h | 41 |
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(); |