-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MakeCode randint()
not random when Bluetooth enabled
#409
Comments
seedRandom() does not generate a random seed when BLE is running
seedRandom is called before BLE is enabled codal-microbit-v2/model/MicroBit.cpp Line 197 in 96faa85
The seed for subsequent calls to seedRandom while BLE is running could be made pseudo random by using: The softdevice calls work - they don't seem to need a call to start the RNG peripheral
|
Thanks Martin, that's really useful! Looking at the datasheet it should be 128 us to start, and 120 per byte, so |
@microbit-carlos Good catch! I followed the non-BLE code without thinking, and didn't look at the DAL either! If we can guarantee the call will eventually work, maybe this is OK. It's quicker than the byte by byte version. I see up to 810 microseconds, but not 12ms. It seems a bit random.
|
The non-BLE code takes around 240us every time. Waiting for 4 bytes with sd_rand_application_bytes_available_get takes a bit longer because of the extra code. Quite a long wait (between 500 and 1000us) is needed to remove the randomness of the first call, and a wait inside the loop doesn’t seem to help. Code variations#include "MicroBit.h"
MicroBit uBit;
void seedRandom()
{
uint32_t r = 0xBBC5EED;
if(!ble_running())
{
// Start the Random number generator. No need to leave it running... I hope. :-)
NRF_RNG->TASKS_START = 1;
for(int i = 0; i < 4; i++)
{
// Clear the VALRDY EVENT
NRF_RNG->EVENTS_VALRDY = 0;
// Wait for a number ot be generated.
while(NRF_RNG->EVENTS_VALRDY == 0);
r = (r << 8) | ((int) NRF_RNG->VALUE);
}
// Disable the generator to save power.
NRF_RNG->TASKS_STOP = 1;
}
else
{
while ( sd_rand_application_vector_get((uint8_t*)&r, sizeof(r)))
{
//target_wait_us(100);
}
//uint8_t byte;
//do
//{
// sd_rand_application_bytes_available_get( &byte);
//}
//while( byte < sizeof(r));
//sd_rand_application_vector_get( (uint8_t*)&r, sizeof(r));
//for (int i = 0; i < 4; i++)
//{
// // Wait for a number to be generated.
// uint8_t byte;
// do
// {
// sd_rand_application_bytes_available_get( &byte);
// }
// while( byte == 0);
// sd_rand_application_vector_get( &byte, 1);
// r = (r << 8) | ((int) byte);
//}
}
uBit.seedRandom(r);
}
int main()
{
CODAL_TIMESTAMP t0, t1;
int randomInt = 0;
uBit.init();
target_wait_us(1000);
//t0 = system_timer_current_time_us();
//uBit.seedRandom();
//t1 = system_timer_current_time_us();
//uBit.sleep(1000);
//DMESG("uBit.seedRandom %d", (int)(t1-t0));
t0 = system_timer_current_time_us();
seedRandom();
t1 = system_timer_current_time_us();
uBit.sleep(1000);
DMESG(" seedRandom %d", (int)(t1-t0));
while (true)
{
uBit.display.print('*');
uBit.sleep(1000);
t0 = system_timer_current_time_us();
uBit.seedRandom();
t1 = system_timer_current_time_us();
DMESG("uBit.seedRandom %d", (int)(t1-t0));
randomInt = uBit.random(9);
uBit.display.print( randomInt);
uBit.sleep(1000);
t0 = system_timer_current_time_us();
seedRandom();
t1 = system_timer_current_time_us();
DMESG(" seedRandom %d", (int)(t1-t0));
randomInt = uBit.random(9);
uBit.display.print( randomInt);
uBit.sleep(1000);
}
}
|
I think maybe we are seeing differences in time because you are seeding and measuring after I'm getting my measurements by moving codal-microbit-v2/model/MicroBit.cpp Lines 297 to 306 in bd446c4
#endif
// Seed our random number generator
uint32_t t = system_timer_current_time_us();
seedRandom();
uint32_t t2 = system_timer_current_time_us();
serial.printf("seed t: %d\n", t2 - t);
// Deschedule for a little while, just to allow for any components that finialise initialisation
// as a background task, and to allow the power mamanger to repsonse to background events from the KL27
// before any user code begins running.
sleep(10);
return DEVICE_OK;
} In this case it does make sense to move it after the sleep, but I still wonder why it would take so long... |
Oh, yes! I see the same - sometimes over 13ms. That explains why a ms pause is mentioned in For the initial seedRandom call in MicroBit:init(), I think it should stay before BLE is initialised. I have wondered why it wasn't further up, say before the component init() loop at least. The BLE mode problem was revealed by MakeCode's extra call after uBit.init (which I don't understand). It looks like MakeCode has a fair amount of code between uBit.init() and platform_init(), which hopefully would act like a long wait. |
Yes, you are right, I was mostly playing around with a few different options initially when I encountered the odd timings, and 12ms felt excessive. The issue at hand in CODAL is (as you have mentioned) that because MakeCode re-seeds on its So, we should add the softdevice call in However, the weird thing is that in MakeCode, this is also a problem for V1, and in DAL we already have this sd code: So not sure yet what might be the problem in V1, maybe |
Oh, I hadn't realised the report included V1. The problem there is that the V1 code gives up after one try rather than looping until it succeeds. I noticed this but thought maybe it happened to be working in V1. It does seem to work first time after the start-up delay. |
Thanks Martin for all the help here! I've created this PR code codal-microbit-v2: This issue for DAL: And this workaround for MakeCode (as it'll take a while for the DAL fix to be released): |
From:
Replicable example from:
With this example the random numbers are always seeded with the same value. Changing
MICROBIT_BLE_ENABLED
to1
works.Possible solution:
The text was updated successfully, but these errors were encountered: