Is there a nondeterministic way to srand() without using the ADC?

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The title more or less speaks for itself, but here's some background. I have a need for a 'random' number(or pseudo-random, or at least something that changes between hard resets) at startup. I need a random seed.

 

This project is using the SAMD21J18A, and a tiny bit of ASF3 for the UARTs and the ADC. I'm using PA02 as an input, and I've discovered the default, minimal configuration of the ADC blocks the input of PA02 (commenting out the configuration of the ADC gives expected behavior of PA02). Is there a way to get a random-ish seed without using the ADC?

 

I realize there are two ways to fix this: seeding the PRNG without using the ADC, or fixing the configuration of the ADC. If you have any input on the latter, here's the code I'm using for the adc:

 

In the main loop:

 

	uint16_t adcResult;

	configure_adc();
	adc_start_conversion(&adc_instance);
	do {
		/* Wait for conversion to be done and read out result */
	} while (adc_read(&adc_instance, &adcResult) == STATUS_BUSY);

a function:

void configure_adc(void)
{
	struct adc_config config_adc;
	adc_get_config_defaults(&config_adc);
	adc_init(&adc_instance, ADC, &config_adc);
	adc_enable(&adc_instance);
}

And the adc_get_config_defaults:

void adc_get_config_defaults(struct adc_config *const config)
{
	Assert(config);
	config->clock_source                  = GCLK_GENERATOR_0;
	config->reference                     = ADC_REFERENCE_INT1V;
	config->clock_prescaler               = ADC_CLOCK_PRESCALER_DIV4;
	config->resolution                    = ADC_RESOLUTION_12BIT;
	config->window.window_mode            = ADC_WINDOW_MODE_DISABLE;
	config->window.window_upper_value     = 0;
	config->window.window_lower_value     = 0;
	config->gain_factor                   = ADC_GAIN_FACTOR_1X;
#if SAMR21
	config->positive_input                = ADC_POSITIVE_INPUT_PIN6 ;
#else
 	//config->positive_input                = ADC_POSITIVE_INPUT_PIN0 ;
#endif
	config->negative_input                = ADC_NEGATIVE_INPUT_GND ;
	config->accumulate_samples            = ADC_ACCUMULATE_DISABLE;
	config->divide_result                 = ADC_DIVIDE_RESULT_DISABLE;
	config->left_adjust                   = false;
	config->differential_mode             = false;
	config->freerunning                   = false;
	config->event_action                  = ADC_EVENT_ACTION_DISABLED;
	config->run_in_standby                = false;
	config->reference_compensation_enable = false;
	config->correction.correction_enable  = false;
	config->correction.gain_correction    = ADC_GAINCORR_RESETVALUE;
	config->correction.offset_correction  = ADC_OFFSETCORR_RESETVALUE;
	config->sample_length                 = 0;
	config->pin_scan.offset_start_scan    = 0;
	config->pin_scan.inputs_to_scan       = 0;
}

 

This topic has a solution.
Last Edited: Sat. Jun 6, 2020 - 07:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To have the ADC input on PA03 :

void configure_adc(void)
{
    struct adc_config config_adc;
    adc_get_config_defaults(&config_adc);
    config_adc.positive_input = ADC_POSITIVE_INPUT_PIN1;
    adc_init(&adc_instance, ADC, &config_adc);
    adc_enable(&adc_instance);
}

This is how the *_get_config_default functions are intended to be used (i.e., get a default config and then overwrite what you need to change). Just commenting out the default setting here

 	//config->positive_input                = ADC_POSITIVE_INPUT_PIN0 ;

gives you whatever is in RAM at that location (but that will likely be 0 so PA02 would be used anyway).
/Lars

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, thanks, got this to work.

 

Problem is, I need just about everything that's attached to the ADC, so PA03 won't work either. But there's another option:

 

void configure_adc(void)
{
    struct adc_config config_adc;
    adc_get_config_defaults(&config_adc);
    config_adc.positive_input = ADC_POSITIVE_INPUT_DAC;
    adc_init(&adc_instance, ADC, &config_adc);
    adc_enable(&adc_instance);
}

I'm not going to pretend I know why this works, but it does. All the pins I need work, and it's random enough.

Last Edited: Sat. Jun 6, 2020 - 07:02 AM