简体   繁体   中英

Cannot use malloc in Contiki

I am trying to write a simple program using the Contiki-ng operating system for IoT platforms. First tests were ok, but something weird happens when trying to allocate dynamic memory. The test code I'm using is the following:

#include "contiki.h"

#include <stdio.h>
#include <stdlib.h>

PROCESS(main_process, "main_process");

AUTOSTART_PROCESSES(&main_process);

PROCESS_THREAD(main_process, ev, data) {
    uint8_t *nonce;
    int i;

    PROCESS_BEGIN();

    nonce = (uint8_t *) malloc(32 * sizeof(uint8_t));
    if (nonce != NULL) {
        for (i = 0; i < 32; i++)
            nonce[i] = 0;

        printf("Todo OK\n");
    } else {
        printf("Todo mal\n");
    }

    PROCESS_END();
}

When building the project, an error rises stating that " In funtion _sbrk_r: undefined reference to _sbrk ". After looking some forums on internet, I managed to solve this problem by including the following line into the Makefile of the project:

MODULES += os/lib/newlib

This solves the problem because inside the path os/lib/newlib there is a file, syscalls.c, which implements the mentioned _sbrk function. However, the following error rises now:

在此处输入图片说明

I have not found anyone over the internet with the same problem, so I got stuck here. Additionally, I don't know why but since then, removing the line "MODULES += os/lib/newlib" from the Makefile does nothing, and the problem with _eheap and _heap persists without returning to the undefined _sbrk error. However, I believe that this weird error is due to something wrong with Eclipse IDE cleaning the project. The code from syscalls.c, if needed, is the following:

#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
/*---------------------------------------------------------------------------*/
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
/*---------------------------------------------------------------------------*/
/**
 * \brief Enlarges the allocated heap space
 * \param incr Number of bytes by which to increase the heap space
 * \return The previous end of heap on success (which is also a pointer to the
 *         start of the newly allocated memory if \p incr is positive), or
 *         <tt>(caddr_t)-1</tt> with \c errno set to \c ENOMEM on error
 */
caddr_t
_sbrk(int incr)
{
  /*
   * Newlib's _sbrk_r() assumes that this global errno variable is used here,
   * which is different from the errno definition provided by <errno.h>.
   */
#undef errno
  extern int errno;

  /* Heap boundaries from linker script. */
  extern uint8_t _heap;
  extern uint8_t _eheap;

  static uint8_t *heap_end = &_heap;
  uint8_t *prev_heap_end = heap_end;

  if(heap_end + incr > &_eheap) {
    PRINTF("Out of heap space!\n");
    errno = ENOMEM;
    return (caddr_t)-1;
  }

  heap_end += incr;
  return (caddr_t)prev_heap_end;
}

I hope someone could help me. I have read that Contiki gives more ways of using dynamic memory, but I need to do it this way because other parts of the code rely on the use of malloc and cannot be changed.

Thanks.

The short is that you almost certainly don't need and don't want to use malloc() on a Contiki-NG microcontroller. Use Contiki's memb module instead.

The long answer is that you can add the _heap symbol by using a linker script. Check example linker scripts provided by Contiki-NG on how to do that. For example, the script arch/cpu/cc26x0-cc13x0/cc26xx.ld (for the cc26x0-cc13x0 platform) places _heap immediately after the BSS segment:

.bss :
{
    /* ... */
} > SRAM

_end = .;  /* End of the .bss segment. */
/* ... */
_stack = .;
_heap = _stack;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM