1 /* 2 * Copyright (c) 2017 Oticon A/S 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #include "NRF_RNG.h" 7 #include <string.h> 8 #include <stdbool.h> 9 #include "time_machine_if.h" 10 #include "NRF_HW_model_top.h" 11 #include "NRF_PPI.h" 12 #include "irq_ctrl.h" 13 #include "irq_sources.h" 14 #include "bs_rand_main.h" 15 16 /* 17 * RNG — Random number generator 18 * http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52840.ps%2Frng.html&cp=2_0_0_24&anchor=concept_h35_c1l_cs 19 * 20 * Very rough model 21 */ 22 23 NRF_RNG_Type NRF_RNG_regs; 24 bs_time_t Timer_RNG = TIME_NEVER; //Time when the next random number will be ready 25 26 static bool RNG_hw_started = false; 27 static bool RNG_INTEN = false; //interrupt enable 28 29 /** 30 * Initialize the RNG model 31 */ nrg_rng_init()32void nrg_rng_init(){ 33 memset(&NRF_RNG_regs, 0, sizeof(NRF_RNG_regs)); 34 RNG_hw_started = false; 35 RNG_INTEN = false; 36 Timer_RNG = TIME_NEVER; 37 } 38 39 /** 40 * Clean up the RNG model before program exit 41 */ nrf_rng_clean_up()42void nrf_rng_clean_up(){ 43 44 } 45 46 /** 47 * TASK_START triggered handler 48 */ nrf_rng_task_start()49void nrf_rng_task_start(){ 50 if (RNG_hw_started) { 51 return; 52 } 53 RNG_hw_started = true; 54 55 bs_time_t delay; 56 if ( NRF_RNG_regs.CONFIG ){ //Bias correction enabled 57 delay = 120 + 128; 58 /* 59 * The spec says that the delay is unpredictable yet it does not 60 * provide any indication of what kind of random distribution to 61 * expect => I just assume the value is always the average(?) they 62 * provide 63 */ 64 } else { 65 delay = 30 + 128; 66 } 67 Timer_RNG = tm_get_hw_time() + delay; 68 69 nrf_hw_find_next_timer_to_trigger(); 70 } 71 72 /** 73 * TASK_STOP triggered handler 74 */ nrf_rng_task_stop()75void nrf_rng_task_stop(){ 76 RNG_hw_started = false; 77 Timer_RNG = TIME_NEVER; 78 nrf_hw_find_next_timer_to_trigger(); 79 } 80 81 nrf_rng_regw_sideeffects_TASK_START()82void nrf_rng_regw_sideeffects_TASK_START(){ 83 if ( NRF_RNG_regs.TASKS_START ) { 84 NRF_RNG_regs.TASKS_START = 0; 85 nrf_rng_task_start(); 86 } 87 } 88 nrf_rng_regw_sideeffects_TASK_STOP()89void nrf_rng_regw_sideeffects_TASK_STOP(){ 90 if ( NRF_RNG_regs.TASKS_STOP ) { 91 NRF_RNG_regs.TASKS_STOP = 0; 92 nrf_rng_task_stop(); 93 } 94 } 95 nrf_rng_regw_sideeffects_INTENSET()96void nrf_rng_regw_sideeffects_INTENSET(){ 97 if ( NRF_RNG_regs.INTENSET ) { 98 RNG_INTEN = true; 99 } 100 } 101 nrf_rng_regw_sideeffects_INTENCLEAR()102void nrf_rng_regw_sideeffects_INTENCLEAR(){ 103 if ( NRF_RNG_regs.INTENCLR ) { 104 RNG_INTEN = false; 105 NRF_RNG_regs.INTENSET = 0; 106 NRF_RNG_regs.INTENCLR = 0; 107 } 108 } 109 110 /** 111 * Handle any register side effect (by inspecting the registers states) 112 * (deprecated) 113 */ nrf_rng_regw_sideeffects()114void nrf_rng_regw_sideeffects(){ 115 116 nrf_rng_regw_sideeffects_TASK_START(); 117 118 nrf_rng_regw_sideeffects_TASK_STOP(); 119 120 nrf_rng_regw_sideeffects_INTENSET(); 121 122 nrf_rng_regw_sideeffects_INTENCLEAR(); 123 } 124 125 /** 126 * Time has come when a new random number is ready 127 */ nrf_rng_timer_triggered()128void nrf_rng_timer_triggered(){ 129 130 NRF_RNG_regs.VALUE = bs_random_uint32(); 131 //A proper random number even if CONFIG is not set to correct the bias 132 133 if ( NRF_RNG_regs.SHORTS == 0 ) { 134 //When the next value will be ready: 135 bs_time_t delay; 136 if ( NRF_RNG_regs.CONFIG ){ //Bias correction enabled 137 delay = 120; 138 } else { 139 delay = 30 ; 140 } 141 Timer_RNG = tm_get_hw_time() + delay; 142 } else { 143 Timer_RNG = TIME_NEVER; 144 } 145 nrf_hw_find_next_timer_to_trigger(); 146 147 NRF_RNG_regs.EVENTS_VALRDY = 1; 148 nrf_ppi_event(RNG_EVENTS_VALRDY); 149 if ( RNG_INTEN ){ 150 hw_irq_ctrl_set_irq(NRF5_IRQ_RNG_IRQn); 151 //Note: there is no real need to delay the interrupt a delta 152 } 153 } 154