static void align_to_tick_boundary(void) { uint32_t tick; tick = sys_tick_get_32(); while (sys_tick_get_32() == tick) { /* Busy wait to align to tick boundary */ } }
void main(void) { int status = TC_FAIL; uint32_t start_tick; uint32_t end_tick; TC_START("Test Nanokernel Sleep and Wakeup APIs\n"); test_objects_init(); test_fiber_id = task_fiber_start(test_fiber_stack, FIBER_STACKSIZE, test_fiber, 0, 0, TEST_FIBER_PRIORITY, 0); TC_PRINT("Test fiber started: id = 0x%x\n", test_fiber_id); helper_fiber_id = task_fiber_start(helper_fiber_stack, FIBER_STACKSIZE, helper_fiber, 0, 0, HELPER_FIBER_PRIORITY, 0); TC_PRINT("Helper fiber started: id = 0x%x\n", helper_fiber_id); /* Activate test_fiber */ nano_task_sem_give(&test_fiber_sem); /* Wait for test_fiber to activate us */ nano_task_sem_take(&task_sem, TICKS_UNLIMITED); /* Wake the test fiber */ task_fiber_wakeup(test_fiber_id); if (test_failure) { goto done_tests; } TC_PRINT("Testing nanokernel task_sleep()\n"); align_to_tick_boundary(); start_tick = sys_tick_get_32(); task_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick - start_tick != ONE_SECOND) { TC_ERROR("task_sleep() slept for %d ticks, not %d\n", end_tick - start_tick, ONE_SECOND); goto done_tests; } status = TC_PASS; done_tests: TC_END_REPORT(status); }
int nanoCpuDisableInterruptsTest(disable_interrupt_func disableRtn, enable_interrupt_func enableRtn, int irq) { unsigned long long count = 0; unsigned long long i = 0; int tick; int tick2; int imask; /* Align to a "tick boundary" */ tick = sys_tick_get_32(); while (sys_tick_get_32() == tick) { } tick++; while (sys_tick_get_32() == tick) { count++; } /* * Inflate <count> so that when we loop later, many ticks should have * elapsed during the loop. This later loop will not exactly match the * previous loop, but it should be close enough in structure that when * combined with the inflated count, many ticks will have passed. */ count <<= 4; imask = disableRtn(irq); tick = sys_tick_get_32(); for (i = 0; i < count; i++) { sys_tick_get_32(); } tick2 = sys_tick_get_32(); /* * Re-enable interrupts before returning (for both success and failure * cases). */ enableRtn(imask); if (tick2 != tick) { return TC_FAIL; } /* Now repeat with interrupts unlocked. */ for (i = 0; i < count; i++) { sys_tick_get_32(); } return (tick == sys_tick_get_32()) ? TC_FAIL : TC_PASS; }
int nano_cpu_idleTest(void) { int tick; /* current tick count */ int i; /* loop variable */ /* Align to a "tick boundary". */ tick = sys_tick_get_32(); while (tick == sys_tick_get_32()) { } tick = sys_tick_get_32(); for (i = 0; i < 5; i++) { /* Repeat the test five times */ nano_cpu_idle(); tick++; if (sys_tick_get_32() != tick) { return TC_FAIL; } } return TC_PASS; }
void busy_task_entry(void) { int ticks_when_awake; int i; while (1) { /* * go to sleep for 1000 ticks allowing the system entering to sleep * mode if required. */ is_busy_task_awake = 0; SLEEP(1000); ticks_when_awake = sys_tick_get_32(); /* * keep the cpu busy for 1000 ticks preventing the system entering * to sleep mode. */ is_busy_task_awake = 1; while (sys_tick_get_32() - ticks_when_awake < 1000) { i++; } } }
static void test_fiber(int arg1, int arg2) { uint32_t start_tick; uint32_t end_tick; nano_fiber_sem_take(&test_fiber_sem, TICKS_UNLIMITED); TC_PRINT("Testing normal expiration of fiber_sleep()\n"); align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick != start_tick + ONE_SECOND) { TC_ERROR(" *** fiber_sleep() slept for %d ticks not %d.", end_tick - start_tick, ONE_SECOND); return; } TC_PRINT("Testing fiber_sleep() + fiber_fiber_wakeup()\n"); nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** fiber_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } TC_PRINT("Testing fiber_sleep() + isr_fiber_wakeup()\n"); nano_fiber_sem_give(&helper_fiber_sem); /* Activate helper fiber */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** isr_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } TC_PRINT("Testing fiber_sleep() + task_fiber_wakeup()\n"); nano_task_sem_give(&task_sem); /* Activate task */ align_to_tick_boundary(); start_tick = sys_tick_get_32(); fiber_sleep(ONE_SECOND); /* Task will execute */ end_tick = sys_tick_get_32(); if (end_tick > start_tick) { TC_ERROR(" *** task_fiber_wakeup() took too long (%d ticks)\n", end_tick - start_tick); return; } test_failure = false; }
/** * Return the current tick converted in microseconds. * * Authorized execution levels: task, fiber * * ZEPHYR does not provide an API to read a high-precision timer, that * returns a 64-bits value. * The tick is read as a 32-bits value, then casted to 64-bits. * * @warning: the return value is false in interrupt context. * * @return current tick converted in microseconds */ uint64_t get_time_us(void) { return (uint64_t)CONVERT_TICKS_TO_US(sys_tick_get_32()); }
/** * Return the current tick converted in milliseconds. * * Authorized execution levels: task, fiber * * @warning: the return value is false in interrupt context. * * @return current tick converted in milliseconds */ uint32_t get_time_ms(void) { return (uint32_t)CONVERT_TICKS_TO_MS(sys_tick_get_32()); }
void button_pressed(struct device *gpiob, struct gpio_callback *cb, uint32_t pins) { PRINT("Button pressed at %d\n", sys_tick_get_32()); }
/** * @brief Summary data printer fiber * * @details Print the summary data of the context switch events * and the total dropped event ocurred. * * @return No return value. */ void summary_data_printer(void) { int i; while (1) { /* print task data */ PRINTF("\x1b[1;32HFork manager task"); if (forks_available) { PRINTF("\x1b[2;32HForks : free to use"); } else { PRINTF("\x1b[2;32HForks : all taken "); } #ifndef CONFIG_NANOKERNEL /* Due to fiber are not pre-emptive, the busy_task_entry thread won't * run as a fiber in nanokernel-only system, because it would affect * the visualization of the sample and the collection of the data * while running busy. */ PRINTF("\x1b[4;32HWorker task"); if (is_busy_task_awake) { PRINTF("\x1b[5;32HState : BUSY"); PRINTF("\x1b[6;32H(Prevent the system going idle)"); } else { PRINTF("\x1b[5;32HState : IDLE"); PRINTF("\x1b[6;32H "); } #endif /* print general data */ PRINTF("\x1b[8;1HGENERAL DATA"); PRINTF("\x1b[9;1H------------"); PRINTF("\x1b[10;1HSystem tick count : %d ", sys_tick_get_32()); /* print dropped event counter */ PRINTF("\x1b[11;1HDropped events # : %d ", total_dropped_counter); /* Print context switch event data */ PRINTF("\x1b[13;1HCONTEXT SWITCH EVENT DATA"); PRINTF("\x1b[14;1H-------------------------"); PRINTF("\x1b[15;1HThread ID Switches"); for (i = 0; i < MAX_BUFFER_CONTEXT_DATA; i++) { if (context_switch_summary_data[i].thread_id != 0) { print_context_data(context_switch_summary_data[i].thread_id, context_switch_summary_data[i].count, context_switch_summary_data[i].last_time_executed, i); } } /* Print sleep event data */ PRINTF("\x1b[8;32HSLEEP EVENT DATA"); PRINTF("\x1b[9;32H----------------"); PRINTF("\x1b[10;32HLast sleep event received"); if (sleep_event_data.last_time_slept > 0) { PRINTF("\x1b[11;32HExit cause : irq #%u ", sleep_event_data.awake_cause); PRINTF("\x1b[12;32HAt tick : %u ", sleep_event_data.last_time_slept); PRINTF("\x1b[13;32HDuration : %u ticks ", sleep_event_data.last_duration); } /* Print interrupt event data */ PRINTF("\x1b[15;32HINTERRUPT EVENT DATA"); PRINTF("\x1b[16;32H--------------------"); PRINTF("\x1b[17;32HInterrupt counters"); int line = 0; for (i = 0; i < 255; i++) { if (interrupt_counters[i] > 0) { PRINTF("\x1b[%d;%dHirq #%d : %d times", 18 + line, 32, i, interrupt_counters[i]); line++; } } #ifdef CONFIG_MICROKERNEL /* Print task monitor status data */ PRINTF("\x1b[1;64HTASK MONITOR STATUS DATA"); PRINTF("\x1b[2;64H-------------------------"); PRINTF("\x1b[3;64HEvento\tTimestamp\tTaskId\tData"); for (i = 0; i < MAX_BUFFER_CONTEXT_DATA; i++) { if (tmon_summary_data[i].timestamp != 0) { print_tmon_status_data(i); } } #endif /* Sleep */ fiber_sleep(50); } }