Linux Audio

Check our new training course

Loading...
/* boot_time.c - Boot Time measurement task */

/*
 * Copyright (c) 2013-2015 Wind River Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
DESCRIPTION
Measure boot time for both nanokernel and microkernel project which includes
- from reset to kernel's _start
- from _start to main()
- from _start to task
- from _start to idle (for microkernel)
 */

#include <zephyr.h>
#include <tc_util.h>

/* externs */
extern uint64_t __start_tsc; /* timestamp when kernel begins executing */
extern uint64_t __main_tsc;  /* timestamp when main() begins executing */
extern uint64_t __idle_tsc;  /* timestamp when CPU went idle */

void bootTimeTask(void)
{
	uint64_t task_tsc;  /* timestamp at beginning of first task  */
	uint64_t _start_us; /* being of __start timestamp in us	 */
	uint64_t main_us;   /* begin of main timestamp in us	 */
	uint64_t task_us;   /* begin of task timestamp in us	 */
	uint64_t s_main_tsc; /* __start->main timestamp		 */
	uint64_t s_task_tsc;  /*__start->task timestamp		 */
#ifndef  CONFIG_NANOKERNEL
	uint64_t idle_us;	/* begin of idle timestamp in us	 */
	uint64_t s_idle_tsc;  /*__start->idle timestamp		 */
#endif /* ! CONFIG_NANOKERNEL */

	task_tsc = _NanoTscRead();
#ifndef  CONFIG_NANOKERNEL
	/* Go to sleep for 1 tick in order to timestamp when IdleTask halts. */
	task_sleep(1);
#endif /* ! CONFIG_NANOKERNEL */

	_start_us = __start_tsc / CONFIG_CPU_CLOCK_FREQ_MHZ;
	s_main_tsc = __main_tsc-__start_tsc;
	main_us   = s_main_tsc / CONFIG_CPU_CLOCK_FREQ_MHZ;
	s_task_tsc = task_tsc-__start_tsc;
	task_us   = s_task_tsc / CONFIG_CPU_CLOCK_FREQ_MHZ;
#ifndef  CONFIG_NANOKERNEL
	s_idle_tsc = __idle_tsc-__start_tsc;
	idle_us   =  s_idle_tsc / CONFIG_CPU_CLOCK_FREQ_MHZ;
#endif

	/* Indicate start for sanity test suite */
	TC_START("Boot Time Measurement");

	/* Only print lower 32bit of time result */
#ifdef CONFIG_NANOKERNEL
	TC_PRINT("NanoKernel Boot Result: Clock Frequency: %d MHz\n",
			 CONFIG_CPU_CLOCK_FREQ_MHZ);
#else	/* CONFIG_MICROKERNEL */
	TC_PRINT("MicroKernel Boot Result: Clock Frequency: %d MHz\n",
			 CONFIG_CPU_CLOCK_FREQ_MHZ);
#endif
	TC_PRINT("__start       : %d cycles, %d us\n",
			 (uint32_t)(__start_tsc & 0xFFFFFFFFULL),
			 (uint32_t) (_start_us  & 0xFFFFFFFFULL));
	TC_PRINT("_start->main(): %d cycles, %d us\n",
			 (uint32_t)(s_main_tsc & 0xFFFFFFFFULL),
			 (uint32_t)  (main_us  & 0xFFFFFFFFULL));
	TC_PRINT("_start->task  : %d cycles, %d us\n",
			 (uint32_t)(s_task_tsc & 0xFFFFFFFFULL),
			 (uint32_t)  (task_us  & 0xFFFFFFFFULL));
#ifndef  CONFIG_NANOKERNEL  /* CONFIG_MICROKERNEL */
	TC_PRINT("_start->idle  : %d cycles, %d us\n",
			 (uint32_t)(s_idle_tsc & 0xFFFFFFFFULL),
			 (uint32_t)  (idle_us  & 0xFFFFFFFFULL));

#endif

	TC_PRINT("Boot Time Measurement finished\n");

	// for sanity regression test utility.
	TC_END_RESULT(TC_PASS);
	TC_END_REPORT(TC_PASS);

}

#ifdef CONFIG_NANOKERNEL

char __stack fiberStack[512];

/**
 *
 * @brief Nanokernel entry point
 *
 * @return N/A
 */

void main(void)
{
	/* record timestamp for nanokernel's main() function */
	__main_tsc = _NanoTscRead();

	/* create bootTime fibers */
	task_fiber_start(fiberStack, 512,
					 (nano_fiber_entry_t) bootTimeTask, 0, 0, 6, 0);
}

#endif /*  CONFIG_NANOKERNEL */