/** * Execute the callback of a timer. * * @param expiredTimer pointer on the timer * * WARNING: expiredTimer MUST NOT be null (rem: static function ) */ static void execute_callback(T_TIMER_LIST_ELT *expiredTimer) { #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log( "\nINFO : execute_callback : executing callback of timer 0x%x (now = %u - expiration = %u)", (uint32_t)expiredTimer, get_uptime_ms(), expiredTimer->desc.expiration); #endif int flags = irq_lock(); /* if the timer was not stopped by its own callback */ if (E_TIMER_RUNNING == expiredTimer->desc.status) { remove_timer(expiredTimer); /* add it again if repeat flag was on */ if (expiredTimer->desc.repeat) { expiredTimer->desc.expiration = get_uptime_ms() + expiredTimer->desc. delay; add_timer(expiredTimer); } } irq_unlock(flags); /* call callback back */ if (NULL != expiredTimer->desc.callback) { expiredTimer->desc.callback(expiredTimer->desc.data); } else { #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log("\nERROR : execute_callback : timer callback is null "); #endif panic(E_OS_ERR); } }
/** * Create a timer object. * This service may panic if err parameter is null and: * callback parameter is null, or * no timer is available. * * Authorized execution levels: task, fiber, ISR * * @param callback: pointer to the function to be executed. * @param privData: pointer to data that shall be passed to the callback * @param delay: number of milliseconds between function executions * @param repeat: specifies if the timer shall be re-started after each execution of the callback * @param startup : specifies if the timer shall be start immediately * @param err (out): execution status: * E_OS_OK : callback is programmed * E_OS_ERR: no timer is available, or callback parameter is null * * @return Handler on the timer, NULL if the service fails (e.g. no available * timer or callback is a null pointer). */ T_TIMER timer_create(T_ENTRY_POINT callback, void *privData, uint32_t delay, bool repeat, bool startup, OS_ERR_TYPE *err) { T_TIMER_LIST_ELT *timer = NULL; /* check input parameters */ if ((NULL != callback) && (OS_WAIT_FOREVER != delay)) { /* delay should be set to 0 if startup flag is false * otherwise delay should be a positive value if startup flag is true */ if (((0 < delay) && (true == startup)) || ((0 <= delay) && (false == startup))) { /* find and reserve a timer resource from g_TimerPool_elements */ /* rem: timer points to an element from the global g_TimerPool_elements */ timer = g_TimerPool_alloc(); if (timer != NULL) { /* initialize timer descriptor */ timer->desc.callback = callback; timer->desc.data = privData; timer->desc.delay = delay; timer->desc.repeat = repeat; timer->desc.status = E_TIMER_READY; /* insert timer in the list of active timers */ if (startup) { int flags; timer->desc.expiration = get_uptime_ms() + timer->desc.delay; flags = irq_lock(); add_timer(timer); irq_unlock(flags); if (g_CurrentTimerHead == timer) { /* new timer is the next to expire, unblock timer_task to assess the change */ signal_timer_task(); } } #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log( "\nINFO : timer_create : new timer will expire at %u (now = %u ) - addr = 0x%x", timer->desc.expiration, get_uptime_ms(), (uint32)timer); #endif error_management(err, E_OS_OK); } else { /* all timers from the pool are already being used */ error_management(err, E_OS_ERR_NO_MEMORY); } } else { /* delay and startup parameter are inconsistent */ error_management(err, E_OS_ERR); } } else { /* callback == NULL or delay == 0 : at least one parameter is invalid */ error_management(err, E_OS_ERR); } return (T_TIMER)timer; }
/** * Main function of the timer task. This function is in charge of * calling the callbacks associated with the timers. * * This function is run in a high priority task on microkernel builds. * This function is run in a high priority fiber on nanokernel builds. * It implements an infinite loop that waits for any of the semaphores from * g_TimerSem. * When a semaphore is signaled, this function fetches the pointer to the * associated callback in g_TimerDesc, then calls it. * * @param dummy1 not used (required by ZEPHYR API) * @param dummy2 not used (required by ZEPHYR API) * * */ void timer_task(int dummy1, int dummy2) { int32_t timeout = UINT32_MAX; uint32_t now; UNUSED(dummy1); UNUSED(dummy2); while (1) { /* the Timer task shall never stop */ /* Before waiting for next timeout, publish it to warn QUARK cpu */ publish_cpu_timeout(timeout); /* block until g_TimerSem is signaled or until the next timeout expires */ #ifdef CONFIG_MICROKERNEL (void)task_sem_take(g_TimerSem, CONVERT_MS_TO_TICKS(timeout)); #else nano_sem_take(&g_TimerSem, CONVERT_MS_TO_TICKS(timeout)); #endif now = get_uptime_ms(); /* task is unblocked: check for expired timers */ while (g_CurrentTimerHead && is_after_expiration(now, &(g_CurrentTimerHead->desc))) { execute_callback(g_CurrentTimerHead); now = get_uptime_ms(); } /* Compute timeout until the expiration of the next timer */ if (g_CurrentTimerHead != NULL) { /* In micro kernel context, timeout = 0 or timeout < 0 works. * In nano kernel context timeout must be a positive value. */ timeout = g_CurrentTimerHead->desc.expiration - now; if (timeout < 0) panic(E_OS_ERR_OVERFLOW); } else { timeout = UINT32_MAX; } #ifdef __DEBUG_OS_ABSTRACTION_TIMER if (NULL != g_CurrentTimerHead) _log( "\nINFO : timer_task : now = %u, next timer expires at %u, timeout = %u", get_uptime_ms(), g_CurrentTimerHead->desc.expiration, timeout); else _log( "\nINFO : timer_task : now = %u, no next timer, timeout = OS_WAIT_FOREVER", get_uptime_ms()); #endif } /* end while(1) */ }
/** * Return the next free block of a pool and * mark it as reserved/allocated. * * @param pool index of the pool in mpool * * @return allocated buffer or NULL if none is * available */ static void *memblock_alloc(uint32_t pool) { uint16_t block; uint32_t flags = interrupt_lock();//irq_lock(); for (block = 0; block < mpool[pool].count; block++) { if (((mpool[pool].track)[block / BITS_PER_U32] & 1 << (BITS_PER_U32 - 1 - (block % BITS_PER_U32))) == 0) { (mpool[pool].track)[block / BITS_PER_U32] = (mpool[pool].track)[block / BITS_PER_U32] | (1 << (BITS_PER_U32 - 1 - (block % BITS_PER_U32))); #ifdef CONFIG_MEMORY_POOLS_BALLOC_STATISTICS mpool[pool].cur = mpool[pool].cur + 1; #ifdef CONFIG_MEMORY_POOLS_BALLOC_TRACK_OWNER /* get return address */ uint32_t ret_a = (uint32_t)__builtin_return_address(0); mpool[pool].owners[block] = (uint32_t *)(((ret_a & 0xFFFF0U) >> 4) | ((get_uptime_ms() & 0xFFFF0) << 12)); #endif if (mpool[pool].cur > mpool[pool].max) mpool[pool].max = mpool[pool].cur; #endif interrupt_unlock(flags);//irq_unlock(flags); return (void *)(mpool[pool].start + mpool[pool].size * block); } }
/** * Curie BSP implementation of jerry_port_get_current_time. */ double jerry_port_get_current_time (void) { uint32_t uptime_ms = get_uptime_ms (); uint32_t epoch_time = uptime_to_epoch (uptime_ms); return ((double) epoch_time) * 1000.0; } /* jerry_port_get_current_time */
/** * Remove a timer from the list of active timers. * * @param timerToRemove pointer on the timer to remove * * WARNING: timerToRemove MUST NOT be null (rem: static function ) * */ static void remove_timer(T_TIMER_LIST_ELT *timerToRemove) { T_TIMER_LIST_ELT *removePoint; #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log( "\nINFO : remove_timer - start: removing 0x%x to expire at %d (now = %d)", (uint32_t)timerToRemove, timerToRemove->desc.expiration, get_uptime_ms()); display_list(); #endif if (NULL != g_CurrentTimerHead) { removePoint = g_CurrentTimerHead; while (NULL != removePoint) { if (timerToRemove == removePoint) { if (NULL != timerToRemove->next) { timerToRemove->next->prev = timerToRemove->prev; } if (NULL != timerToRemove->prev) { timerToRemove->prev->next = timerToRemove->next; } } removePoint = removePoint->next; } if (timerToRemove == g_CurrentTimerHead) { g_CurrentTimerHead = g_CurrentTimerHead->next; if (NULL != g_CurrentTimerHead) { g_CurrentTimerHead->prev = NULL; } } } else { #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log("\nERROR : remove_timer : list of active timer is empty "); #endif panic(E_OS_ERR); } /* clean-up links */ timerToRemove->prev = NULL; timerToRemove->next = NULL; timerToRemove->desc.status = E_TIMER_READY; #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log("\nINFO : remove_timer - end "); display_list(); #endif }
void panic_handler(void) { irq_lock(); struct arcv2_panic_arch_data *arc_info = (struct arcv2_panic_arch_data *)&arcv2_panic_data->arch_data; struct panic_data_footer *footer = (struct panic_data_footer *)&arcv2_panic_data->footer; footer->struct_size = sizeof(struct panic_data_footer) + sizeof(struct arcv2_panic_arch_data); // Copy stack to panic RAM location if sp is valid if (IN_RANGE(arc_info->sp, ARC_RAM_START_ADDR, ARC_RAM_START_ADDR + ARC_RAM_SIZE * 1024) || IN_RANGE(arc_info->sp, ARC_DCCM_START_ADDR, ARC_DCCM_START_ADDR + CONFIG_QUARK_SE_ARC_DCCM_SIZE)) { uint8_t *stack_dump = (uint8_t *)arc_info - PANIC_ARC_STACK_SIZE; // Align sp pointer on 32bits to avoid alignement issues memcpy(stack_dump, (uint32_t *)((arc_info->sp + 3) & (~3)), PANIC_ARC_STACK_SIZE); footer->struct_size += PANIC_ARC_STACK_SIZE; } footer->arch = ARC_CORE; footer->flags = PANIC_DATA_FLAG_FRAME_VALID | PANIC_DATA_FLAG_FRAME_BLE_AVAILABLE; footer->magic = PANIC_DATA_MAGIC; footer->reserved = 0; footer->time = get_uptime_ms(); memcpy(&footer->build_cksum, (const void *)version_header.hash, sizeof(version_header.hash)); footer->struct_version = version_header.version; if (!is_panic) { is_panic = true; if (!is_panic_notification) { // Notify master core that a panic occured panic_notify(0); } else { // Notify master core that panic notification has been processed panic_done(); } } // Stop core while (1) ; }
/** * start the timer. * This service may panic if err parameter is null and: * no timer is available or timer is running . * * Authorized execution levels: task, fiber, ISR * * @param tmr : handler on the timer (value returned by timer_create ). * @param err (out): execution status: */ void timer_start(T_TIMER tmr, uint32_t delay, OS_ERR_TYPE *err) { T_TIMER_LIST_ELT *timer = (T_TIMER_LIST_ELT *)tmr; OS_ERR_TYPE localErr = E_OS_OK; /* if timer is created */ if (NULL != timer) { int flags = irq_lock(); if (timer->desc.status == E_TIMER_READY) { /* if timer parameter are valid */ if ((NULL != timer->desc.callback) && (0 < delay)) { #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log("\nINFO : timer_start : starting timer "); #endif /* Update expiration time */ timer->desc.delay = delay; timer->desc.expiration = get_uptime_ms() + timer->desc.delay; /* add the timer */ add_timer(timer); irq_unlock(flags); /* new timer is the next to expire, unblock timer_task to assess the change */ if (g_CurrentTimerHead == timer) { signal_timer_task(); } } else { /* timer is not valid */ localErr = E_OS_ERR; } } else if (timer->desc.status == E_TIMER_RUNNING) { irq_unlock(flags); localErr = E_OS_ERR_BUSY; if (err != NULL) *err = localErr; return; } } else { /* tmr is not a timer from g_TimerPool_elements */ localErr = E_OS_ERR; } error_management(err, localErr); }
/** * Insert a timer in the list of active timer, * according to its expiration date. * * @param newTimer pointer on the timer to insert * * WARNING: newTimer MUST NOT be null (rem: static function ) * */ static void add_timer(T_TIMER_LIST_ELT *newTimer) { T_TIMER_LIST_ELT *insertionPoint; T_TIMER_LIST_ELT *listTail; bool found; #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log( "\nINFO : add_timer - start: adding 0x%x to expire at %d (now = %d - delay = %d - ticktime = %d)", (uint32_t)newTimer, newTimer->desc.expiration, get_uptime_ms(), newTimer->desc.delay, sys_clock_us_per_tick); display_list(); #endif if (NULL == g_CurrentTimerHead) { /* there is no active timer, make newTimer the head timer */ g_CurrentTimerHead = newTimer; newTimer->prev = NULL; newTimer->next = NULL; } else { /* find the next timer to expire after newTimer->desc.expiration */ insertionPoint = g_CurrentTimerHead; listTail = g_CurrentTimerHead; found = false; while ((NULL != insertionPoint) && (false == found)) { if (!is_after_expiration(newTimer->desc.expiration, &(insertionPoint->desc))) { /* newTimer is due to expire before insertionPoint */ if (g_CurrentTimerHead == insertionPoint) { /* insert newTimer before the head timer */ g_CurrentTimerHead->prev = newTimer; newTimer->prev = NULL; newTimer->next = g_CurrentTimerHead; g_CurrentTimerHead = newTimer; } else { /* insert newTimer between insertionPoint and insertionPoint->prev */ newTimer->prev = insertionPoint->prev; newTimer->next = insertionPoint; insertionPoint->prev = newTimer; newTimer->prev->next = newTimer; } /* done */ found = true; } else { /* newTimer is due to expire after insertionPoint, continue searching */ listTail = insertionPoint; /* update list head marker = last non null insertionPoint */ /* move downward */ insertionPoint = insertionPoint->next; } } if ((false == found) && (NULL != listTail)) { /* newTimer is due to expire after all others have expired */ listTail->next = newTimer; newTimer->prev = listTail; } } newTimer->desc.status = E_TIMER_RUNNING; #ifdef __DEBUG_OS_ABSTRACTION_TIMER _log("\nINFO : add_timer - end "); display_list(); display_list(); #endif }