void kill_thread(struct thread *thread) { irq_state_t irq; struct thread_block *block; if (thread == current()) __exit_thread(); irq = irq_save(); /* * Muck with the stack so that the next time the thread is run then * we end up going to __exit_thread. */ thread->esp->eip = __exit_thread; thread->prio = INT_MIN; block = thread->blocked; if (block) { struct semaphore *sem = block->semaphore; /* Remove us from the queue and increase the count */ block->list.next->prev = block->list.prev; block->list.prev->next = block->list.next; sem->count++; thread->blocked = NULL; block->timed_out = true; /* Fake an immediate timeout */ } __schedule(); irq_restore(irq); }
void gpio_out_toggle(struct gpio_out g) { irqstatus_t flag = irq_save(); gpio_out_toggle_noirq(g); irq_restore(flag); }
void command_debug_write16(uint32_t *args) { uint16_t *ptr = (void*)(size_t)args[0]; irqstatus_t flag = irq_save(); *ptr = args[1]; irq_restore(flag); }
// Cancel a sample that may have been started with gpio_adc_sample() void gpio_adc_cancel_sample(struct gpio_adc g) { irqstatus_t flag = irq_save(); if ((ADC->ADC_CHSR & 0xffff) == g.bit) gpio_adc_read(g); irq_restore(flag); }
void command_debug_read16(uint32_t *args) { uint16_t *ptr = (void*)(size_t)args[0]; irqstatus_t flag = irq_save(); uint16_t v = *ptr; irq_restore(flag); sendf("debug_result val=%hu", v); }
void up(semaphore_t *s) { unsigned long flags; irq_save(flags); atomic_dec(&s->count); wake_up(&s->wait); irq_restore(flags); }
void down(semaphore_t *s) { unsigned long flags; irq_save(flags); atomic_inc(&s->count); if (atomic_read(&s->count) != 1) { wait(&s->wait); } irq_restore(flags); }
// Cancel a sample that may have been started with gpio_adc_sample() void gpio_adc_cancel_sample(struct gpio_adc g) { uint32_t chan = adc_status.chan; if (chan != g.chan) return; irqstatus_t flag = irq_save(); LPC_ADC->ADCR = adc_status.adcr; adc_status.chan = chan | ADC_DONE; adc_status.pos = ARRAY_SIZE(adc_status.samples); (&LPC_ADC->ADDR0)[chan & 0xff]; irq_restore(flag); }
void create_kernel_thread(void) { irq_state_t irq_state = irq_save(); thread_t *thread = (thread_t *)kmalloc(sizeof(thread_t)); if (!thread) { return; } memset(thread, 0, sizeof(thread_t)); thread->id = request_thread_id(); thread->process = 0; thread->page_dir = current_directory; ++num_threads; schedule_thread(thread); irq_restore(irq_state); }
struct gpio_out gpio_out_setup(uint8_t pin, uint8_t val) { if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) goto fail; Pio *regs = digital_regs[GPIO2PORT(pin)]; uint32_t bit = GPIO2BIT(pin); irqstatus_t flag = irq_save(); if (val) regs->PIO_SODR = bit; else regs->PIO_CODR = bit; regs->PIO_OER = bit; regs->PIO_OWER = bit; regs->PIO_PER = bit; irq_restore(flag); return (struct gpio_out){ .regs=regs, .bit=bit }; fail: shutdown("Not an output pin"); }
struct gpio_in gpio_in_setup(uint8_t pin, int8_t pull_up) { if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) goto fail; uint32_t port = GPIO2PORT(pin); Pio *regs = digital_regs[port]; uint32_t bit = GPIO2BIT(pin); irqstatus_t flag = irq_save(); PMC->PMC_PCER0 = 1 << (ID_PIOA + port); if (pull_up) regs->PIO_PUER = bit; else regs->PIO_PUDR = bit; regs->PIO_ODR = bit; regs->PIO_PER = bit; irq_restore(flag); return (struct gpio_in){ .regs=regs, .bit=bit }; fail: shutdown("Not an input pin"); }
/* all clocks in the 1.8 V domain are stopped, * the PLL, the HSI and the HSE RC oscillators are disabled. * SRAM and register contents are preserved. * all I/O pins keep the same state as in the Run mode. * ADC, DAC, WDG, RTC, LSI_RC, and LSE_OSC can consume power. */ void __enter_stop_mode() { unsigned int irqflag; irq_save(irqflag); local_irq_disable(); PWRCLK_ENABLE(); SCB_SCR |= 4; /* Set SLEEPDEEP bit */ /* Clear PDDS bit in Power Control register (PWR_CR) */ PWR_CR |= 1; /* configure LPDS bit in PWR_CR */ stop_scheduler(); dsb(); __wfi(); clock_init(); run_scheduler(); SCB_SCR &= ~4; PWR_CR &= ~1; PWRCLK_DISABLE(); irq_restore(irqflag); /* wakeup latency: * HSI RC wakeup time + regulator wakeup time from Low-power mode */ /* Note from reference manual: * If the application needs to disable the external clock before * entering Stop mode, the HSEON bit must first be disabled and the * system clock switched to HSI. Otherwise, if the HSEON bit remains * enabled and the external clock (external oscillator) is removed when * entering Stop mode, the clock security system (CSS) feature must be * enabled to detect any external oscillator failure and avoid a * malfunction behavior when entering stop mode. */ //BITBAND(&RCC_CR, CSSON, ON); }
uint32_t create_thread(process_t *process, entry_t entry, void *args, uint32_t priority, int user, int vm86) { /* create thread */ thread_t *thread = (thread_t *)kmalloc(sizeof(thread_t)); if (!thread) { return 0; } memset(thread, 0, sizeof(thread_t)); /* setup the stack(s) */ thread->kstack = (uintptr_t)kmalloc(STACK_SIZE); /* if (user) { uint32_t *stack = (uint32_t *)thread->kstack; (void)stack; DBPRINT("+++ thread->kstack: %x\n", thread->kstack); for (int i = -15; i < 15; ++i) { DBPRINT("%x -> stack[%d] = %x\n", thread->kstack + i, i, stack[i]); } } */ if (!thread->kstack) { return 0; } if (user) { thread->ustack = (uintptr_t)kmalloc(STACK_SIZE); if (!thread->ustack) { return 0; } } uint32_t *kstack = (uint32_t *)stack_top(thread->kstack); uint32_t data_segment = user ? 0x20+3 : 0x10; uint32_t code_segment = user ? 0x18+3 : 0x08; /* bit 2 always set - bit 9 = interruption flag (IF) - bits 12/13 = privilege level * bit 17 = virtua-8086 mode (VM) */ uint32_t eflags = (user ? 0x3202 : 0x0202) | (vm86 ? 1 << 17 : 0 << 17); if (user) { uint32_t *ustack = (uint32_t *)stack_top(thread->ustack); PUSH(ustack, (uintptr_t)args); /* args */ PUSH(ustack, 0xdeadcaca); /* return address - thread should be finished * with a system call, not by jumping to this address */ PUSH(kstack, 0x23); /* ss */ PUSH(kstack, (uintptr_t)ustack); /* esp */ } else { PUSH(kstack, (uintptr_t)args); /* args */ PUSH(kstack, (uintptr_t)&thread_exit); /* return address */ } PUSH(kstack, eflags); /* eflags */ PUSH(kstack, code_segment); /* cs */ PUSH(kstack, (uintptr_t)entry); /* eip */ PUSH(kstack, 0); /* error code */ PUSH(kstack, 0); /* interrupt number */ PUSH(kstack, 0); /* eax */ PUSH(kstack, 0); /* ebx */ PUSH(kstack, 0); /* ecx */ PUSH(kstack, 0); /* edx */ PUSH(kstack, 0); /* esi */ PUSH(kstack, 0); /* edi */ PUSH(kstack, 0); /* ebp */ PUSH(kstack, data_segment); /* ds */ PUSH(kstack, data_segment); /* es */ PUSH(kstack, data_segment); /* fs */ PUSH(kstack, data_segment); /* gs */ thread->esp = (uintptr_t)kstack; thread->ss = data_segment; thread->id = request_thread_id(); thread->process = process; /* thread's priority can't exceed its parent's priority */ thread->priority = min(priority, process->priority); thread->page_dir = process ? process->page_dir : kernel_directory; thread->runtime = 0; irq_state_t irq_state = irq_save(); ++num_threads; /* register this thread */ schedule_thread(thread); irq_restore(irq_state); return thread->id; }