Esempio n. 1
0
int main(int argc, char ** argv)
{
	struct vcom vcom;
	int i = 0;

	DCC_LOG_CONNECT();
	DCC_LOG_INIT();

	thinkos_init(THINKOS_OPT_PRIORITY(0) | THINKOS_OPT_ID(0));

	vcom.usb = usb_cdc_init();
	vcom.serial = serial_init(stm32f_uart5);

	thinkos_thread_create((void *)usb_recv_task, (void *)&vcom,
						  usb_recv_stack, STACK_SIZE, 0);

	thinkos_thread_create((void *)usb_ctrl_task, (void *)&vcom,
						  usb_ctrl_stack, STACK_SIZE, 0);

	thinkos_thread_create((void *)serial_recv_task, (void *)&vcom,
						  serial_recv_stack, STACK_SIZE, 0);

	thinkos_thread_create((void *)serial_ctrl_task, (void *)&vcom,
						  serial_ctrl_stack, STACK_SIZE, 0);

	for (i = 0; ;i++) {
		thinkos_sleep(10000);
	}

	return 0;
}
Esempio n. 2
0
int main(int argc, char ** argv)
{
	uint32_t * uid = STM32F_UID;
	int i = 0;

	DCC_LOG_INIT();
	DCC_LOG_CONNECT();

	/* calibrate usecond delay loop */
	cm3_udelay_calibrate();

	DCC_LOG(LOG_TRACE, "1. io_init()");
	io_init();

	DCC_LOG(LOG_TRACE, "2. leds_init()");
	leds_init();

	DCC_LOG(LOG_TRACE, "3. stdio_init()");
	stdio_init();

	printf("\n\n");
	printf("-----------------------------------------\n");
	printf(" RS485 token ring network test\n");
	printf("-----------------------------------------\n");
	printf("\n");

	DCC_LOG(LOG_TRACE, "4. thinkos_init()");
	thinkos_init(THINKOS_OPT_PRIORITY(0) | THINKOS_OPT_ID(32));

	DCC_LOG(LOG_TRACE, "5. net_init()");
	net_init();

	thinkos_thread_create((void *)supervisor_task, (void *)NULL,
						  supervisor_stack, sizeof(supervisor_stack), 
						  THINKOS_OPT_PRIORITY(0) | THINKOS_OPT_ID(0));

	thinkos_thread_create((void *)tx_task, (void *)NULL,
						  tx_stack, sizeof(tx_stack), 
						  THINKOS_OPT_PRIORITY(1) | THINKOS_OPT_ID(1));

	thinkos_thread_create((void *)rx_task, (void *)NULL,
						  rx_stack, sizeof(rx_stack), 
						  THINKOS_OPT_PRIORITY(2) | THINKOS_OPT_ID(2));


	printf("UID=%08x:%08x:%08x\n", uid[2], uid[1], uid[0]);
	DCC_LOG3(LOG_TRACE, "UID=%08x:%08x:%08x", uid[2], uid[1], uid[0]);

	for (i = 0; ; ++i) {
		thinkos_sleep(1000);
	}

	return 0;
}
Esempio n. 3
0
void semaphore_test(void)
{
	int producer_th;
	int consumer_th;
	int producer_ret;
	int consumer_ret;

	/* allocate the empty signal semaphores */
	/* initialize the empty as 1 so we can insert an item immediately. */
	sem_empty = thinkos_sem_alloc(1); 

	/* allocate the full signal semaphores */
	/* initialize the full as 0 as we don't have produced anything yet. */
	sem_full = thinkos_sem_alloc(0); 

	/* create the producer thread */
	producer_th = thinkos_thread_create(producer_task, NULL, 
			producer_stack, sizeof(producer_stack));

	/* create the consuer thread */
	consumer_th = thinkos_thread_create(consumer_task, NULL, 
			consumer_stack, sizeof(consumer_stack));

	printf(" * Empty semaphore: %d\n", sem_empty);
	printf(" * Full semaphore: %d\n", sem_full);
	printf(" * Producer thread: %d\n", producer_th);
	printf(" * Consumer thread: %d\n", consumer_th);
	printf("\n");
	thinkos_sleep(100);

	/* number of items to be produced */
	prod_count = 100;

	/* wait for the production thread to finish */
	producer_ret = thinkos_join(producer_th);

	/* wait for the consumer thread to finish */
	consumer_ret = thinkos_join(consumer_th);

	printf(" * Production return = %d\n", producer_ret);
	printf(" * Consumer return = %d\n", consumer_ret);

	/* release the semaphores */
	thinkos_sem_free(sem_empty);
	thinkos_sem_free(sem_full);

	printf("\n");
};
Esempio n. 4
0
void watchdog_init(void)
{

	thinkos_thread_create((void *)watchdog_task, (void *)NULL,
						  watchdog_stack, sizeof(watchdog_stack) |
						  THINKOS_OPT_PRIORITY(0) | THINKOS_OPT_ID(0));
}
Esempio n. 5
0
void monitor_init(void)
{
	monitor_stream = stdout;
	monitor_auto_flush = false;

	thinkos_thread_create((void *)monitor_task, (void *)NULL,
						  monitor_stack, sizeof(monitor_stack) |
						  THINKOS_OPT_PRIORITY(1) | THINKOS_OPT_ID(1));
}
Esempio n. 6
0
static void btn_init(void)
{
	btn_mutex = thinkos_mutex_alloc();

	printf("%s(): btn_mutex=%d.\n", __func__, btn_mutex);

	thinkos_thread_create((void *)__btn_task, (void *)NULL,
						  btn_stack, sizeof(btn_stack) |
						  THINKOS_OPT_PRIORITY(2));
	thinkos_sleep(100);
}
Esempio n. 7
0
void net_recv_init(void)
{
	static int8_t thread = -1;

	if (thread >= 0)
		return;

	thread = thinkos_thread_create((void *)net_recv_task, (void *)NULL,
								   net_recv_stack, sizeof(net_recv_stack) |
								   THINKOS_OPT_PRIORITY(5) | THINKOS_OPT_ID(5));
}
Esempio n. 8
0
void leds_init(void)
{
	struct stm32_rcc * rcc = STM32_RCC;
	struct stm32f_tim * tim = STM32F_TIM3;
	struct stm32_afio * afio = STM32_AFIO;
	uint32_t div;
	uint32_t pre;
	uint32_t n;

	afio->mapr |= AFIO_SPI1_REMAP;

	stm32_gpio_mode(LED1_IO, ALT_FUNC, PUSH_PULL | SPEED_HIGH);
	stm32_gpio_mode(LED2_IO, ALT_FUNC, PUSH_PULL | SPEED_HIGH);

	/* get the total divisior */
	div = ((2 * stm32f_apb1_hz) + (TIMER_PWM_FREQ / 2)) / TIMER_PWM_FREQ;
	/* get the minimum pre scaler */
	pre = (div / 65536) + 1;
	/* get the reload register value */
	n = (div + pre / 2) / pre;

	DCC_LOG2(LOG_TRACE, "div=%d pre=%d", div, pre);

	/* Timer clock enable */
	rcc->apb1enr |= RCC_TIM3EN;
	
	/* Timer configuration */
	tim->sr= 0; /* Clear interrupts */
	tim->psc = pre - 1;
	tim->arr = n - 1;

	tim->cnt = 0;
	tim->egr = 0;
	tim->rcr = 0;

	/* */
	DCC_LOG1(LOG_TRACE, "ARR=%d", tim->arr);
	tim->ccr1 = 0;
	tim->ccr2 = tim->arr;
	tim->ccmr1 = TIM_OC1M_PWM_MODE1 | TIM_OC1PE | \
				 TIM_OC2M_PWM_MODE2 | TIM_OC2PE;
	tim->ccer = TIM_CC1E | TIM_CC2E;
	tim->bdtr = TIM_MOE | TIM_OSSR;

	/* enable counter */
	tim->cr2 = 0;
	tim->cr1 = TIM_URS | TIM_CEN; 

	led_flag = thinkos_flag_alloc();

	thinkos_thread_create((void *)led_task, (void *)NULL,
						  led_stack, sizeof(led_stack) |
						  THINKOS_OPT_PRIORITY(8) | THINKOS_OPT_ID(6));
}
Esempio n. 9
0
void audio_init(void)
{
	int th;

	DCC_LOG(LOG_TRACE, "...");

	audio_drv.enabled = false;

	/* 50 ms jitter buffer */
	jitbuf_init(&audio_drv.jitbuf, SAMPLE_RATE,
				SAMPLE_RATE, 25);

	codec_hw_reset();

	tracef("%s(): initializing I2S...", __func__);
	i2s_slave_init();

	tracef("%s(): initializing TLV320...", __func__);
	tlv320_reset();

	tlv320_init();

	th = thinkos_thread_create((void *)net_rcv_task, (void *)NULL,
							   net_rcv_stack, 
							   sizeof(net_rcv_stack), 
							   THINKOS_OPT_PRIORITY(1) | 
							   THINKOS_OPT_ID(1));
	audio_drv.net_thread = th;

	th = thinkos_thread_create((void *)audio_io_task, (void *)NULL,
							   audio_io_stack, 
							   sizeof(audio_io_stack), 
							   THINKOS_OPT_PRIORITY(0) | 
							   THINKOS_OPT_ID(0));
	audio_drv.io_thread = th;

}
Esempio n. 10
0
void leds_init(void)
{
	int i;

	__leds_io_init();

	for (i = 0; i < LED_COUNT; ++i)
		led_rate[i] = 0;

	leds_mutex = thinkos_mutex_alloc();

	printf("%s(): leds_mutex=%d.\n", __func__, leds_mutex);

	thinkos_thread_create((void *)__leds_task, (void *)NULL,
						  leds_stack, sizeof(leds_stack) |
						  THINKOS_OPT_PRIORITY(2));

	thinkos_sleep(100);
}
Esempio n. 11
0
int main(int argc, char ** argv)
{
	struct acc_info acc;
	uint32_t cnt = 0;
	int dt;
	int x;
	int y;
	int i;

	/* calibrate usecond delay loop */
	cm3_udelay_calibrate();

	__leds_io_init();

	__leds_all_on();
	udelay(100000);
	__leds_all_off();
	udelay(100000);

	/* Initialize the stdin, stdout and stderr */
	stdio_init();

	__leds_all_on();
	udelay(100000);

	/* Print a useful information message */
	printf("\n");

	__leds_all_off();

	printf("---------------------------------------------------------\n");
	printf(" STM32F4 Discovery example\n");
	printf("---------------------------------------------------------\n");
	printf("\n");

//	while (1) {
//		__leds_all_on();
//		udelay(100000);
//		__leds_all_off();
//		udelay(100000);
//	}


	thinkos_init(THINKOS_OPT_PRIORITY(4) | THINKOS_OPT_ID(4));

	leds_init();
	btn_init();

#if 0
	for (i = 0; ; ++i) {
		led_off((i - 2) & 0x7);
		led_on(i & 0x7);

		dt = i & 255;
		if (dt > 127)
			dt = 255 - dt;

		thinkos_sleep(dt);
	}
#endif

	acc.sem = thinkos_sem_alloc(0);
	printf("%s(): acc.sem=%d.\n", __func__, acc.sem);
	thinkos_thread_create((void *)accelerometer_task, (void *)&acc,
						  accelerometer_stack, sizeof(accelerometer_stack) |
						  THINKOS_OPT_PRIORITY(1));

	for (i = 0; ; ++i) {
		thinkos_sem_wait(acc.sem);

		if (btn_event_get() == BTN_PRESSED) {
			/* request calibration */
			acc.cal_req = true;
		}
	
		/* Scale */
		x = acc.x * 64 / 512;
		y = acc.y * 64 / 512;

		if ((++cnt & 0x03) == 0) {
			printf("%5d,%5d\r", x, y);
		}

		if (x == 0) {
			led_on(1);
			led_on(3);
		} else if (x < 0) {
			led_blink(3, -x);
			led_off(1);
		} else {
			led_blink(1, x);
			led_off(3);
		}

		if (y == 0) {
			led_on(0);
			led_on(2);
		} else if (y < 0) {
			led_off(0);
			led_blink(2, -y);
		} else {
			led_off(2);
			led_blink(0, y);
		}
	}

	return 0;
}
Esempio n. 12
0
void irq_test(void)
{
	int timer_th;
	int event_th;
	struct set max;
	struct set avg;
	struct set ticks;
	struct set ticks0;
	struct set dt;
	int i;
	int ms;

	/* make sure IRQs are disabled */
	cm3_irq_disable(STM32F_IRQ_TIM6);
	cm3_irq_disable(STM32F_IRQ_TIM7);
	cm3_irq_disable(STM32F_IRQ_TIM9);

	/* allocate semaphore */
	printf("1.\n");
	sem_timer = thinkos_sem_alloc(0); 
	/* allocate event */
	printf("2.\n");
	ev_timer = thinkos_ev_alloc(); 

	/* initialize timer 6 */
	timer_init(STM32F_TIM6);

	/* initialize timer 7 */
	timer_init(STM32F_TIM7);
	/* set timer 7 to very high priority */
	cm3_irq_pri_set(STM32F_IRQ_TIM7, 0x20);
	cm3_irq_enable(STM32F_IRQ_TIM7);

	/* initialize timer 9 */
	timer_init(STM32F_TIM9);
	/* set timer 9 to very low priority */
	cm3_irq_pri_set(STM32F_IRQ_TIM9, 0xff);
	cm3_irq_enable(STM32F_IRQ_TIM9);

	printf("4.\n");
	event_th = thinkos_thread_create(event_wait_task, NULL, 
						  stack[1], STACK_SIZE, 
						  THINKOS_OPT_PRIORITY(0) |
						  THINKOS_OPT_ID(0));

	printf("5.\n");
	timer_th = thinkos_thread_create(timer_isr_task, NULL, 
						  stack[2], STACK_SIZE, 
						  THINKOS_OPT_PRIORITY(0) |
						  THINKOS_OPT_ID(0));


	thinkos_sleep(100);

//	printf("- All times in microseconds\n");
	printf("| TIM6 IRQ Wait  | TIM7 High Pri  "
		   "| TIM9 Low Pri   | TIM7 > Ev Wait |\n"); 

	printf("|   dt  avg  max |   dt  avg  max "
		   "|   dt  avg  max |   dt  avg  max |\n"); 
		   
	memset(&meter, 0, sizeof(meter));

	timer_start(STM32F_TIM6);
	timer_start(STM32F_TIM7);
	timer_start(STM32F_TIM9);

	ticks0.tim6 = 0;
	ticks0.tim7 = 0;
	ticks0.tim9 = 0;
	ticks0.event = 0;

//	for (i = 0; i < 10; i++) {
	for (i = 0; i < 5; i++) {
		for (ms = 0; ms < 1000; ms++) 
			thinkos_sem_wait(sem_timer);

		/* get data */
		max = meter.max;
		avg = meter.avg;
		ticks = meter.ticks;

		avg.tim6 = (avg.tim6 * 33) / 64;
		max.tim6 *= 33;

		avg.tim7 = (avg.tim7 * 33) / 64;
		max.tim7 *= 33;

		avg.tim9 = (avg.tim9 * 33) / 64;
		max.tim9 *= 33;

		avg.event = (avg.event * 33) / 64;
		max.event *= 33;

		dt.tim6 = ticks.tim6 - ticks0.tim6;
		ticks0.tim6 = ticks.tim6;

		dt.tim7 = ticks.tim7 - ticks0.tim7;
		ticks0.tim7 = ticks.tim7;

		dt.tim9 = ticks.tim9 - ticks0.tim9;
		ticks0.tim9 = ticks.tim9;

		dt.event = ticks.event - ticks0.event;
		ticks0.event = ticks.event;

		printf("| %4d %4d %4d | %4d %4d %4d | %4d %4d %4d | %4d %4d %4d |\n", 
			   dt.tim6, avg.tim6, max.tim6, 
			   dt.tim7, avg.tim7, max.tim7, 
			   dt.tim9, avg.tim9, max.tim9,
			   dt.event, avg.event, max.event);
	}
	printf("\n");

	cm3_irq_disable(STM32F_IRQ_TIM7);
	cm3_irq_disable(STM32F_IRQ_TIM9);

	thinkos_cancel(event_th, 0);
	thinkos_cancel(timer_th, 0);

	thinkos_ev_free(ev_timer);
	thinkos_sem_free(sem_timer);
}
Esempio n. 13
0
void console_shell_init(void)
{
	thinkos_thread_create((void *)console_shell_task, (void *)NULL,
						  console_shell_stack, sizeof(console_shell_stack) | 
						  THINKOS_OPT_PRIORITY(2) | THINKOS_OPT_ID(2));
}
Esempio n. 14
0
void sched_speed_test(void)
{
//	uint32_t stack[4][STACK_SIZE / 4];
//	volatile struct my_arg ctrl[4];
	int th[4];
	int x[4];
	int y[4];
	int d[4];
	int ret;
	int i;

	printf("---------------------------------------------------------\n");
	printf(" - Scheduler speed test\n");

	th[0] = thinkos_thread_create(yield_task, (void *)&dev[0], 
								  stack[0], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(1) |
								  THINKOS_OPT_ID(2) | THINKOS_OPT_PAUSED);
								  
	th[1] = thinkos_thread_create(yield_task, (void *)&dev[1], 
								  stack[1], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(1) |
								  THINKOS_OPT_ID(2) | THINKOS_OPT_PAUSED);

	th[2] = thinkos_thread_create(yield_task, (void *)&dev[2], 
								  stack[2], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(2) |
								  THINKOS_OPT_ID(0) | THINKOS_OPT_PAUSED);

	th[3] = thinkos_thread_create(yield_task, (void *)&dev[3], 
								  stack[3], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(2) |
								  THINKOS_OPT_ID(0) | THINKOS_OPT_PAUSED);

	printf("  * Threads: %d, %d, %d, %d\n", th[0], th[1], th[2], th[3]);

	/* The threads where paused on creation, start them */
	for (i = 0; i < 4; i++) {
		thinkos_resume(th[i]);
	}

	for (i = 0; i < 5; i++) {
		x[0] = dev[0].cnt;
		x[1] = dev[1].cnt;
		x[2] = dev[2].cnt;
		x[3] = dev[3].cnt;
		thinkos_sleep(1000);
		y[0] = dev[0].cnt;
		y[1] = dev[1].cnt;
		y[2] = dev[2].cnt;
		y[3] = dev[3].cnt;

		d[0] = y[0] - x[0];
		d[1] = y[1] - x[1];
		d[2] = y[2] - x[2];
		d[3] = y[3] - x[3];

		printf(" %8d + %8d + %8d + %8d = %8d (%d idle)\n", 
			   d[0], d[1], d[2], d[3], d[0] + d[1] + d[2] + d[3], 
			   thinkos_idle_val());
	}

	for (i = 0; i < 4; i++) {
		thinkos_cancel(th[i], i + 30);
		printf("  * join(%d) ...", th[i]);
		ret = thinkos_join(th[i]);
		printf(" %d\n", ret);
	}


	printf("\n");
};
Esempio n. 15
0
int main(int argc, char ** argv)
{
	struct usb_cdc_class * cdc;
	struct serial_dev * serial;
	struct vcom vcom;
	int i;

	DCC_LOG_INIT();
	DCC_LOG_CONNECT();

	/* calibrate usecond delay loop */
	cm3_udelay_calibrate();

	DCC_LOG(LOG_TRACE, "1. io_init()");
	io_init();

	DCC_LOG(LOG_TRACE, "2. thinkos_init()");
	thinkos_init(THINKOS_OPT_PRIORITY(3) | THINKOS_OPT_ID(3));

	leds_init();

	cdc = usb_cdc_init(&stm32f_usb_fs_dev, cdc_acm_str, 
					   cdc_acm_strcnt);

	serial = serial2_open();

	vcom.serial = serial;
	vcom.cdc = cdc;
	vcom.mode = VCOM_MODE_NONE;

	thinkos_thread_create((void *)led_task, (void *)NULL,
						  led_stack, sizeof(led_stack) |
						  THINKOS_OPT_PRIORITY(1) | THINKOS_OPT_ID(1));


	thinkos_thread_create((void *)serial_recv_task, 
						  (void *)&vcom,
						  serial_recv_stack, sizeof(serial_recv_stack) |
						  THINKOS_OPT_PRIORITY(0) | THINKOS_OPT_ID(0));

	thinkos_thread_create((void *)serial_ctrl_task, 
						  (void *)&vcom,
						  serial_ctrl_stack, sizeof(serial_ctrl_stack) |
						  THINKOS_OPT_PRIORITY(2) | THINKOS_OPT_ID(2));

	usb_vbus(true);

	for (i = 0; i < 5; ++i) {
		led_on(LED_AMBER);
		thinkos_sleep(100);
		led_off(LED_AMBER);
		led_on(LED_RED);
		thinkos_sleep(100);
		led_off(LED_RED);
	}


	for (;;) {
		usb_recv_task(&vcom);
	}
}
Esempio n. 16
0
void busy_test(void)
{
	int th[4];
	int x[4];
	int y[4];
	int d[4];
	int sum;
	int ref;
	int ret;
	int i;

	printf("---------------------------------------------------------\n");
	printf(" - Scheduler test\n");

	for (i = 0; i < 4; i++) {
		dev[i].enabled = true;
		dev[i].cnt = 0;
	}

	th[0] = thinkos_thread_create(busy_task, (void *)&dev[0], 
								  stack[0], STACK_SIZE, 
								  THINKOS_OPT_PRIORITY(2) |
								  THINKOS_OPT_ID(8));

	th[1] = thinkos_thread_create(busy_task, (void *)&dev[1], 
								  stack[1], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(4) |
								  THINKOS_OPT_ID(8));

	th[2] = thinkos_thread_create(busy_task, (void *)&dev[2], 
								  stack[2], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(6) |
								  THINKOS_OPT_ID(8));

	th[3] = thinkos_thread_create(busy_task, (void *)&dev[3], 
								  stack[3], STACK_SIZE,
								  THINKOS_OPT_PRIORITY(8) |
								  THINKOS_OPT_ID(8));

	printf("  * Threads: %d, %d, %d, %d\n", th[0], th[1], th[2], th[3]);

	for (i = 0; i < 8; i++) {
		x[0] = dev[0].cnt;
		x[1] = dev[1].cnt;
		x[2] = dev[2].cnt;
		x[3] = dev[3].cnt;
		thinkos_sleep(1000);
		y[0] = dev[0].cnt;
		y[1] = dev[1].cnt;
		y[2] = dev[2].cnt;
		y[3] = dev[3].cnt;

		d[0] = y[0] - x[0];
		d[1] = y[1] - x[1];
		d[2] = y[2] - x[2];
		d[3] = y[3] - x[3];
		sum = d[0] + d[1] + d[2] + d[3];

		ref = 100 * d[3];

		printf(" %8d + %8d + %8d + %8d = %8d (%d idle)\n", 
			   d[0], d[1], d[2], d[3], sum, thinkos_idle_val());
		printf(" %d%% %d%% %d%% %d%%\n", 
			   ref / d[0], ref / d[1], ref / d[2], ref / d[3]);

	}

	for (i = 0; i < 4; i++) {
		dev[i].enabled = false;
		printf("  * join(%d) ...", th[i]);
		ret = thinkos_join(th[i]);
		printf(" %d\n", ret);
	}

	thinkos_sleep(1);

	printf("\n");
}
Esempio n. 17
0
void busy_test(void)
{
	int th[4];
	uint32_t x[4];
	uint32_t y[4];
	uint32_t d[4];
	uint32_t sum;
	uint32_t ref;
	uint32_t wrk;
	struct thinkos_rt rt;
	uint32_t cycsum;
	int ret;
	int i;
	int j;

	printf("---------------------------------------------------------\n");
	printf(" - Scheduler test\n");

	thinkos_rt_snapshot(&rt);
	thinkos_sleep(1000);
	thinkos_rt_snapshot(&rt);
	cycsum = 0;

	for (j = 0; j < THINKOS_THREADS_MAX + 1; ++j) {
		uint32_t cyc = rt.cyccnt[j];
		cycsum += cyc;
		if (cyc > 0) {
			printf("  * Thread %d: %9d cycles.\n", j, cyc);
		}
	}
	printf("  *    Total: %9d cycles.\n", cycsum);

	for (i = 0; i < 4; i++) {
		dev[i].enabled = true;
		dev[i].cnt = 0;
	}

	th[0] = thinkos_thread_create(busy_task, (void *)&dev[0], 
								  stack[0], STACK_SIZE |
								  THINKOS_OPT_PRIORITY(2) |
								  THINKOS_OPT_ID(8));

	th[1] = thinkos_thread_create(busy_task, (void *)&dev[1], 
								  stack[1], STACK_SIZE |
								  THINKOS_OPT_PRIORITY(4) |
								  THINKOS_OPT_ID(8));

	th[2] = thinkos_thread_create(busy_task, (void *)&dev[2], 
								  stack[2], STACK_SIZE |
								  THINKOS_OPT_PRIORITY(6) |
								  THINKOS_OPT_ID(8));

	th[3] = thinkos_thread_create(busy_task, (void *)&dev[3], 
								  stack[3], STACK_SIZE |
								  THINKOS_OPT_PRIORITY(8) |
								  THINKOS_OPT_ID(8));

	printf("  * Thread: %8d   %8d   %8d   %8d\n", th[0], th[1], th[2], th[3]);

	for (i = 0; i < 8; i++) {
		x[0] = dev[0].cnt;
		x[1] = dev[1].cnt;
		x[2] = dev[2].cnt;
		x[3] = dev[3].cnt;
		thinkos_rt_snapshot(&rt);
		thinkos_sleep(1000);
		thinkos_rt_snapshot(&rt);
		y[0] = dev[0].cnt;
		y[1] = dev[1].cnt;
		y[2] = dev[2].cnt;
		y[3] = dev[3].cnt;

		d[0] = y[0] - x[0];
		d[1] = y[1] - x[1];
		d[2] = y[2] - x[2];
		d[3] = y[3] - x[3];
		sum = d[0] + d[1] + d[2] + d[3];

		/* XXX: reusing x, to scale down the deltas.
		 This is to avoid overflowing the percentage calculations */
		x[0] = (d[0] + 50) / 100;
		x[1] = (d[1] + 50) / 100;
		x[2] = (d[2] + 50) / 100;
		x[3] = (d[3] + 50) / 100;
		/* scale down the total sum */
		wrk = sum / 100;

		ref = d[3];
		printf("%d.\n", i);
		printf("  *   Oper: %8d + %8d + %8d + %8d = %8d (%d idle)\n", 
			   d[0], d[1], d[2], d[3], sum, thinkos_idle_val());
		printf("  *   Work: %7d%%   %7d%%   %7d%%   %7d%% = %7d%%\n", 
			   (d[0] + wrk / 2) / wrk, (d[1] + wrk / 2) / wrk,
			   (d[2] + wrk / 2) / wrk, (d[3] + wrk / 2) / wrk,
			   (sum + wrk / 2) / wrk);
		printf("  *   Nice: %7d%%   %7d%%   %7d%%   %7d%%\n", 
			   (ref + x[0] / 2) / x[0], (ref + x[1] / 2) / x[1], 
			   (ref + x[2] / 2) / x[2], (ref + x[3] / 2) / x[3]); 

		cycsum = 0;
		for (j = 0; j < THINKOS_THREADS_MAX + 1; ++j)
			cycsum += rt.cyccnt[j];

		printf("  * Cycles: %8d + %8d + %8d + %8d = %8d (%d idle)\n", 
			   rt.cyccnt[th[0]], rt.cyccnt[th[1]], 
			   rt.cyccnt[th[2]], rt.cyccnt[th[3]], 
			   cycsum, rt.cyccnt[THINKOS_THREADS_MAX]); 

	}
	printf("\n");



	for (i = 0; i < 4; i++) {
		dev[i].enabled = false;
		printf("  * join(%d) ...", th[i]);
		ret = thinkos_join(th[i]);
		printf(" %d\n", ret);
	}
	printf("---------------------------------------------------------\n");
	printf("\n");
}