# LwIP stdlib rand() function failing

**URL:** <https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684>\
**Category:** Kernel\
**Created:** [October 22, 2024, 4:46am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684 "2024-10-22T04:46:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rgarnett](https://avatars.discourse-cdn.com/v4/letter/r/779978/32.png) [@rgarnett](https://forums.freertos.org/u/rgarnett)\
**Post date:** [October 22, 2024, 4:46am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/1 "2024-10-22T04:46:08Z")

</div>

Hi,

I’m trying to get LwIP going on an STH7. The initialisation of the network functions calls the stdlib function rand() in a number of places. The function fails and you end up in the syscalls module:

```auto
void _exit (int status)
{
	_kill(status, -1);
	while (1) {} /* Make sure we hang here */
}

```

LwIP Initialisation gets called from the default task which I named monitorTask as a static task as it runs all the time.

I am using the cmsis calling protocol as it is built in to the ST code generator.

Below are the relevant extracts from main.c.

```auto
/* Definitions for monitorTaskHnd */
osThreadId_t monitorTaskHndHandle;
uint32_t monitorTaskHndBuffer[4096];  
osStaticThreadDef_t monitorTaskHndControlBlock;
const osThreadAttr_t monitorTaskHnd_attributes = {
  .name = "monitorTaskHnd",
  .cb_mem = &monitorTaskHndControlBlock,
  .cb_size = sizeof(monitorTaskHndControlBlock),
  .stack_mem = &monitorTaskHndBuffer[0],
  .stack_size = sizeof(monitorTaskHndBuffer),
  .priority = (osPriority_t) osPriorityNormal,
};...

int main(void)
{ ...
	uint32_t randNo = rand();
...
}

void monitorTask(void *argument)
{

  uint32_t randNo = rand();
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(100);
  }
  /* USER CODE END 5 */
}

```

To take LwIP out of the equation I called rand() from within the main function and then at the start of the monitor task.

rand() works when called from main, but errors out when called from the task.

I tried turning off interrupts as rand is not guaranteed re-entrent but it sill failed to the  
\_exit (int status) function.

The disassembly of and stepping shows it fails at the assert line

```auto
          rand:
900347fc: ldr r3, [pc, #88] @ (0x90034858 <rand+92>)
900347fe: push {r4, lr}
90034800: ldr r4, [r3, #0]
90034802: ldr r3, [r4, #48] @ 0x30
90034804: cbnz r3, 0x90034834 <rand+56>
90034806: movs r0, #24
90034808: bl 0x90034680 <malloc>
9003480c: mov r2, r0
9003480e: str r0, [r4, #48] @ 0x30
90034810: cbnz r0, 0x9003481c <rand+32>
90034812: ldr r3, [pc, #72] @ (0x9003485c <rand+96>)
90034814: ldr r0, [pc, #72] @ (0x90034860 <rand+100>)
90034816: movs r1, #82 @ 0x52
90034818: bl 0x90034638 <__assert_func> /* <== ******Fails here******** /

```

I reckon the problem has something to do with the heap, but I don’t understand what it might be.

Has anyone any ideas.

Rob

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [October 22, 2024, 5:15am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/2 "2024-10-22T05:15:23Z")

</div>

Seems like malloc is failing to allocate memory. You have couple of options -

1. LWIP allows overriding [LWIP\_RAND](https://github.com/lwip-tcpip/lwip/blob/master/contrib/ports/unix/port/include/arch/cc.h#L66) and most likely, your implementation of it is calling `rand`. You can change that to use any TRNG (assuming one is available on your hardware).
2. You can use GCC linker warp to swap `rand` with another implementation which uses TRNG.
3. If you want to use the newlib version of `rand`, you need to do the following -
  - One of the auto-generated source file will have `sbrk` or `brk` implementation which needs to be fixed. Please share the definition so that we can look.
  - Implement malloc\_lock and malloc\_unlock to ensure that malloc is thread safe.

---

<div class="post-metadata">

**Author:** ![rgarnett](https://avatars.discourse-cdn.com/v4/letter/r/779978/32.png) [@rgarnett](https://forums.freertos.org/u/rgarnett)\
**Post date:** [October 22, 2024, 6:48am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/3 "2024-10-22T06:48:01Z")

</div>

Hi,

Thanks for that.

1. I’m doing the first of your suggestions at the moment.

2. I don’t understand your second suggestion about the linker script.

3. The sysmem.c auto generated file has the following \_sbrk code:

```auto
/* Includes */
#include <errno.h>
#include <stdio.h>

#include <sys/types.h> // Added as a workaround for Bugzilla 158966

/* Variables */
extern int errno;
register char * stack_ptr asm("sp");

/* Functions */

/**
 _sbrk
 Increase program data space. Malloc and related functions depend on this
**/
caddr_t _sbrk(int incr)
{
	extern char end asm("end");
	static char *heap_end;
	char *prev_heap_end;

	if (heap_end == 0)
		heap_end = &end;

	prev_heap_end = heap_end;
	if (heap_end + incr > stack_ptr)
	{
		errno = ENOMEM;
		return (caddr_t) -1;
	}

	heap_end += incr;

	return (caddr_t) prev_heap_end;
}

```

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [October 22, 2024, 11:16am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/4 "2024-10-22T11:16:10Z")

</div>

> [@rgarnett](#):
>
> I don’t understand your second suggestion about the linker script.

Here is good post explaining that - [c++ - How to wrap functions with the `--wrap` option correctly? - Stack Overflow](https://stackoverflow.com/questions/46444052/how-to-wrap-functions-with-the-wrap-option-correctly).

> [@rgarnett](#):
>
> The sysmem.c auto generated file has the following \_sbrk code:

Try using the following -

```auto
/* Includes */
#include <errno.h>
#include <stdio.h>

#include <sys/types.h> // Added as a workaround for Bugzilla 158966

/* Variables */
extern int errno;
register char * stack_ptr asm("msp"); // <-- This is the line I changed.

/* Functions */

/**
 _sbrk
 Increase program data space. Malloc and related functions depend on this
**/
caddr_t _sbrk(int incr)
{
	extern char end asm("end");
	static char *heap_end;
	char *prev_heap_end;

	if (heap_end == 0)
		heap_end = &end;

	prev_heap_end = heap_end;
	if (heap_end + incr > stack_ptr)
	{
		errno = ENOMEM;
		return (caddr_t) -1;
	}

	heap_end += incr;

	return (caddr_t) prev_heap_end;
}

```

---

<div class="post-metadata">

**Author:** ![rgarnett](https://avatars.discourse-cdn.com/v4/letter/r/779978/32.png) [@rgarnett](https://forums.freertos.org/u/rgarnett)\
**Post date:** [October 22, 2024, 1:42pm UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/5 "2024-10-22T13:42:34Z")

</div>

Hi,

Thanks for that I will give it a try.

Regards  
Rob

---

<div class="post-metadata">

**Author:** ![rgarnett](https://avatars.discourse-cdn.com/v4/letter/r/779978/32.png) [@rgarnett](https://forums.freertos.org/u/rgarnett)\
**Post date:** [October 23, 2024, 12:18am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/6 "2024-10-23T00:18:35Z")

</div>

Hi aggarg,

The change to the sbrk fcn didn’t compile:

```auto
**** Building Selected Files of configuration Debug for project STM32H750B-DK 
Info: Internal Builder is used for build
arm-none-eabi-gcc "...
"Application\\User\\sysmem.o" 
..\Application\User\sysmem.c:57:17: error: invalid register name for 'stack_ptr'
   57 | register char * stack_ptr asm("msp");
      | ^ ~~~~~~~~
11:12:43 Build Failed. 1 errors, 0 warnings. (took 633ms)

```

It didn’t like the register name _“msp”_.

Don’t you hate computers!

Regards  
Rob

```auto
/* Includes */

#include <errno.h>

#include <stdio.h>

#include <sys/types.h> // Added as a workaround for Bugzilla 158966

/* Variables */

extern int errno;

register char * stack_ptr asm("msp");

/* Functions */

/**

_sbrk

Increase program data space. Malloc and related functions depend on this

**/

caddr_t _sbrk(int incr)

{

extern char end asm("end");

static char *heap_end;

char *prev_heap_end;

if (heap_end == 0)

heap_end = &end;

prev_heap_end = heap_end;

if (heap_end + incr > stack_ptr)

{

errno = ENOMEM;

return (caddr_t) -1;

}

heap_end += incr;

return (caddr_t) prev_heap_end;

}

```

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [October 23, 2024, 5:28am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/7 "2024-10-23T05:28:03Z")

</div>

Apologies. Try this -

```auto
/* Includes */
#include <errno.h>
#include <stdio.h>

#include <sys/types.h> // Added as a workaround for Bugzilla 158966

/* Variables */
extern int errno;

/* Functions */

/**
 _sbrk
 Increase program data space. Malloc and related functions depend on this
**/
caddr_t _sbrk(int incr)
{
	extern char end asm("end");
	static char *heap_end;
	char *prev_heap_end;
	char * stack_ptr;

	if (heap_end == 0)
		heap_end = &end;

	__asm volatile ("MRS %0, msp" : "=r" (stack_ptr) );

	prev_heap_end = heap_end;
	if (heap_end + incr > stack_ptr)
	{
		errno = ENOMEM;
		return (caddr_t) -1;
	}

	heap_end += incr;

	return (caddr_t) prev_heap_end;
}

```

Also, which version of STM32CubeIDE did you use to generate this project? The version 1.14.0 seems to generate \_sbrk which does not use stack pointer and therefore, would not have this issue.

---

<div class="post-metadata">

**Author:** ![rgarnett](https://avatars.discourse-cdn.com/v4/letter/r/779978/32.png) [@rgarnett](https://forums.freertos.org/u/rgarnett)\
**Post date:** [October 24, 2024, 1:50am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/8 "2024-10-24T01:50:29Z")

</div>

Hi aggard,

I generated the project using the TouchGFX builder I think it uses 6.12.0 but I’m not sure. The updates for all ST’s tools come thick and fast so it is hard for me, (and I think them) to keep up.

I will give your sugggestion a try. I am in the middle of doing another “clean” buld using TouchGFX as I have butchered my previous attemp.

Regards  
Rob

---

<div class="post-metadata">

**Author:** ![funky23](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/funky23/32/5640_2.png) [@funky23](https://forums.freertos.org/u/funky23)\
**Post date:** [October 28, 2024, 10:46am UTC](https://forums.freertos.org/t/lwip-stdlib-rand-function-failing/21684/9 "2024-10-28T10:46:22Z")

</div>

or you maybe could try this:

put it in a source file into your project and overwrite the normal malloc/new functions

i had crashes when i used the STL and some containers malloced memory in my tasks. it came to obscure crashes. with this i could fix it.

but to be honest: after reading the sbrk stuff here i’m not quite sure if it was just by coincidence and if this is realy the suggested way to handle the dynamic memory

```auto
#include "FreeRTOS.h"

static uint32_t u32_totalAllocated = 0;

void *operator new( size_t size )
{
  u32_totalAllocated += size;
  //log_debug( "Mem::new %.3d total allocated: %d", size, u32_totalAllocated );
  return pvPortMalloc( size );
}

void *operator new[]( size_t size )
{
  //log_debug( "Mem::new[] %.3d total allocated: %d", size, u32_totalAllocated );
  return pvPortMalloc( size );
}

void operator delete( void *ptr )
{
  // log_debug("delete");
  vPortFree( ptr );
}

void operator delete[]( void *ptr )
{
  // log_debug("delete[]");
  vPortFree( ptr );
}

```
