/** * @ingroup SystemInit * This function will startup scheduler. It will select one thread * with the highest priority level, then switch to it. */ void rt_system_scheduler_start(void) { register struct rt_thread *to_thread; register rt_ubase_t highest_ready_priority; #if RT_THREAD_PRIORITY_MAX > 32 register rt_ubase_t number; number = __rt_ffs(rt_thread_ready_priority_group) - 1; highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #else highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; #endif /* get switch to thread */ to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, struct rt_thread, tlist); rt_current_thread = to_thread; /* switch to new thread */ rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp); /* never come back */ }
/* * Mask off any voltages we don't support and select * the lowest voltage */ rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr) { int bit; extern int __rt_ffs(int value); ocr &= host->valid_ocr; bit = __rt_ffs(ocr); if (bit) { bit -= 1; ocr &= 3 << bit; host->io_cfg.vdd = bit; mmcsd_set_iocfg(host); } else { rt_kprintf("host doesn't support card's voltages\n"); ocr = 0; } return ocr; }
static struct rt_prio_queue_item* _do_pop(struct rt_prio_queue *que) { int ffs; struct rt_prio_queue_item *item; ffs = __rt_ffs(que->bitmap); if (ffs == 0) return RT_NULL; ffs--; item = que->head[ffs]; RT_ASSERT(item); que->head[ffs] = item->next; if (que->head[ffs] == RT_NULL) { que->bitmap &= ~(1 << ffs); } return item; }
static void fh_gpio_interrupt(int irq, void *param) { rt_uint32_t irq_status; int gpio_num, gpio; rt_uint32_t base; // struct fh_gpio_obj *gpio_obj = (struct fh_gpio_obj *)param; // rt_kprintf("fh_gpio_interrupt start\n"); // fixme: spin lock??? base = (irq == 40) ? GPIO0_REG_BASE : GPIO1_REG_BASE; irq_status = GET_REG(base + REG_GPIO_INTSTATUS); if (irq_status == 0) { rt_kprintf("gpio irq status is zero.\n"); return; } /* temporarily mask (level sensitive) parent IRQ */ gpio_irq_mask(irq); gpio_num = __rt_ffs(irq_status) - 1; SET_REG(base + REG_GPIO_PORTA_EOI, BIT(gpio_num)); gpio = gpio_num + ((irq == 40) ? 0 : 32); // generic_handle_irq(gpio_to_irq(gpio)); if (irq_desc[gpio_to_irq(gpio)].handler) irq_desc[gpio_to_irq(gpio)].handler(gpio_to_irq(gpio), irq_desc[gpio_to_irq(gpio)].param); gpio_irq_mask(irq); /* now it may re-trigger */ }
/** * This function will perform one schedule. It will select one thread * with the highest priority level, then switch to it. */ void rt_schedule(void) { rt_base_t level; struct rt_thread *to_thread; struct rt_thread *from_thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* check the scheduler is enabled or not */ if (rt_scheduler_lock_nest == 0) { register rt_ubase_t highest_ready_priority; #if RT_THREAD_PRIORITY_MAX <= 32 highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; #else register rt_ubase_t number; number = __rt_ffs(rt_thread_ready_priority_group) - 1; highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #endif /* get switch to thread */ to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, struct rt_thread, tlist); /* if the destination thread is not the same as current thread */ if (to_thread != rt_current_thread) { rt_current_priority = (rt_uint8_t)highest_ready_priority; from_thread = rt_current_thread; rt_current_thread = to_thread; RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (from_thread, to_thread)); /* switch to new thread */ RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("[%d]switch to priority#%d " "thread:%.*s(sp:0x%p), " "from thread:%.*s(sp: 0x%p)\n", rt_interrupt_nest, highest_ready_priority, RT_NAME_MAX, to_thread->name, to_thread->sp, RT_NAME_MAX, from_thread->name, from_thread->sp)); #ifdef RT_USING_OVERFLOW_CHECK _rt_scheduler_stack_check(to_thread); #endif if (rt_interrupt_nest == 0) { rt_hw_context_switch((rt_uint32_t)&from_thread->sp, (rt_uint32_t)&to_thread->sp); } else { RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n")); rt_hw_context_switch_interrupt((rt_uint32_t)&from_thread->sp, (rt_uint32_t)&to_thread->sp); } } } /* enable interrupt */ rt_hw_interrupt_enable(level); }