static void transmit_pattern(struct atrf_dsc *dsc, double pause_s, int times) { uint8_t buf[MAX_PSDU]; uint8_t n = 0; int us = fmod(pause_s, 1)*1000000; atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); /* * 180 us, according to AVR2001 section 4.3. We time out after * nominally 200 us. */ wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1); while (run) { memset(buf, n, sizeof(buf)); atrf_buf_write(dsc, buf, sizeof(buf)); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); /* wait up to 10 ms (nominally) */ wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_PLL_LOCK, 10); if (pause_s >= 1) sleep(pause_s); if (us) usleep(us); if (times && !--times) break; n++; } }
static void transmit(struct atrf_dsc *dsc, const char *msg, int hex, int times) { uint8_t buf[MAX_PSDU]; int len; atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); /* * 180 us, according to AVR2001 section 4.3. We time out after * nominally 200 us. */ wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1); /* * We need to copy the message to append the CRC placeholders. */ if (hex) { len = dehex(buf, msg); } else { strcpy((void *) buf, msg); len = strlen(msg); } atrf_buf_write(dsc, buf, len+2); while (run && times--) { /* @@@ should wait for clear channel */ atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); /* wait up to 10 ms (nominally) */ wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_PLL_LOCK, 10); } }
static void rtt_master(struct atrf_dsc *dsc, int packets, int size) { uint8_t buf[size+2]; /* +CRC */ struct timeval t0, t1; uint8_t irq; int first = 1; double min = 0, max = 0, sum = 0, sum2 = 0, d; int lost = 0, n; int i; memset(buf, 0, size+2); for (i = 0; i != packets; i++) { atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); atrf_buf_write(dsc, buf, size+2); gettimeofday(&t0, NULL); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); /* prepare transition to RX_ON while still sending */ while ((atrf_reg_read(dsc, REG_TRX_STATUS) & TRX_STATUS_MASK) == TRX_STATUS_TRANSITION); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); /* wait for transmission to end */ wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK | IRQ_AMI, 1); /* wait for reception */ irq = wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK | IRQ_AMI, 1000); if (irq) { gettimeofday(&t1, NULL); d = t1.tv_sec-t0.tv_sec+(t1.tv_usec-t0.tv_usec)*1e-6; sum += d; sum2 += d*d; if (first || d < min) min = d; if (first || d > max) max = d; first = 0; n = atrf_buf_read(dsc, buf, size); if (n != size) fprintf(stderr, "%d bytes received\n", n); } else { lost++; } } n = packets-lost; printf("%d sent, %d received, %d lost (%g%%)\n", packets, n, lost, lost*100.0/packets); if (n) printf("rtt min/avg/max = %.3f/%.3f/%.3f ms, mdev = %.3f ms\n", min*1000.0, sum*1000.0/n, max*1000.0, sqrt((sum2-sum*sum/n)/n)*1000.0); }
/* No private data for IPC */ void ipc_platform_do_cmd(struct ipc *ipc) { struct sof_ipc_reply reply; int32_t err; /* perform command and return any error */ err = ipc_cmd(); if (err > 0) { mailbox_hostbox_read(&reply, SOF_IPC_MSG_MAX_SIZE, 0, sizeof(reply)); goto done; /* reply created and copied by cmd() */ } else if (err < 0) { /* send std error reply */ reply.error = err; } else if (err == 0) { /* send std reply */ reply.error = 0; } /* send std error/ok reply */ reply.hdr.cmd = SOF_IPC_GLB_REPLY; reply.hdr.size = sizeof(reply); done: spi_push(spi_get(SOF_SPI_INTEL_SLAVE), &reply, sizeof(reply)); ipc->host_pending = 0; // TODO: signal audio work to enter D3 in normal context /* are we about to enter D3 ? */ if (ipc->pm_prepare_D3) { while (1) wait_for_interrupt(0); } }
void process_text(char *in_buffer) { uint8_t last_pos = *ringbuffer_pos; char buffer[64] = {0}; while(1) { uint8_t new_pos; while(last_pos == (new_pos = *ringbuffer_pos)) { uint64_t info = wait_for_interrupt(); if(INT_ID(info) == CLOCK_ID) { toggle_pos(cursor_pos, normal, inverted); } } while(last_pos != new_pos) { uint8_t c; c = keyboard_ringbuffer[last_pos]; process_char(c,1); last_pos = ((last_pos + 1) % RINGBUFFER_SIZE); if(c == '\r') { strcpy(in_buffer, input); process_char('\r',0); input_size = 0; memset(input,0,sizeof(input)); goto done; } } } done: return; }
static struct atrf_dsc *init_txrx(const char *driver, int trim, unsigned mhz) { struct atrf_dsc *dsc; dsc = atrf_open(driver); if (!dsc) exit(1); atrf_reset_rf(dsc); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF); #if 1 // def HAVE_USB /* @@@ yeah, ugly */ atrf_reg_write(dsc, REG_XOSC_CTRL, (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim); #else atrf_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT); #endif if (!atrf_set_clkm(dsc, mhz)) if (mhz) { atrf_close(dsc); exit(1); } /* We want to see all interrupts, not only the ones we're expecting. */ atrf_reg_write(dsc, REG_IRQ_MASK, 0xff); flush_interrupts(dsc); if (atrf_identify(dsc) == atrf_at86rf231) wait_for_interrupt(dsc, IRQ_CCA_ED_DONE, IRQ_CCA_ED_DONE, 1); /* according to table 7-1, 37 us max */ return dsc; }
/* * This test tests the wait_for_interrupt() function. The boot process * creates another process. This process enters a loop. For * each interation it calls wait_for_interrupt (TIMER_IRQ) to cause * a short delay before the next interation. */ void isr_process(PROCESS self, PARAM param) { int ticks; int i; unsigned char* screen_base; kprintf("Process: %s\n", self->name); kprintf("ABCDEF"); /* screen_base points to the beginning of the string "ABCDEF" */ screen_base = (unsigned char*) 0xb8000 + 4 * 80 * 2; i = 0; int j; for (j = 0; j < 30; j ++) { ticks = 3; while (ticks--) wait_for_interrupt(TIMER_IRQ); *(screen_base + i * 2) = *(screen_base + i * 2) + 1; i++; if (i == 6) i = 0; check_sum ++; } return_to_boot(); }
static void ping_tx(struct atrf_dsc *dsc, const struct ping *pck) { atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); /* * 180 us, according to AVR2001 section 4.3. We time out after * nominally 200 us. */ wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1); atrf_buf_write(dsc, pck, sizeof(*pck)); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); /* wait up to 10 ms (nominally) */ wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_PLL_LOCK, 10); }
static void receive_message(struct atrf_dsc *dsc, int hex) { uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */ int n, ok, i; uint8_t ed, lqi; fprintf(stderr, "Ready.\n"); wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START | IRQ_AMI, 0); if (!run) return; n = atrf_buf_read(dsc, buf, sizeof(buf)); if (n < 0) exit(1); if (n < 3) { fprintf(stderr, "%d bytes received\n", n); exit(1); } ed = atrf_reg_read(dsc, REG_PHY_ED_LEVEL); ok = !!(atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID); lqi = buf[n-1]; fprintf(stderr, "%d bytes payload, CRC %s, LQI %u, ED %d dBm\n", n-3, ok ? "OK" : "BAD", lqi, -91+ed); if (hex) { for (i = 0; i != n-3; i++) printf("%s%02x", i ? " " : "", buf[i]); } else { for (i = 0; i != n-3; i++) putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]); } putchar('\n'); }
void switch_tasks() { uint32_t eflags = disable_interrupts(); task_t *old_task = current_task(); task_t *current_candidate = old_task->next; task_t *first_candidate = current_candidate; task_t *selected = NULL; // Buscamos una tarea que este lista para ejecutarse. Si no hay ninguna, // hacemos halt hasta que ocurra una interrupcion. do { do { if (!(current_candidate->waiting)) { selected = current_candidate; break; } current_candidate = current_candidate->next; } while(current_candidate != first_candidate); if (selected == NULL) { outb(PIC1_DATA, (PIC_ALL_ENABLED & (~PIC_TIMER)) | PIC_TIMER); wait_for_interrupt(); outb(PIC1_DATA, PIC_ALL_ENABLED); } } while (selected == NULL); task_list = selected; switch_context(old_task, current_task()); restore_eflags(eflags); }
void timer_notifier(PROCESS self, PARAM param) { while (42) { // kprintf("I am running!\n"); wait_for_interrupt(TIMER_IRQ); // kprintf("Got timer IRQ\n"); message(timer_port, NULL); } }
/* 游戏主循环。 * 在初始化工作结束后,main函数就跳转到主循环执行。 * 在主循环执行期间随时会插入异步的中断。时钟中断最终调用timer_event, * 键盘中断最终调用keyboard_event。中断处理完成后将返回主循环原位置继续执行。 * * tick是时钟中断中维护的信号,数值含义是“系统到当前时刻已经发生过的时钟中断数” * HZ是时钟控制器硬件每秒产生的中断数,在include/device/timer.h中定义 * now是主循环已经正确处理的时钟中断数,即游戏已经处理到的物理时间点 * * 由于qemu-kvm在访问内存映射IO区域时每次都会产生陷入,在30FPS时, * 对显存区域每秒会产生30*320*200/4次陷入,从而消耗过多时间导致跳帧的产生(实际FPS<30)。 * 在CFLAGS中增加-DSLOW可以在此情况下提升FPS。如果FPS仍太小,可以尝试 * -DTOOSLOW,此时将会采用隔行扫描的方式更新屏幕(可能会降低显示效果)。 * 这些机制的实现在device/video.c中。 * */ void main_loop(void) { int now = 0, target; int num_draw = 0; bool redraw; while (TRUE) { wait_for_interrupt(); disable_interrupt(); if (now == tick) { enable_interrupt(); continue; } assert(now < tick); target = tick; /* now总是小于tick,因此我们需要“追赶”当前的时间 */ enable_interrupt(); redraw = FALSE; while (update_keypress()) ; /* 依次模拟已经错过的时钟中断。一次主循环如果执行时间长,期间可能到来多次时钟中断, * 从而主循环中维护的时钟可能与实际时钟相差较多。为了维持游戏的正常运行,必须补上 * 期间错过的每一帧游戏逻辑。 */ while (now < target) { /* 每隔一定时间产生一个新的字符 */ if (now % (HZ / CHARACTER_PER_SECOND) == 0) { create_new_letter(); } /* 每隔一定时间更新屏幕上字符的位置 */ if (now % (HZ / UPDATE_PER_SECOND) == 0) { update_letter_pos(); } /* 每隔一定时间需要刷新屏幕。注意到这里实现了“跳帧”的机制:假设 * HZ = 1000, FPS = 100, now = 10, target = 1000 * 即我们要模拟990个时钟中断之间发生的事件,其中包含了9次屏幕更新, * 但redraw flag只被置一次。 */ if (now % (HZ / FPS) == 0) { redraw = TRUE; } /* 更新fps统计信息 */ if (now % (HZ / 2) == 0) { int now_fps = num_draw * 2 + 1; if (now_fps > FPS) now_fps = FPS; set_fps(now_fps); num_draw = 0; } now ++; } if (redraw) { /* 当需要重新绘图时重绘 */ num_draw ++; redraw_screen(); } } }
int abort(const char *fname, int line) { /* 当程序遇到不可恢复的错误时,首先将外部中断关闭以防其他错误发生, * 然后显示出错信息后,等待下一个中断到来(实际永远等不到)。*/ disable_interrupt(); blue_screen(fname, line); while (TRUE) { wait_for_interrupt(); } }
static void start_test_mode_231(struct atrf_dsc *dsc) { atrf_reg_write(dsc, REG_PART_NUM, 0x54); /*13 */ atrf_reg_write(dsc, REG_PART_NUM, 0x46); /*14 */ atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); /*15 */ wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 0); /*16 */ atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); /*17 */ }
int _start(void) { crash_handler_word[0] = crash_handler; int max = 1000; cursor_pos = INITIAL_CURSOR_POS; clear_screen_with_border(BACKGROUND, FOREGROUND, border_size); banner(); uint32_t number = (getrand()%max)+1; int remaining = 1337; while(1) { char buffer[32] = {0}; char *episode_name = NULL; int season = getrand()%7;; int episode_number; if(season == 0) { episode_number = getrand()%12; } else { episode_number = getrand()%22; } episode_name = episodes[season][episode_number]; episode_number++; season++; //format the question question[29] = (episode_number >= 10) ? ('0' + (episode_number/10)) : ' '; question[30] = '0' + (episode_number%10); question[42] = '0' + season; //ask the question process_string(question); process_text(buffer); if(0 == strcasecmp(buffer,episode_name)) { if(remaining == 0) { print_secret(); break; } else { process_string("Correct! get "); print_number(remaining--); process_string(" more correct to learn the password\r\r"); } } else { process_string("Wrong! The answer is \""); process_string(episode_name); process_string("\"\r\r"); } } //infinite loop while(1) { wait_for_interrupt(); } }
static void sweep(struct atrf_dsc *dsc, int *z) { int chan; for (chan = 11; chan <= 26; chan++) { atrf_reg_write(dsc, REG_PHY_CC_CCA, chan); /* 150 us, according to AVR2001 section 3.5 */ wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1); *z++ = Z_STEP*atrf_reg_read(dsc, REG_PHY_RSSI) & RSSI_MASK; #if 0 if (chan >= 13 && chan <= 19 ) z[-1] = 3*28-(chan-16)*(chan-16)*(chan-16)*(chan-16); #endif } }
static void enter_test_mode_230(struct atrf_dsc *dsc, uint8_t cont_tx) { atrf_buf_write(dsc, "", 1); atrf_reg_write(dsc, REG_CONT_TX_0, CONT_TX_MAGIC); atrf_reg_write(dsc, REG_CONT_TX_1, cont_tx); if (!atrf_test_mode(dsc)) { atrf_reset_rf(dsc); fprintf(stderr, "device does not support test mode\n"); exit(1); } atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 0); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); }
void com_reader_process (PROCESS self, PARAM param) { PORT reply_port; PROCESS sender_proc; COM_Message* msg; int i; reply_port = (PORT) param; while (1) { msg = (COM_Message*) receive (&sender_proc); i = 0; while (i != msg->len_input_buffer) { wait_for_interrupt (COM1_IRQ); msg->input_buffer[i++] = inportb (COM1_PORT); } message (reply_port, &msg); } }
static int wait_byte_done(int port) { uint8_t sts = MEC1322_I2C_STATUS(port); int rv; int event = 0; while (sts & STS_PIN) { rv = wait_for_interrupt(port, &event); if (rv) return rv; sts = MEC1322_I2C_STATUS(port); } /* * Restore any events that we saw while waiting. TASK_EVENT_TIMER isn't * one, because we've handled it above. */ task_set_event(task_get_current(), event, 0); return sts & STS_LRB; }
void play(void) { //主循环 const char *text = "http://cslab.nju.edu.cn/opsystem"; static char buf[2]; int text_len = 32; int w = SCR_WIDTH / 8; int color = 0, start_pos = 0, clk = 0; for (; ; clk = (clk + 1) % 5) { // 主循环是一个死循环 int i; prepare_buffer(); // 在绘图之前,先需要准备缓冲区 if (clk == 0) { start_pos = (start_pos + 1) % w; } color = (color + 1) % 72; for (i = 0; i < text_len; i ++) { // 计算每个字符的位置 然后显示在屏幕上 int j = (i + start_pos) % w; int d = 50 * sin(2 * PI * j / w); buf[0] = text[i]; draw_string(buf, 8 * j, SCR_HEIGHT / 2 - 4 + d, 32 + color); } // 在左下角显示键盘扫描码 draw_string(itoa(last_key), 0, SCR_HEIGHT - 8, live > 0 ? 10: 7); if (live > 0) live --; i = HZ / 60; while (i) { wait_for_interrupt(); disable_interrupt(); // 关闭中断是为了防止数据竞争(data race)。 if (timers > 0) { timers --; i --; } enable_interrupt(); } display_buffer(); // 绘图结束后,调用这个函数将绘制的图像显示到屏幕上 } }
static void sweep(struct atrf_dsc *dsc) { int chan, rssi; struct timeval t; for (chan = 11; chan <= 26; chan++) { atrf_reg_write(dsc, REG_PHY_CC_CCA, chan); /* 150 us, according to AVR2001 section 3.5 */ wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1); gettimeofday(&t, NULL); rssi = atrf_reg_read(dsc, REG_PHY_RSSI) & RSSI_MASK; t.tv_sec -= t0.tv_sec; t.tv_usec -= t0.tv_usec; printf("%d %f %d\n", 2405+(chan-11)*5, (double) t.tv_sec+t.tv_usec/1000000.0, -91+3*(rssi-1)); } printf("\n"); }
void process_text(char *in_buffer, int remaining) { uint8_t last_pos = *ringbuffer_pos; char buffer[64] = {0}; if(remaining > 0) { //Dammit there's no standard library so I can't use sprintf :( strcpy(buffer,"You have guesses remaining\r>"); if(remaining >= 10) { buffer[9] = '0' + (remaining/10); } buffer[10] = '0' + (remaining%10); process_string(buffer); } else { process_string("You ran out, I picked a new number\r>"); } while(1) { uint8_t new_pos; while(last_pos == (new_pos = *ringbuffer_pos)) { uint64_t info = wait_for_interrupt(); if(INT_ID(info) == CLOCK_ID) { toggle_pos(cursor_pos, normal, inverted); } } while(last_pos != new_pos) { uint8_t c; c = keyboard_ringbuffer[last_pos]; process_char(c,1); last_pos = ((last_pos + 1) % RINGBUFFER_SIZE); if(c == '\r') { memcpy(in_buffer, input, input_size); input_size = 0; memset(input,0,sizeof(input)); goto done; } } } done: return; }
static int wait_idle(int port) { uint8_t sts = MEC1322_I2C_STATUS(port); int rv; int event = 0; while (!(sts & STS_NBB)) { rv = wait_for_interrupt(port, &event); if (rv) return rv; sts = MEC1322_I2C_STATUS(port); } /* * Restore any events that we saw while waiting. TASK_EVENT_TIMER isn't * one, because we've handled it above. */ task_set_event(task_get_current(), event, 0); if (sts & (STS_BER | STS_LAB)) return EC_ERROR_UNKNOWN; return EC_SUCCESS; }
static enum rx_res ping_rx(struct atrf_dsc *dsc, struct ping *pck, int wait_ms) { uint8_t irq; int n; atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); irq = wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START | IRQ_PLL_LOCK, wait_ms); if (!run) return rx_exit; if (!irq) return rx_timeout; n = atrf_buf_read(dsc, pck, sizeof(*pck)); if (n < 0) exit(1); if (n != sizeof(*pck)) { fprintf(stderr, "%d bytes received\n", n); return rx_bad; } return atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID ? rx_good : rx_bad; }
int _start(void) { crash_handler_word[0] = crash_handler; int max = 1000; cursor_pos = INITIAL_CURSOR_POS; clear_screen_with_border(BACKGROUND, FOREGROUND, border_size); banner(); uint32_t number = (getrand()%max)+1; int remaining = 10; while(1) { char buffer[64] = {0}; process_text(buffer,remaining); if(remaining <= 0) { number = (getrand()%max)+1; remaining = 10; } int guess = atoi(buffer); if(guess <= 0 || guess > max) { process_string("That is not a valid guess\r"); } else if(guess == number) { process_string("Correct! The first word to the passphrase is \"sulphuric\"\r"); process_string("Please reset now\r"); break; } else if(guess < number) { process_string("Your guess is too low\r"); } else { process_string("Your guess is too high\r"); } remaining -= 1; } //infinite loop while(1) { wait_for_interrupt(); } }
void kentry(void) { init_serial(); //初始化串口输出 init_idt(); init_timer(); init_intr(); init_seg(); //getKeyCode(); uint32_t entry = load_umain(); init_pcb(entry); //putchar('A'); asm volatile("movl %%eax, %%esp" ::"a"(&idle.regs.esp)); enable_interrupt(); while(1){ //putchar('^'); wait_for_interrupt(); } ///p_idle(); //enter_user_space(entry); while(1); }
/* 游戏主循环。 * 在初始化工作结束后,main函数就跳转到主循环执行。 * 在主循环执行期间随时会插入异步的中断。时钟中断最终调用timer_event, * 键盘中断最终调用keyboard_event。中断处理完成后将返回主循环原位置继续执行。 * * tick是时钟中断中维护的信号,数值含义是“系统到当前时刻已经发生过的时钟中断数” * HZ是时钟控制器硬件每秒产生的中断数,在include/device/timer.h中定义 * now是主循环已经正确处理的时钟中断数,即游戏已经处理到的物理时间点 * * 由于qemu-kvm在访问内存映射IO区域时每次都会产生陷入,在30FPS时, * 对显存区域每秒会产生30*320*200/4次陷入,从而消耗过多时间导致跳帧的产生(实际FPS<30)。 * 在CFLAGS中增加-DSLOW可以在此情况下提升FPS。如果FPS仍太小,可以尝试 * -DTOOSLOW,此时将会采用隔行扫描的方式更新屏幕(可能会降低显示效果)。 * 这些机制的实现在device/video.c中。 * */ void maze_loop(void) { int now = 0, target; int num_draw = 0; bool redraw; Result res = LET; while ( (res = winOrLose()) == LET) { wait_for_interrupt(); disable_interrupt(); if (now == tick) { enable_interrupt(); continue; } assert(now < tick); target = tick; /* now总是小于tick,因此我们需要“追赶”当前的时间 */ enable_interrupt(); redraw = FALSE; while (update_you()) ; /* 依次模拟已经错过的时钟中断。一次主循环如果执行时间长,期间可能到来多次时钟中断, * 从而主循环中维护的时钟可能与实际时钟相差较多。为了维持游戏的正常运行,必须补上 * 期间错过的每一帧游戏逻辑。 */ while (now < target) { /* 每隔一定时间更新屏幕上字符的位置 */ if (now % (HZ / UPDATE_PER_SECOND) == 0) { update_monster(); } // update timer every second if ((now % HZ) == 0) { update_timer(); } /* 每隔一定时间需要刷新屏幕。注意到这里实现了“跳帧”的机制:假设 * HZ = 1000, FPS = 100, now = 10, target = 1000 * 即我们要模拟990个时钟中断之间发生的事件,其中包含了9次屏幕更新, * 但redraw flag只被置一次。 */ if (now % (HZ / FPS) == 0) { redraw = TRUE; } /* 更新fps统计信息 */ if (now % (HZ / 2) == 0) { int now_fps = num_draw * 2 + 1; if (now_fps > FPS) now_fps = FPS; set_mfps(now_fps); num_draw = 0; } now ++; } if (redraw) { /* 当需要重新绘图时重绘 */ num_draw ++; redraw_timerMonsterAndYou(); } } draw_end(res); printk("ending\n"); //release_enter(); }
void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info) { struct vhost_vring_state state = { .index = info->idx }; struct vhost_vring_file file = { .index = info->idx }; unsigned long long features = dev->vdev.features[0]; struct vhost_vring_addr addr = { .index = info->idx, .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc, .avail_user_addr = (uint64_t)(unsigned long)info->vring.avail, .used_user_addr = (uint64_t)(unsigned long)info->vring.used, }; int r; r = ioctl(dev->control, VHOST_SET_FEATURES, &features); assert(r >= 0); state.num = info->vring.num; r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state); assert(r >= 0); state.num = 0; r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state); assert(r >= 0); r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr); assert(r >= 0); file.fd = info->kick; r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file); assert(r >= 0); file.fd = info->call; r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file); assert(r >= 0); } static void vq_info_add(struct vdev_info *dev, int num) { struct vq_info *info = &dev->vqs[dev->nvqs]; int r; info->idx = dev->nvqs; info->kick = eventfd(0, EFD_NONBLOCK); info->call = eventfd(0, EFD_NONBLOCK); r = posix_memalign(&info->ring, 4096, vring_size(num, 4096)); assert(r >= 0); memset(info->ring, 0, vring_size(num, 4096)); vring_init(&info->vring, num, info->ring, 4096); info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev, info->ring, vq_notify, vq_callback, "test"); assert(info->vq); info->vq->priv = info; vhost_vq_setup(dev, info); dev->fds[info->idx].fd = info->call; dev->fds[info->idx].events = POLLIN; dev->nvqs++; } static void vdev_info_init(struct vdev_info* dev, unsigned long long features) { int r; memset(dev, 0, sizeof *dev); dev->vdev.features[0] = features; dev->vdev.features[1] = features >> 32; dev->buf_size = 1024; dev->buf = malloc(dev->buf_size); assert(dev->buf); dev->control = open("/dev/vhost-test", O_RDWR); assert(dev->control >= 0); r = ioctl(dev->control, VHOST_SET_OWNER, NULL); assert(r >= 0); dev->mem = malloc(offsetof(struct vhost_memory, regions) + sizeof dev->mem->regions[0]); assert(dev->mem); memset(dev->mem, 0, offsetof(struct vhost_memory, regions) + sizeof dev->mem->regions[0]); dev->mem->nregions = 1; dev->mem->regions[0].guest_phys_addr = (long)dev->buf; dev->mem->regions[0].userspace_addr = (long)dev->buf; dev->mem->regions[0].memory_size = dev->buf_size; r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem); assert(r >= 0); } /* TODO: this is pretty bad: we get a cache line bounce * for the wait queue on poll and another one on read, * plus the read which is there just to clear the * current state. */ static void wait_for_interrupt(struct vdev_info *dev) { int i; unsigned long long val; poll(dev->fds, dev->nvqs, -1); for (i = 0; i < dev->nvqs; ++i) if (dev->fds[i].revents & POLLIN) { read(dev->fds[i].fd, &val, sizeof val); } } static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs) { struct scatterlist sl; long started = 0, completed = 0; long completed_before; int r, test = 1; unsigned len; long long spurious = 0; r = ioctl(dev->control, VHOST_TEST_RUN, &test); assert(r >= 0); for (;;) { virtqueue_disable_cb(vq->vq); completed_before = completed; do { if (started < bufs) { sg_init_one(&sl, dev->buf, dev->buf_size); r = virtqueue_add_buf(vq->vq, &sl, 1, 0, dev->buf + started); if (likely(r >= 0)) { ++started; virtqueue_kick(vq->vq); } } else r = -1; /* Flush out completed bufs if any */ if (virtqueue_get_buf(vq->vq, &len)) { ++completed; r = 0; } } while (r >= 0); if (completed == completed_before) ++spurious; assert(completed <= bufs); assert(started <= bufs); if (completed == bufs) break; if (virtqueue_enable_cb(vq->vq)) { wait_for_interrupt(dev); } } test = 0; r = ioctl(dev->control, VHOST_TEST_RUN, &test); assert(r >= 0); fprintf(stderr, "spurious wakeus: 0x%llx\n", spurious); } const char optstring[] = "h"; const struct option longopts[] = { { .name = "help", .val = 'h', }, { .name = "event-idx",
void arch_cpu_idle(void) { wait_for_interrupt(); local_irq_enable(); }
int main() { int i; int btns_check, sws_check; int ld9_toggle; int uiofd0; // AXI timer int uiofd1; // btns_8bits int uiofd2; // leds_8bits int uiofd3; // sws_8bits const char *uiod0 = "/dev/uio0"; const char *uiod1 = "/dev/uio1"; const char *uiod2 = "/dev/uio2"; const char *uiod3 = "/dev/uio3"; void *uioptr0; void *uioptr1; void *uioptr2; void *uioptr3; printf("-- Example program --\n"); // Open the UIO devices uiofd0 = open(uiod0, O_RDWR); if (uiofd0 < 1) { printf("Invalid UIO device file:%s.\n", uiod0); exit(-1); } uiofd1 = open(uiod1, O_RDWR); if (uiofd1 < 1) { printf("Invalid UIO device file:%s.\n", uiod1); exit(-1); } uiofd2 = open(uiod2, O_RDWR); if (uiofd2 < 1) { printf("Invalid UIO device file:%s.\n", uiod2); exit(-1); } uiofd3 = open(uiod3, O_RDWR); if (uiofd3 < 1) { printf("Invalid UIO device file:%s.\n", uiod3); exit(-1); } // mmap() the UIO devices uioptr0 = mmap(NULL, UIO_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, uiofd0, 0); if (uioptr0 == MAP_FAILED) { printf("mmap call failure.\n"); exit(-1); } uioptr1 = mmap(NULL, UIO_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, uiofd1, 0); if (uioptr1 == MAP_FAILED) { printf("mmap call failure.\n"); exit(-1); } uioptr2 = mmap(NULL, UIO_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, uiofd2, 0); if (uioptr2 == MAP_FAILED) { printf("mmap call failure.\n"); exit(-1); } uioptr3 = mmap(NULL, UIO_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, uiofd3, 0); if (uioptr3 == MAP_FAILED) { printf("mmap call failure.\n"); exit(-1); } // Initialize timer timer_baseaddr = uioptr0; timer_baseaddr_u32 = (unsigned int *) uioptr0; timer_fd = uiofd0; initialize_timer(); //printf("TCSR0=0x%08X TLR0=0x%08X TCR0=0x%08X\n", read32(timer_baseaddr, 0x0), read32(timer_baseaddr, 0x4), read32(timer_baseaddr, 0x8)); printf("-- Press BTNR push button to change the LD9 toggle --\n"); printf("-- Press BTND push button to start the Timer interrupt --\n"); printf("-- Press BTNL push button to exit --\n"); printf("-- Change slide switches to see corresponding output on LEDs --\n"); ld9_toggle = 0; //InterruptFlag = 0; while(1) { btns_check = *((volatile unsigned *) uioptr1); //printf("Buttons Status %x\n", btns_check); sws_check = *((volatile unsigned *) uioptr3); //printf("Switches Status %x\n", sws_check); *((volatile unsigned *) uioptr2) = sws_check; if ((btns_check & 0x08) == 0x08) { printf("BTNR is pressed\n"); printf("Changing the LD9 toggle\n"); ld9_toggle = !ld9_toggle; // FIXME } if ((btns_check & 0x02) == 0x02) { printf("BTND is pressed\n"); printf("Starting the Timer\n"); // Start Timer start_timer(); // Wait for interrupt wait_for_interrupt(); } if ((btns_check & 0x04) == 0x04) { printf("BTNL is pressed\n"); printf("Exiting\n"); break; } for (i=0; i<999999999; i++); // delay loop } // end while loop printf("-- Exiting main() --\n"); // Unmap the UIO devices munmap(uioptr0, UIO_SIZE); munmap(uioptr1, UIO_SIZE); munmap(uioptr2, UIO_SIZE); munmap(uioptr3, UIO_SIZE); return 0; }