initial
This commit is contained in:
commit
42e59d38c5
|
@ -0,0 +1,3 @@
|
||||||
|
cmake-build/
|
||||||
|
test*.*
|
||||||
|
screenlog.*
|
|
@ -0,0 +1,40 @@
|
||||||
|
set(PROJECT "rorand")
|
||||||
|
|
||||||
|
option(PICO_NO_FLASH "Disable writing the compiled program to flash, and only load it to RAM. Useful for testing, but not much else (OFF by default)." OFF)
|
||||||
|
option(PICO_COPY_TO_RAM "Run all code in RAM, while the program is also stored on flash. On bootup, everything will be copied to RAM (OFF by default)." OFF)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.11)
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
project(${PROJECT})
|
||||||
|
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
add_executable(${PROJECT})
|
||||||
|
|
||||||
|
# use usb output
|
||||||
|
pico_enable_stdio_uart(${PROJECT} 0)
|
||||||
|
pico_enable_stdio_usb(${PROJECT} 1)
|
||||||
|
|
||||||
|
target_sources(${PROJECT} PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/util.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/rorand.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT} PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT}
|
||||||
|
pico_stdlib pico_unique_id hardware_pio hardware_dma hardware_clocks
|
||||||
|
hardware_resets hardware_sync hardware_pwm cmsis_core pico_multicore
|
||||||
|
tinyusb_device_unmarked pico_usb_reset_interface_headers pico_unique_id
|
||||||
|
)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(${PROJECT})
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type -Werror=aggressive-loop-optimizations")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--cref")
|
|
@ -0,0 +1,62 @@
|
||||||
|
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate this SDK
|
||||||
|
# It should be include()ed prior to project()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||||
|
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||||
|
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||||
|
|
||||||
|
if (NOT PICO_SDK_PATH)
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT)
|
||||||
|
include(FetchContent)
|
||||||
|
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||||
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
if (NOT pico_sdk)
|
||||||
|
message("Downloading Raspberry Pi Pico SDK")
|
||||||
|
FetchContent_Populate(pico_sdk)
|
||||||
|
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||||
|
endif ()
|
||||||
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||||
|
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||||
|
|
||||||
|
include(${PICO_SDK_INIT_CMAKE_FILE})
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <hardware/structs/bus_ctrl.h>
|
||||||
|
#include <hardware/structs/rosc.h>
|
||||||
|
#include <hardware/clocks.h>
|
||||||
|
#include <hardware/vreg.h>
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
#include <pico/time.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "rorand.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
vreg_set_voltage(VREG_VOLTAGE_1_15);
|
||||||
|
set_sys_clock_khz(250*1000, true);
|
||||||
|
for (size_t i = 0; i < 0x100; ++i) asm volatile("nop");
|
||||||
|
busy_wait_ms(16);
|
||||||
|
|
||||||
|
stdio_init_all();
|
||||||
|
while (!stdio_usb_connected()) ;
|
||||||
|
busy_wait_ms(16);
|
||||||
|
iprintf("hello world!\n");
|
||||||
|
|
||||||
|
if ((clocks_hw->clk[clk_sys].ctrl & CLOCKS_CLK_SYS_CTRL_AUXSRC_BITS) ==
|
||||||
|
(CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC << CLOCKS_CLK_SYS_CTRL_AUXSRC_LSB)) {
|
||||||
|
panic("System is running from ring oscillator. This makes it impossible to be used as randomness source.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
rorand_init();
|
||||||
|
uint8_t data[32];
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
const uintptr_t total = 1024*1024;
|
||||||
|
for (uintptr_t off = 0; off < total; off += count_of(data)) {
|
||||||
|
rorand_get(data, count_of(data)*CHAR_BIT);
|
||||||
|
hexdump(NULL, off, data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
iprintf("done\n");
|
||||||
|
/*uint32_t a = 0;
|
||||||
|
while(1) {
|
||||||
|
iprintf("a%lu ", a);
|
||||||
|
++a;
|
||||||
|
if (a>16)break;
|
||||||
|
}
|
||||||
|
iprintf("\n");*/
|
||||||
|
while(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <RP2040.h>
|
||||||
|
#include <hardware/structs/psm.h>
|
||||||
|
#include <hardware/structs/rosc.h>
|
||||||
|
#include <hardware/structs/systick.h>
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
#include <pico/critical_section.h>
|
||||||
|
|
||||||
|
#include "rorand.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define IMPL 2
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint32_t enter_critical_section(void) {
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
uint32_t dis = __get_PRIMASK();
|
||||||
|
__disable_irq();
|
||||||
|
return dis;
|
||||||
|
}
|
||||||
|
static inline void exit_critical_section(uint32_t dis) {
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
__set_PRIMASK(dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void rosc_wait_stab(void) {
|
||||||
|
while (!(rosc_hw->status & ROSC_STATUS_STABLE_BITS)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t tests[256];
|
||||||
|
static uint32_t testind;
|
||||||
|
static critical_section_t cs;
|
||||||
|
static void test_monitor(uint32_t v) {
|
||||||
|
tests[testind] = v;
|
||||||
|
++testind;
|
||||||
|
|
||||||
|
if (testind == count_of(tests)) {
|
||||||
|
//iprintf("[tst] do test!\n");
|
||||||
|
// get average
|
||||||
|
uint64_t avg = 0;
|
||||||
|
for (size_t i = 0; i < count_of(tests); ++i) avg += tests[i];
|
||||||
|
avg >>= 8;
|
||||||
|
// get variance
|
||||||
|
uint64_t var = 0;
|
||||||
|
for (size_t i = 0; i < count_of(tests); ++i) {
|
||||||
|
uint64_t x = tests[i] - avg;
|
||||||
|
var += x * x;
|
||||||
|
}
|
||||||
|
var >>= 8;
|
||||||
|
float stddev = sqrtf((uint32_t)var);
|
||||||
|
printf("[tst] avg=%llu, var=%llu stddev=%f\n", avg, var, stddev);
|
||||||
|
testind = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint __time_critical_func(get_raw_bit_a)(void) {
|
||||||
|
busy_wait_us_32(1);
|
||||||
|
// 1. power-gate rosc and wait a bit for the value to become indeterminate
|
||||||
|
psm_hw->frce_off = PSM_FRCE_OFF_ROSC_BITS;
|
||||||
|
busy_wait_us_32(1);
|
||||||
|
// 2. bring it back
|
||||||
|
psm_hw->frce_on = PSM_FRCE_ON_ROSC_BITS;
|
||||||
|
while (!(psm_hw->done & PSM_DONE_ROSC_BITS)) ;
|
||||||
|
rorand_init();
|
||||||
|
|
||||||
|
uint bit = rosc_hw->randombit & 1;
|
||||||
|
|
||||||
|
// TODO: test monitor?
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
static uint __time_critical_func(get_raw_bit_b)(void) {
|
||||||
|
volatile uint32_t* tick = &SysTick->VAL;
|
||||||
|
volatile uint32_t* count = &rosc_hw->count;
|
||||||
|
uint32_t a, b;
|
||||||
|
|
||||||
|
critical_section_enter_blocking(&cs);
|
||||||
|
uint32_t v = enter_critical_section();
|
||||||
|
{
|
||||||
|
*tick = 0;
|
||||||
|
__COMPILER_BARRIER();
|
||||||
|
a = *tick;
|
||||||
|
__COMPILER_BARRIER();
|
||||||
|
for (size_t i = 0; i < 0x1/*000*/; ++i) {
|
||||||
|
*count = 0x80;
|
||||||
|
// TODO: tweak the above parameter.
|
||||||
|
// * 0x20 seems to result in a few weak test results in dieharder (1 MiB data)
|
||||||
|
// * 0x80 seems to pass them
|
||||||
|
// -> take something in the middle to speed up things while still being good?
|
||||||
|
// problematic test are diehard_operm5, sts_monobit
|
||||||
|
__COMPILER_BARRIER();
|
||||||
|
while (*count) __COMPILER_BARRIER();
|
||||||
|
}
|
||||||
|
__COMPILER_BARRIER();
|
||||||
|
b = *tick;
|
||||||
|
}
|
||||||
|
exit_critical_section(v);
|
||||||
|
critical_section_exit(&cs);
|
||||||
|
|
||||||
|
uint32_t diff = a - b;
|
||||||
|
//iprintf("[---] diff=%lu a=%lu b=%lu\n", diff, a, b);
|
||||||
|
uint bit = diff & 1;
|
||||||
|
uint32_t test = diff >> 1;
|
||||||
|
//test_monitor(test);
|
||||||
|
|
||||||
|
return bit ^ rosc_hw->randombit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline static uint get_raw_bit(void) {
|
||||||
|
/*#if IMPL == 1
|
||||||
|
return get_raw_bit_a();
|
||||||
|
#else*/
|
||||||
|
return get_raw_bit_b();
|
||||||
|
/*#endif*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint neumann_filter(void) {
|
||||||
|
uint a, b;
|
||||||
|
uint32_t counter = 0;
|
||||||
|
const uint32_t limit = 0x40;
|
||||||
|
|
||||||
|
do {
|
||||||
|
a = get_raw_bit();
|
||||||
|
b = get_raw_bit();
|
||||||
|
++counter;
|
||||||
|
} while (a == b && counter < limit);
|
||||||
|
|
||||||
|
if (counter == limit) iprintf("[---] aaaaaaa!\n");
|
||||||
|
//iprintf("[---] emit bit %u%s\n", b, (counter == 0x100) ? "aaaaaa" : "");
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rorand_init(void) {
|
||||||
|
critical_section_init(&cs);
|
||||||
|
|
||||||
|
testind = 0;
|
||||||
|
memset(tests, 0, sizeof(tests));
|
||||||
|
|
||||||
|
SysTick->LOAD = 0xffffffffu;
|
||||||
|
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||||
|
|
||||||
|
/*psm_hw->frce_on = PSM_FRCE_ON_ROSC_BITS;
|
||||||
|
while (!(psm_hw->done & PSM_DONE_ROSC_BITS)) ;
|
||||||
|
iprintf("[---] rosc power on\n");*/
|
||||||
|
|
||||||
|
//rosc_hw->dormant = 1;
|
||||||
|
rosc_hw->ctrl = 0xfabfa7; // enable, high freqrange
|
||||||
|
rosc_hw->freqa = 0x96967777;
|
||||||
|
rosc_hw->freqb = 0x96967777;
|
||||||
|
//rosc_hw->dormant = 0;
|
||||||
|
rosc_wait_stab();
|
||||||
|
iprintf("[---] rosc now stab\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rorand_get(void* dst_, size_t nbits) {
|
||||||
|
uint8_t* dst = (uint8_t*)dst_;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < nbits; j += 8) {
|
||||||
|
size_t bs = nbits - j;
|
||||||
|
if (bs > 8) bs = 8;
|
||||||
|
//iprintf("[===] byte %u (%u bits)\n", j>>3, bs);
|
||||||
|
|
||||||
|
uint8_t v = 0;
|
||||||
|
for (size_t i = 0; i < bs; ++i) {
|
||||||
|
v <<= 1;
|
||||||
|
uint r = neumann_filter();
|
||||||
|
v |= r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//iprintf("[===] emit byte %02hhx\n", v);
|
||||||
|
*dst = v;
|
||||||
|
++dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#ifndef RORAND_H_
|
||||||
|
#define RORAND_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void rorand_init(void);
|
||||||
|
void rorand_get(void* dst, size_t nbits);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
void hexdump(const char* pfix, uintptr_t baseaddr, const void* data_, size_t nbytes) {
|
||||||
|
char fmt[8];
|
||||||
|
const uint8_t* data = (const uint8_t*)data_;
|
||||||
|
|
||||||
|
if (pfix) iprintf("%s:\n", pfix);
|
||||||
|
|
||||||
|
uint32_t nybs = ((32 - __builtin_clz(baseaddr + nbytes)) + 3) >> 2;
|
||||||
|
sniprintf(fmt, sizeof fmt, "%%0%lulx\t", nybs);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nbytes; i += 16) {
|
||||||
|
iprintf(fmt, baseaddr + i);
|
||||||
|
for (size_t j = 0; i + j < nbytes && j < 16; ++j) {
|
||||||
|
iprintf("%02hhx%c", data[i+j], (j == 15 || i+j == nbytes-1) ? '\n' : ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#ifndef UTIL_H_
|
||||||
|
#define UTIL_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
void hexdump(const char* pfix, uintptr_t baseaddr, const void* data, size_t nbytes);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue