1

STM32 chips (and many others) have hardware random number generator (RNG), it is faster and more reliable than software RNG provided by libc. Compiler knows nothing about hardware.

Is there a way to redefine implementation of rand()?

There are other hardware modules, i.e real time clock (RTC) which can provide data for time().

kyb
  • 7,233
  • 5
  • 52
  • 105
  • 3
    Just implement your own version of `rand()` if you link it from a .o, it should override what's in the stdlib. If you link it from an .a, it still should take that version if the author of the stdlib version has marked it WEAK (which they should have). – Russ Schultz Apr 06 '19 at 16:54
  • You might as well read on linker's --wrap option that comes handy when you need both variants to be available (for comparison etc.) – tum_ Apr 06 '19 at 22:27

1 Answers1

6

You simply override them by defining functions with identical signature. If they are defined WEAK in the standard library they will be overridden, otherwise they are overridden on a first resolution basis so so long as your implementation is passed to the linker before libc is searched, it will override. Moreover .o / .obj files specifically are used in symbol resolution before .a / .lib files, so if your implementation is included in your project source, it will always override.

You should be careful to get the semantics of your implementation correct. For example rand() returns a signed integer 0 to RAND_MAX, which is likley not teh same as the RNG hardware. Since RAND_MAX is a macro, changing it would require changing the standard header, so your implementation needs to enforce the existing RAND_MAX.

Example using STM32 Standard Peripheral Library:

#include <stdlib.h>
#include <stm32xxx.h> // Your processor header here

#if defined __cplusplus
extern "C"
{
#endif

static int rng_running = 0 ;

int rand( void )
{
    if( rng_running == 0 )
    {
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
        RNG_Cmd(ENABLE);
        rng_running = 1 ;
    }
    while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET) { }

    // Assumes RAND_MAX is an "all ones" integer value (check)
    return (int)(RNG_GetRandomNumber() & (unsigned)RAND_MAX) ;
}

void srand( unsigned ) { }

#if defined __cplusplus
}
#endif

For time() similar applies and there is an example at Problem with time() function in embedded application with C

Clifford
  • 88,407
  • 13
  • 85
  • 165