📄 msched.c
字号:
SET_SLEEP_OCR_VALUE(time); // must wait for these bits to be updated on the async clock WAIT_FOR_ASYNC_UPDATE(); handle_t int_handle = mos_disable_ints(); ENABLE_SLEEP_TIMER(); PRE_KERNEL_SLEEP(); ENABLE_INTS(); SLEEP(); mos_enable_ints(int_handle); POST_KERNEL_SLEEP();}static void idle_mode(void){ handle_t int_handle; int_handle = mos_disable_ints(); ENABLE_IDLE(); ENABLE_INTS(); IDLE(); mos_enable_ints(int_handle);}inline static uint8_t decide_power_save_mode(void){ handle_t i; uint8_t suspend_state; suspend_state = threads[0].suspend_state; // pass over idle thread (index 0) for(i = 1; i < MAX_THREADS; i++) { if(threads[i].suspend_state < suspend_state) { suspend_state = threads[i].suspend_state; if(suspend_state == SUSPEND_STATE_IDLE) { break; } } } // just re-using the index var here i = mos_disable_ints(); //suspend_state = SUSPEND_STATE_IDLE; switch(suspend_state) { case SUSPEND_STATE_SLEEP: ENABLE_SLEEP(); DISABLE_TSLICE_TIMER(); break; case SUSPEND_STATE_IDLE: default: ENABLE_IDLE(); } mos_enable_ints(i); return suspend_state;}inline static uint8_t set_last_sleep_time(thread_t *sleep_thread){ uint32_t st; uint8_t ocr_val; st = sleep_thread->st; if(st > MSECS_MAX_SLEEP) { ocr_val = 255; last_sleep_time = MSECS_MAX_SLEEP; } else { ocr_val = st / MSECS_PER_SLEEP_TICK; ocr_val -= ocr_val % SLEEP_TICK_OVERFLOW; // TODO: what if st is 0 here? (we'll just increment for now) if(!ocr_val) ocr_val++; last_sleep_time = st; } return ocr_val;}/** @brief The idle loop. * * The lowest priority thread (idle thread) runs this loop. * It contains the sleep logic */void idle_loop(void){ thread_t *sleep_thread; // Do power management, deadlock detection, etc. stuff here... while(1) { sleep_thread = mos_tlist_head(&sleepQ); if(sleep_thread) { //threads on sleep q uint8_t ocr_val; if(decide_power_save_mode() == SUSPEND_STATE_IDLE) { idle_mode(); continue; } ocr_val = set_last_sleep_time(sleep_thread);//get ocr val kernel_sleep(ocr_val);//sleep for the ocr value } else { //no sleeping threads idle_mode(); } }}uint8_t mos_thread_new(void (*function_start) (void), uint16_t stack_size, uint8_t priority){ stackval_t *stack_addr; handle_t int_handle; uint8_t id, i; int_handle = mos_disable_ints(); for(id = 0; id < MAX_THREADS; id++) { if(threads[id].state == EMPTY) break; } if(id == MAX_THREADS) { mos_enable_ints(int_handle); return NO_MORE_THREADS; } //Allocate memory for the stack space. stack_addr = mos_mem_alloc(stack_size); if(stack_addr == NULL) { mos_enable_ints(int_handle); return NO_MORE_MEMORY; // Can't continue if we don't have memory } // Now save the memory addr and point to the top of the stack. threads[id].stack = stack_addr; stack_addr += stack_size - 1; threads[id].stackSize = stack_size; threads[id].func = function_start; threads[id].state = READY; // Init thread state threads[id].suspend_state = SUSPEND_STATE_IDLE; threads[id].priority = priority; CONTEXT_SWITCH_PREAMBLE(); mos_tlist_add(&readyQ[priority], &threads[id]); mos_enable_ints(int_handle); if(running) dispatcher(); return THREAD_OK;}uint8_t mos_thread_new_havestack(void (*function_start) (void), uint16_t stack_size, stackval_t* stack_addr, uint8_t priority){ handle_t int_handle; uint8_t id, i; int_handle = mos_disable_ints(); for(id = 0; id < MAX_THREADS; id++) { if(threads[id].state == EMPTY) break; } if(id == MAX_THREADS) { mos_enable_ints(int_handle); return NO_MORE_THREADS; } // Stack space is already allocated, but check pointer anyway if(stack_addr == NULL) { mos_enable_ints(int_handle); return NO_MORE_MEMORY; // Can't continue if we don't have memory } // Make it look like the stack was allocated from the memory manager. // This will allow us to free it in case the thread exits. // (I originally wrote this function to avoid the overhead of the memory // manager. But this "overhead" is only six bytes per block. The real // usefulness of this function is that we can see the stack during static // analysis.) node_t *block = (node_t *)stack_addr; stack_size -= sizeof(node_t); stack_addr += sizeof(node_t); block->size = stack_size; // Flag the block for debugging, normally memory manager does this uint16_t j; for(j = 0; j < stack_size; j++) stack_addr[j] = 0xEF; // Now save the memory addr and point to the top of the stack. threads[id].stack = stack_addr; stack_addr += stack_size - 1; threads[id].stackSize = stack_size; threads[id].func = function_start; threads[id].state = READY; // Init thread state threads[id].suspend_state = SUSPEND_STATE_IDLE; threads[id].priority = priority; CONTEXT_SWITCH_PREAMBLE(); mos_tlist_add(&readyQ[priority], &threads[id]); mos_enable_ints(int_handle); if(running) dispatcher(); return THREAD_OK;}/** @brief A wrapper for starting threads so we can guarantee that they are * de-allocated after completion. */void start_wrapper(void){ _current_thread->func(); mos_thread_exit();}void mos_thread_exit(void){ uint8_t id; handle_t int_handle; int_handle = mos_disable_ints(); // Find the id of the currently running thread for(id = 0; id < MAX_THREADS; id++) { if(&threads[id] == _current_thread) break; } // De-allocate the stack memory and free the thread space mos_mem_free(threads[id].stack); threads[id].state = EMPTY; mos_enable_ints(int_handle); dispatcher();}/** @brief Sets the timer value to trigger the dispatch function. * * We can't set it to the exact output compare value because * it could get missed so we give it a couple cycles spare time. * * trigger_dispatch() not used *//*inline void trigger_dispatch(void){ DO_SOFT_INT();}*/#ifdef DEBUG_MEMORY// Print list of allocated threads and their stack usagevoid print_threads(uint8_t verbose){ uint8_t nt = 0; uint16_t totstack = 0; uint16_t usestack = 0; uint8_t ok = 1; uint8_t i; for(i = 0; i < MAX_THREADS; i++) { if(threads[i].state != EMPTY) { // check for flag bytes that haven't been clobbered uint16_t unused = mos_check_stack(&threads[i]); if(verbose) printf_P(sThreadRow, i, threads[i].sp, threads[i].stack, threads[i].stackSize, unused, threads[i].state, threads[i].priority); nt++; totstack += threads[i].stackSize; usestack += threads[i].sp - threads[i].stack; if(threads[i].sp < threads[i].stack) { printf_P(sStackOver, i); ok = 0; } if(unused == 0) { printf_P(sStackFull, i); ok = 0; } } } printf_P(sThreadTot, nt, totstack, usestack);}#endifSLEEP_INT_HEADER(){ if(SLEEP_TIMER_EXPIRED) { SET_TSLICE_TIMER_VALUE(0); DISABLE_SLEEP_TIMER(); ENABLE_TSLICE_TIMER(); //we have woken up from sleep, idle thread will call dispatcher if(running) mos_thread_wakeup(last_sleep_time); }}TSLICE_INT_HEADER(){ static uint16_t sleep_time = 0; if(TSLICE_TIMER_EXPIRED) { //the time slice has gone off, trigger a dispatch sleep_time += (10 * TIMESLICE_20_MS) / (CLOCK_SPEED_1024 / 100); if(running) { mos_thread_wakeup(sleep_time); sleep_time = 0; } }}/*SOFT_INT_HEADER(){ //PORTE |= (1 << TRIGGER_INT_BIT); DISABLE_SOFT_INT(); uint16_t sleep_time; if (TSLICE_TIMER_VALUE < 8) sleep_time = 1; else sleep_time = (10 * TSLICE_TIMER_VALUE) / (CLOCK_SPEED_1024 / 100); TSLICE_TIMER_VALUE = 0; //software interrupt occurred, trigger a dispatch if(running) mos_thread_wakeup (sleep_time);}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -