/** * @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); }
/** * @brief Initializes the kernel. * @details Initializes the kernel structures, the current instructions flow * becomes the idle thread upon return. The idle thread must not * invoke any kernel primitive able to change state to not runnable. * @note This function assumes that the @p nil global variable has been * zeroed by the runtime environment. If this is not the case then * make sure to clear it before calling this function. * * @special */ void chSysInit(void) { thread_t *tp; const thread_config_t *tcp; #if CH_DBG_SYSTEM_STATE_CHECK == TRUE nil.isr_cnt = (cnt_t)0; nil.lock_cnt = (cnt_t)0; #endif /* System initialization hook.*/ CH_CFG_SYSTEM_INIT_HOOK(); /* Iterates through the list of defined threads.*/ tp = &nil.threads[0]; tcp = nil_thd_configs; while (tp < &nil.threads[CH_CFG_NUM_THREADS]) { #if CH_DBG_ENABLE_STACK_CHECK tp->stklimit = (stkalign_t *)tcp->wbase; #endif /* Port dependent thread initialization.*/ PORT_SETUP_CONTEXT(tp, tcp->wbase, tcp->wend, tcp->funcp, tcp->arg); /* Initialization hook.*/ CH_CFG_THREAD_EXT_INIT_HOOK(tp); tp++; tcp++; } #if CH_DBG_ENABLE_STACK_CHECK /* The idle thread is a special case because its stack is set up by the runtime environment.*/ tp->stklimit = THD_IDLE_BASE; #endif /* Interrupts partially enabled. It is equivalent to entering the kernel critical zone.*/ chSysSuspend(); #if CH_DBG_SYSTEM_STATE_CHECK == TRUE nil.lock_cnt = (cnt_t)1; #endif /* Heap initialization, if enabled.*/ #if CH_CFG_USE_HEAP == TRUE _heap_init(); #endif /* Port layer initialization last because it depend on some of the initializations performed before.*/ port_init(); /* Runs the highest priority thread, the current one becomes the idle thread.*/ nil.current = nil.next = nil.threads; port_switch(nil.current, tp); chSysUnlock(); }
/** * @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] 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. * * @iclass */ thread_t *chThdCreateI(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) { /* The thread structure is laid out in the lower part of the thread workspace.*/ thread_t *tp = wsp; chDbgCheckClassI(); chDbgCheck((wsp != NULL) && (size >= THD_WORKING_AREA_SIZE(0)) && (prio <= HIGHPRIO) && (pf != NULL)); PORT_SETUP_CONTEXT(tp, wsp, size, pf, arg); return _thread_init(tp, prio); }
/** * @brief Initializes the kernel. * @details Initializes the kernel structures, the current instructions flow * becomes the idle thread upon return. The idle thread must not * invoke any kernel primitive able to change state to not runnable. * @note This function assumes that the @p nil global variable has been * zeroed by the runtime environment. If this is not the case then * make sure to clear it before calling this function. * * @special */ void chSysInit(void) { thread_t *tp; const thread_config_t *tcp; /* Port layer initialization.*/ port_init(); /* System initialization hook.*/ NIL_CFG_SYSTEM_INIT_HOOK(); /* Iterates through the list of defined threads.*/ tp = &nil.threads[0]; tcp = nil_thd_configs; while (tp < &nil.threads[NIL_CFG_NUM_THREADS]) { #if NIL_CFG_ENABLE_STACK_CHECK tp->stklim = (stkalign_t *)tcp->wbase; #endif /* Port dependent thread initialization.*/ PORT_SETUP_CONTEXT(tp, tcp->wend, tcp->funcp, tcp->arg); /* Initialization hook.*/ NIL_CFG_THREAD_EXT_INIT_HOOK(tp); tp++; tcp++; } #if NIL_CFG_ENABLE_STACK_CHECK /* The idle thread is a special case because its stack is set up by the runtime environment.*/ tp->stklim = THD_IDLE_BASE; #endif /* Runs the highest priority thread, the current one becomes the null thread.*/ nil.current = nil.next = nil.threads; port_switch(nil.current, tp); /* Interrupts enabled for the idle thread.*/ chSysEnable(); }
/** * @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; }