/**
  * Attempt to allocate a given amount of memory from any of our configured heap areas.
  *
  * @param size The amount of memory, in bytes, to allocate.
  *
  * @return A pointer to the allocated memory, or NULL if insufficient memory is available.
  */
void *microbit_malloc(size_t size)
{
    void *p;

    // Assign the memory from the first heap created that has space.
    for (int i=0; i < heap_count; i++)
    {
        p = microbit_malloc(size, heap[i]);
        if (p != NULL)
        {
#if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG)
            if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_malloc: ALLOCATED: %d [%p]\n", size, p);
#endif
            return p;
        }
    }

    // If we reach here, then either we have no memory available, or our heap spaces
    // haven't been initialised. Either way, we try the native allocator.

    p = native_malloc(size);
    if (p != NULL)
    {
#if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG)
        // Keep everything trasparent if we've not been initialised yet
        if (heap_count > 0)
            if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_malloc: NATIVE ALLOCATED: %d [%p]\n", size, p);
#endif
        return p;
    }

    // We're totally out of options (and memory!).
#if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG)
    // Keep everything transparent if we've not been initialised yet
    if (heap_count > 0)
        if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_malloc: OUT OF MEMORY [%d]\n", size);
#endif

#if CONFIG_ENABLED(MICROBIT_PANIC_HEAP_FULL)
	microbit_panic(MICROBIT_OOM);
#endif

    return NULL;
}
/**
 * Poll to see if new data is available from the hardware. If so, update it.
 * n.b. it is not necessary to explicitly call this funciton to update data
 * (it normally happens in the background when the scheduler is idle), but a check is performed
 * if the user explicitly requests up to date data.
 *
 * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the update fails.
 *
 * @note This method should be overidden by the hardware driver to implement the requested
 * changes in hardware.
 */
int MicroBitAccelerometer::requestUpdate()
{
    microbit_panic(MICROBIT_HARDWARE_UNAVAILABLE_ACC);
    return MICROBIT_NOT_SUPPORTED;
}