예제 #1
0
/**
 * @brief   Low level memory manager initialization.
 *
 * @notapi
 */
void _core_init(void) {
#if CH_MEMCORE_SIZE == 0
  extern uint8_t __heap_base__[];
  extern uint8_t __heap_end__[];
  nextmem = (uint8_t *)MEM_ALIGN_NEXT(__heap_base__);
  endmem = (uint8_t *)MEM_ALIGN_PREV(__heap_end__);
#else
  static stkalign_t buffer[MEM_ALIGN_NEXT(CH_MEMCORE_SIZE)/MEM_ALIGN_SIZE];
  nextmem = (uint8_t *)&buffer[0];
  endmem = (uint8_t *)&buffer[MEM_ALIGN_NEXT(CH_MEMCORE_SIZE)/MEM_ALIGN_SIZE];
#endif
}
예제 #2
0
파일: chthreads.c 프로젝트: sdalu/ChibiOS
/**
 * @brief   Creates a new thread into a static memory area.
 * @details The new thread is initialized but not inserted in the ready list,
 *          the initial state is @p CH_STATE_WTSTART.
 * @post    The initialized thread can be subsequently started by invoking
 *          @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
 *          depending on the execution context.
 * @note    A thread can terminate by calling @p chThdExit() or by simply
 *          returning from its main function.
 * @note    Threads created using this function do not obey to the
 *          @p CH_DBG_FILL_THREADS debug option because it would keep
 *          the kernel locked for too much time.
 *
 * @param[out] tdp      pointer to the thread descriptor
 * @return              The pointer to the @p thread_t structure allocated for
 *                      the thread into the working space area.
 *
 * @iclass
 */
thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) {
  thread_t *tp;

  chDbgCheckClassI();
  chDbgCheck(tdp != NULL);
  chDbgCheck(MEM_IS_ALIGNED(tdp->wbase, PORT_WORKING_AREA_ALIGN) &&
             MEM_IS_ALIGNED(tdp->wend, PORT_STACK_ALIGN) &&
             (tdp->wend > tdp->wbase) &&
             ((size_t)((tdp->wend - tdp->wbase) *
                       sizeof (stkalign_t)) >= THD_WORKING_AREA_SIZE(0)));
  chDbgCheck((tdp->prio <= HIGHPRIO) && (tdp->funcp != NULL));

  /* The thread structure is laid out in the upper part of the thread
     workspace. The thread position structure is aligned to the required
     stack alignment because it represents the stack top.*/
  tp = (thread_t *)((uint8_t *)tdp->wend -
                    MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));

  /* Initial state.*/
  tp->state = CH_STATE_WTSTART;

  /* Stack boundary.*/
  tp->stklimit = tdp->wbase;

  /* Setting up the port-dependent part of the working area.*/
  PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg);

  /* The driver object is initialized but not started.*/
  return _thread_init(tp, tdp->name, tdp->prio);
}
예제 #3
0
void chCoreGrowI(size_t size) {

  chDbgCheckClassI();
  size = MEM_ALIGN_NEXT(size);
  chDbgCheck(endmem + size <= realendmem, "chCoreGrowI");
  endmem += size;
}
/**
 * @brief   Initializes an empty memory pool.
 * @note    The size is internally aligned to be a multiple of the
 *          @p stkalign_t type size.
 *
 * @param[out] mp       pointer to a @p MemoryPool structure
 * @param[in] size      the size of the objects contained in this memory pool,
 *                      the minimum accepted size is the size of a pointer to
 *                      void.
 * @param[in] provider  memory provider function for the memory pool or
 *                      @p NULL if the pool is not allowed to grow
 *                      automatically
 *
 * @init
 */
void chPoolInit(MemoryPool *mp, size_t size, memgetfunc_t provider) {

  chDbgCheck((mp != NULL) && (size >= sizeof(void *)), "chPoolInit");

  mp->mp_next = NULL;
  mp->mp_object_size = MEM_ALIGN_NEXT(size);
  mp->mp_provider = provider;
}
예제 #5
0
/**
 * @brief   Allocates a block of memory from the heap by using the first-fit
 *          algorithm.
 * @details The allocated block is guaranteed to be properly aligned for a
 *          pointer data type (@p stkalign_t).
 *
 * @param[in] heapp     pointer to a heap descriptor or @p NULL in order to
 *                      access the default heap.
 * @param[in] size      the size of the block to be allocated. Note that the
 *                      allocated block may be a bit bigger than the requested
 *                      size for alignment and fragmentation reasons.
 * @return              A pointer to the allocated block.
 * @retval NULL         if the block cannot be allocated.
 *
 * @api
 */
void *chHeapAlloc(memory_heap_t *heapp, size_t size) {
  union heap_header *qp, *hp, *fp;

  if (heapp == NULL) {
    heapp = &default_heap;
  }

  size = MEM_ALIGN_NEXT(size);
  qp = &heapp->h_free;

  H_LOCK(heapp);
  while (qp->h.u.next != NULL) {
    hp = qp->h.u.next;
    if (hp->h.size >= size) {
      if (hp->h.size < (size + sizeof(union heap_header))) {
        /* Gets the whole block even if it is slightly bigger than the
           requested size because the fragment would be too small to be
           useful.*/
        qp->h.u.next = hp->h.u.next;
      }
      else {
        /* Block bigger enough, must split it.*/
        /*lint -save -e9087 [11.3] Safe cast.*/
        fp = (void *)((uint8_t *)(hp) + sizeof(union heap_header) + size);
        /*lint -restore*/
        fp->h.u.next = hp->h.u.next;
        fp->h.size = (hp->h.size - sizeof(union heap_header)) - size;
        qp->h.u.next = fp;
        hp->h.size = size;
      }
      hp->h.u.heap = heapp;
      H_UNLOCK(heapp);

      /*lint -save -e9087 [11.3] Safe cast.*/
      return (void *)(hp + 1);
      /*lint -restore*/
    }
    qp = hp;
  }
  H_UNLOCK(heapp);

  /* More memory is required, tries to get it from the associated provider
     else fails.*/
  if (heapp->h_provider != NULL) {
    hp = heapp->h_provider(size + sizeof(union heap_header));
    if (hp != NULL) {
      hp->h.u.heap = heapp;
      hp->h.size = size;
      hp++;

      /*lint -save -e9087 [11.3] Safe cast.*/
      return (void *)hp;
      /*lint -restore*/
    }
  }

  return NULL;
}
예제 #6
0
/**
 * @brief   Low level memory manager initialization.
 *
 * @notapi
 */
void _core_init(void) {
#if CH_CFG_MEMCORE_SIZE == 0
  extern uint8_t __heap_base__[];
  extern uint8_t __heap_end__[];

  /*lint -save -e9033 [10.8] Required cast operations.*/
  nextmem = (uint8_t *)MEM_ALIGN_NEXT(__heap_base__);
  endmem = (uint8_t *)MEM_ALIGN_PREV(__heap_end__);
  /*lint restore*/
#else
  static stkalign_t buffer[MEM_ALIGN_NEXT(CH_CFG_MEMCORE_SIZE) /
                           MEM_ALIGN_SIZE];

  nextmem = (uint8_t *)&buffer[0];
  endmem = (uint8_t *)&buffer[MEM_ALIGN_NEXT(CH_CFG_MEMCORE_SIZE) /
                              MEM_ALIGN_SIZE];
#endif
}
예제 #7
0
void *chCoreUnreserveI(size_t size) {

  chDbgCheckClassI();

  size = MEM_ALIGN_NEXT(size);
  if ((size_t)(realendmem - endmem) < size)
    return NULL;
  endmem += size;
  return endmem;
}
예제 #8
0
void *chCoreReserveI(size_t size) {

  chDbgCheckClassI();

  size = MEM_ALIGN_NEXT(size);
  if ((size_t)(endmem - nextmem) < size)
    return NULL;
  endmem -= size;
  return endmem;
}
예제 #9
0
/**
 * @brief   Allocates a memory block.
 * @details The size of the returned block is aligned to the alignment
 *          type so it is not possible to allocate less than
 *          <code>MEM_ALIGN_SIZE</code>.
 *
 * @param[in] size      the size of the block to be allocated.
 * @return              A pointer to the allocated memory block.
 * @retval NULL         allocation failed, core memory exhausted.
 *
 * @iclass
 */
void *chCoreAllocI(size_t size) {
  void *p;

  chDbgCheckClassI();

  size = MEM_ALIGN_NEXT(size);
  if ((size_t)(endmem - nextmem) < size)
    return NULL;
  p = nextmem;
  nextmem += size;
  return p;
}
예제 #10
0
/**
 * @brief   Allocates a memory block.
 * @details The size of the returned block is aligned to the alignment
 *          type so it is not possible to allocate less than
 *          <code>MEM_ALIGN_SIZE</code>.
 *
 * @param[in] size      the size of the block to be allocated.
 * @return              A pointer to the allocated memory block.
 * @retval NULL         allocation failed, core memory exhausted.
 *
 * @iclass
 */
void *chCoreAllocI(size_t size) {
  void *p;

  chDbgCheckClassI();

  size = MEM_ALIGN_NEXT(size);
  /*lint -save -e9033 [10.8] The cast is safe.*/
  if ((size_t)(endmem - nextmem) < size) {
  /*lint -restore*/
    return NULL;
  }
  p = nextmem;
  nextmem += size;

  return p;
}
예제 #11
0
파일: chthreads.c 프로젝트: sdalu/ChibiOS
/**
 * @brief   Creates a new thread into a static memory area.
 * @note    A thread can terminate by calling @p chThdExit() or by simply
 *          returning from its main function.
 *
 * @param[out] wsp      pointer to a working area dedicated to the thread stack
 * @param[in] size      size of the working area
 * @param[in] prio      the priority level for the new thread
 * @param[in] pf        the thread function
 * @param[in] arg       an argument passed to the thread function. It can be
 *                      @p NULL.
 * @return              The pointer to the @p thread_t structure allocated for
 *                      the thread into the working space area.
 *
 * @api
 */
thread_t *chThdCreateStatic(void *wsp, size_t size,
                            tprio_t prio, tfunc_t pf, void *arg) {
  thread_t *tp;

  chDbgCheck((wsp != NULL) &&
             MEM_IS_ALIGNED(wsp, PORT_WORKING_AREA_ALIGN) &&
             (size >= THD_WORKING_AREA_SIZE(0)) &&
             MEM_IS_ALIGNED(size, PORT_STACK_ALIGN) &&
             (prio <= HIGHPRIO) && (pf != NULL));

#if CH_DBG_FILL_THREADS == TRUE
  _thread_memfill((uint8_t *)wsp,
                  (uint8_t *)wsp + size,
                  CH_DBG_STACK_FILL_VALUE);
#endif

  chSysLock();

  /* The thread structure is laid out in the upper part of the thread
     workspace. The thread position structure is aligned to the required
     stack alignment because it represents the stack top.*/
  tp = (thread_t *)((uint8_t *)wsp + size -
                    MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));

  /* Stack boundary.*/
  tp->stklimit = (stkalign_t *)wsp;

  /* Setting up the port-dependent part of the working area.*/
  PORT_SETUP_CONTEXT(tp, wsp, tp, pf, arg);

  tp = _thread_init(tp, "noname", prio);

  /* Starting the thread immediately.*/
  chSchWakeupS(tp, MSG_OK);
  chSysUnlock();

  return tp;
}