コード例 #1
0
ファイル: thread.c プロジェクト: rsalveti/zephyr
/*
 * @brief Initialize a new thread from its stack space
 *
 * The thread control structure is put at the lower address of the stack. An
 * initial context, to be "restored" by __return_from_coop(), is put at
 * the other end of the stack, and thus reusable by the stack when not
 * needed anymore.
 *
 * The initial context is a basic stack frame that contains arguments for
 * _thread_entry() return address, that points at _thread_entry()
 * and status register.
 *
 * <options> is currently unused.
 *
 * @param pStackmem the pointer to aligned stack memory
 * @param stackSize the stack size in bytes
 * @param pEntry thread entry point routine
 * @param parameter1 first param to entry point
 * @param parameter2 second param to entry point
 * @param parameter3 third param to entry point
 * @param priority thread priority
 * @param options thread options: K_ESSENTIAL
 *
 * @return N/A
 */
void _new_thread(struct k_thread *thread, k_thread_stack_t stack,
		 size_t stackSize, _thread_entry_t pEntry,
		 void *parameter1, void *parameter2, void *parameter3,
		 int priority, unsigned int options)
{
	char *pStackMem = K_THREAD_STACK_BUFFER(stack);
	_ASSERT_VALID_PRIO(priority, pEntry);

	char *stackEnd = pStackMem + stackSize;
	struct init_stack_frame *pInitCtx;

	_new_thread_init(thread, pStackMem, stackSize, priority, options);

	/* carve the thread entry struct from the "base" of the stack */
	pInitCtx = (struct init_stack_frame *)(STACK_ROUND_DOWN(stackEnd) -
				       sizeof(struct init_stack_frame));

	pInitCtx->pc = ((u32_t)_thread_entry_wrapper);
	pInitCtx->r0 = (u32_t)pEntry;
	pInitCtx->r1 = (u32_t)parameter1;
	pInitCtx->r2 = (u32_t)parameter2;
	pInitCtx->r3 = (u32_t)parameter3;
	/*
	 * For now set the interrupt priority to 15
	 * we can leave interrupt enable flag set to 0 as
	 * seti instruction in the end of the _Swap() will
	 * enable the interrupts based on intlock_key
	 * value.
	 */
#ifdef CONFIG_ARC_STACK_CHECKING
	pInitCtx->status32 = _ARC_V2_STATUS32_SC | _ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL);
	thread->arch.stack_base = (u32_t) stackEnd;
#else
	pInitCtx->status32 = _ARC_V2_STATUS32_E(_ARC_V2_DEF_IRQ_LEVEL);
#endif

#ifdef CONFIG_THREAD_MONITOR
	/*
	 * In debug mode thread->entry give direct access to the thread entry
	 * and the corresponding parameters.
	 */
	thread->entry = (struct __thread_entry *)(pInitCtx);
#endif

	/*
	 * intlock_key is constructed based on ARCv2 ISA Programmer's
	 * Reference Manual CLRI instruction description:
	 * dst[31:6] dst[5] dst[4]       dst[3:0]
	 *    26'd0    1    STATUS32.IE  STATUS32.E[3:0]
	 */
	thread->arch.intlock_key = 0x3F;
	thread->arch.relinquish_cause = _CAUSE_COOP;
	thread->callee_saved.sp =
		(u32_t)pInitCtx - ___callee_saved_stack_t_SIZEOF;

	/* initial values in all other regs/k_thread entries are irrelevant */

	thread_monitor_init(thread);
}
コード例 #2
0
ファイル: thread.c プロジェクト: zmole945/zephyr
void _new_thread(struct k_thread *thread, k_thread_stack_t *stack,
		 size_t stack_size, k_thread_entry_t thread_func,
		 void *arg1, void *arg2, void *arg3,
		 int priority, unsigned int options)
{
	char *stack_memory = K_THREAD_STACK_BUFFER(stack);
	_ASSERT_VALID_PRIO(priority, thread_func);

	struct __esf *stack_init;

	_new_thread_init(thread, stack_memory, stack_size, priority, options);

	/* Initial stack frame for thread */
	stack_init = (struct __esf *)
		STACK_ROUND_DOWN(stack_memory +
				 stack_size - sizeof(struct __esf));

	/* Setup the initial stack frame */
	stack_init->a0 = (u32_t)thread_func;
	stack_init->a1 = (u32_t)arg1;
	stack_init->a2 = (u32_t)arg2;
	stack_init->a3 = (u32_t)arg3;
	/*
	 * Following the RISC-V architecture,
	 * the MSTATUS register (used to globally enable/disable interrupt),
	 * as well as the MEPC register (used to by the core to save the
	 * value of the program counter at which an interrupt/exception occcurs)
	 * need to be saved on the stack, upon an interrupt/exception
	 * and restored prior to returning from the interrupt/exception.
	 * This shall allow to handle nested interrupts.
	 *
	 * Given that context switching is performed via a system call exception
	 * within the RISCV32 architecture implementation, initially set:
	 * 1) MSTATUS to SOC_MSTATUS_DEF_RESTORE in the thread stack to enable
	 *    interrupts when the newly created thread will be scheduled;
	 * 2) MEPC to the address of the _thread_entry_wrapper in the thread
	 *    stack.
	 * Hence, when going out of an interrupt/exception/context-switch,
	 * after scheduling the newly created thread:
	 * 1) interrupts will be enabled, as the MSTATUS register will be
	 *    restored following the MSTATUS value set within the thread stack;
	 * 2) the core will jump to _thread_entry_wrapper, as the program
	 *    counter will be restored following the MEPC value set within the
	 *    thread stack.
	 */
	stack_init->mstatus = SOC_MSTATUS_DEF_RESTORE;
	stack_init->mepc = (u32_t)_thread_entry_wrapper;

	thread->callee_saved.sp = (u32_t)stack_init;

	thread_monitor_init(thread);
}
コード例 #3
0
ファイル: thread.c プロジェクト: zmole945/zephyr
/**
 * @brief Create a new kernel execution thread
 *
 * Initializes the k_thread object and sets up initial stack frame.
 *
 * @param thread pointer to thread struct memory, including any space needed
 *		for extra coprocessor context
 * @param stack the pointer to aligned stack memory
 * @param stack_size the stack size in bytes
 * @param entry thread entry point routine
 * @param arg1 first param to entry point
 * @param arg2 second param to entry point
 * @param arg3 third param to entry point
 * @param priority thread priority
 * @param options thread options: K_ESSENTIAL, K_FP_REGS, K_SSE_REGS
 *
 * Note that in this arch we cheat quite a bit: we use as stack a normal
 * pthreads stack and therefore we ignore the stack size
 *
 */
void _new_thread(struct k_thread *thread, k_thread_stack_t *stack,
		size_t stack_size, k_thread_entry_t thread_func,
		void *arg1, void *arg2, void *arg3,
		int priority, unsigned int options)
{

	char *stack_memory = K_THREAD_STACK_BUFFER(stack);

	_ASSERT_VALID_PRIO(priority, thread_func);

	posix_thread_status_t *thread_status;

	_new_thread_init(thread, stack_memory, stack_size, priority, options);

	/* We store it in the same place where normal archs store the
	 * "initial stack frame"
	 */
	thread_status = (posix_thread_status_t *)
		STACK_ROUND_DOWN(stack_memory + stack_size
				- sizeof(*thread_status));

	/* _thread_entry() arguments */
	thread_status->entry_point = thread_func;
	thread_status->arg1 = arg1;
	thread_status->arg2 = arg2;
	thread_status->arg3 = arg3;
#if defined(CONFIG_ARCH_HAS_THREAD_ABORT)
	thread_status->aborted = 0;
#endif

	thread->callee_saved.thread_status = (u32_t)thread_status;


	posix_new_thread(thread_status);

	thread_monitor_init(thread);
}
コード例 #4
0
ファイル: thread.c プロジェクト: rsalveti/zephyr
void _new_thread(struct k_thread *thread, k_thread_stack_t stack,
		size_t stackSize,
		void (*pEntry)(void *, void *, void *),
		void *p1, void *p2, void *p3,
		int priority, unsigned int options)
{
	char *pStack = K_THREAD_STACK_BUFFER(stack);

	/* Align stack end to maximum alignment requirement. */
	char *stackEnd = (char *)ROUND_DOWN(pStack + stackSize, 16);
#if XCHAL_CP_NUM > 0
	u32_t *cpSA;
	char *cpStack;
#endif

	_new_thread_init(thread, pStack, stackSize, priority, options);

#ifdef CONFIG_DEBUG
	printk("\nstackPtr = %p, stackSize = %d\n", pStack, stackSize);
	printk("stackEnd = %p\n", stackEnd);
#endif
#if XCHAL_CP_NUM > 0
	/* Ensure CP state descriptor is correctly initialized */
	cpStack = thread->arch.preempCoprocReg.cpStack; /* short hand alias */
	memset(cpStack, 0, XT_CP_ASA); /* Set to zero to avoid bad surprises */
	/* Coprocessor's stack is allocated just after the k_thread */
	cpSA = (u32_t *)(thread->arch.preempCoprocReg.cpStack + XT_CP_ASA);
	/* Coprocessor's save area alignment is at leat 16 bytes */
	*cpSA = ROUND_UP(cpSA + 1,
		(XCHAL_TOTAL_SA_ALIGN < 16 ? 16 : XCHAL_TOTAL_SA_ALIGN));
#ifdef CONFIG_DEBUG
	printk("cpStack  = %p\n", thread->arch.preempCoprocReg.cpStack);
	printk("cpAsa    = %p\n",
	       *(void **)(thread->arch.preempCoprocReg.cpStack + XT_CP_ASA));
#endif
#endif
	/* Thread's first frame alignment is granted as both operands are
	 * aligned
	 */
	XtExcFrame *pInitCtx =
		(XtExcFrame *)(stackEnd - (XT_XTRA_SIZE - XT_CP_SIZE));
#ifdef CONFIG_DEBUG
	printk("pInitCtx = %p\n", pInitCtx);
#endif
	/* Explicitly initialize certain saved registers */

	 /* task entrypoint */
	pInitCtx->pc   = (u32_t)_thread_entry;

	/* physical top of stack frame */
	pInitCtx->a1   = (u32_t)pInitCtx + XT_STK_FRMSZ;

	/* user exception exit dispatcher */
	pInitCtx->exit = (u32_t)_xt_user_exit;

	/* Set initial PS to int level 0, EXCM disabled, user mode.
	 * Also set entry point argument arg.
	 */
#ifdef __XTENSA_CALL0_ABI__
	pInitCtx->a2 = (u32_t)pEntry;
	pInitCtx->a3 = (u32_t)p1;
	pInitCtx->a4 = (u32_t)p2;
	pInitCtx->a5 = (u32_t)p3;
	pInitCtx->ps = PS_UM | PS_EXCM;
#else
	/* For windowed ABI set also WOE and CALLINC
	 * (pretend task is 'call4')
	 */
	pInitCtx->a6 = (u32_t)pEntry;
	pInitCtx->a7 = (u32_t)p1;
	pInitCtx->a8 = (u32_t)p2;
	pInitCtx->a9 = (u32_t)p3;
	pInitCtx->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
#endif
	thread->callee_saved.topOfStack = pInitCtx;
	thread->arch.flags = 0;
#ifdef CONFIG_THREAD_MONITOR
	/*
	 * In debug mode thread->entry give direct access to the thread entry
	 * and the corresponding parameters.
	 */
	thread->entry = (struct __thread_entry *)(pInitCtx);
#endif
	/* initial values in all other registers/k_thread entries are
	 * irrelevant
	 */

	thread_monitor_init(thread);
}
コード例 #5
0
ファイル: ieee802154_nrf5.c プロジェクト: rsalveti/zephyr
static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3)
{
	struct device *dev = (struct device *)arg1;
	struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
	struct net_buf *frag = NULL;
	enum net_verdict ack_result;
	struct net_pkt *pkt;
	u8_t pkt_len;

	ARG_UNUSED(arg2);
	ARG_UNUSED(arg3);

	while (1) {
		pkt = NULL;

		SYS_LOG_DBG("Waiting for frame");
		k_sem_take(&nrf5_radio->rx_wait, K_FOREVER);

		SYS_LOG_DBG("Frame received");

		pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT);
		if (!pkt) {
			SYS_LOG_ERR("No pkt available");
			goto out;
		}

#if defined(CONFIG_IEEE802154_NRF5_RAW)
		/**
		 * Reserve 1 byte for length
		 */
		net_pkt_set_ll_reserve(pkt, 1);
#endif

		frag = net_pkt_get_frag(pkt, K_NO_WAIT);
		if (!frag) {
			SYS_LOG_ERR("No frag available");
			goto out;
		}

		net_pkt_frag_insert(pkt, frag);

		/* rx_mpdu contains length, psdu, fcs|lqi
		 * The last 2 bytes contain LQI or FCS, depending if
		 * automatic CRC handling is enabled or not, respectively.
		 */
#if defined(CONFIG_IEEE802154_NRF5_RAW)
		pkt_len = nrf5_radio->rx_psdu[0];
#else
		pkt_len = nrf5_radio->rx_psdu[0] -  NRF5_FCS_LENGTH;
#endif

		/* Skip length (first byte) and copy the payload */
		memcpy(frag->data, nrf5_radio->rx_psdu + 1, pkt_len);
		net_buf_add(frag, pkt_len);

		nrf_drv_radio802154_buffer_free(nrf5_radio->rx_psdu);

		ack_result = ieee802154_radio_handle_ack(nrf5_radio->iface,
							 pkt);
		if (ack_result == NET_OK) {
			SYS_LOG_DBG("ACK packet handled");
			goto out;
		}

		SYS_LOG_DBG("Caught a packet (%u) (LQI: %u)",
			    pkt_len, nrf5_radio->lqi);

		if (net_recv_data(nrf5_radio->iface, pkt) < 0) {
			SYS_LOG_DBG("Packet dropped by NET stack");
			goto out;
		}

		net_analyze_stack("nRF5 rx stack",
				  K_THREAD_STACK_BUFFER(nrf5_radio->rx_stack),
				  K_THREAD_STACK_SIZEOF(nrf5_radio->rx_stack));
		continue;

out:
		if (pkt) {
			net_pkt_unref(pkt);
		}
	}
}