?? stellaris.c
字號:
} return s->fifo[n].data[tail];}static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n, uint32_t value){ int head; head = (s->fifo[n].state >> 4) & 0xf; if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) { s->ostat |= 1 << n; return; } s->fifo[n].data[head] = value; head = (head + 1) & 0xf; s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY; s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4); if ((s->fifo[n].state & 0xf) == head) s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;}static void stellaris_adc_update(stellaris_adc_state *s){ int level; level = (s->ris & s->im) != 0; qemu_set_irq(s->irq, level);}static void stellaris_adc_trigger(void *opaque, int irq, int level){ stellaris_adc_state *s = (stellaris_adc_state *)opaque; /* Some applications use the ADC as a random number source, so introduce some variation into the signal. */ static uint32_t noise = 0; if ((s->actss & 1) == 0) { return; } noise = noise * 314159 + 1; /* ??? actual inputs not implemented. Return an arbitrary value. */ stellaris_adc_fifo_write(s, 0, 0x200 + ((noise >> 16) & 7)); s->ris |= 1; stellaris_adc_update(s);}static void stellaris_adc_reset(stellaris_adc_state *s){ int n; for (n = 0; n < 4; n++) { s->ssmux[n] = 0; s->ssctl[n] = 0; s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY; }}static uint32_t stellaris_adc_read(void *opaque, target_phys_addr_t offset){ stellaris_adc_state *s = (stellaris_adc_state *)opaque; /* TODO: Implement this. */ offset -= s->base; if (offset >= 0x40 && offset < 0xc0) { int n; n = (offset - 0x40) >> 5; switch (offset & 0x1f) { case 0x00: /* SSMUX */ return s->ssmux[n]; case 0x04: /* SSCTL */ return s->ssctl[n]; case 0x08: /* SSFIFO */ return stellaris_adc_fifo_read(s, n); case 0x0c: /* SSFSTAT */ return s->fifo[n].state; default: break; } } switch (offset) { case 0x00: /* ACTSS */ return s->actss; case 0x04: /* RIS */ return s->ris; case 0x08: /* IM */ return s->im; case 0x0c: /* ISC */ return s->ris & s->im; case 0x10: /* OSTAT */ return s->ostat; case 0x14: /* EMUX */ return s->emux; case 0x18: /* USTAT */ return s->ustat; case 0x20: /* SSPRI */ return s->sspri; case 0x30: /* SAC */ return s->sac; default: cpu_abort(cpu_single_env, "strllaris_adc_read: Bad offset 0x%x\n", (int)offset); return 0; }}static void stellaris_adc_write(void *opaque, target_phys_addr_t offset, uint32_t value){ stellaris_adc_state *s = (stellaris_adc_state *)opaque; /* TODO: Implement this. */ offset -= s->base; if (offset >= 0x40 && offset < 0xc0) { int n; n = (offset - 0x40) >> 5; switch (offset & 0x1f) { case 0x00: /* SSMUX */ s->ssmux[n] = value & 0x33333333; return; case 0x04: /* SSCTL */ if (value != 6) { cpu_abort(cpu_single_env, "ADC: Unimplemented sequence %x\n", value); } s->ssctl[n] = value; return; default: break; } } switch (offset) { case 0x00: /* ACTSS */ s->actss = value & 0xf; if (value & 0xe) { cpu_abort(cpu_single_env, "Not implemented: ADC sequencers 1-3\n"); } break; case 0x08: /* IM */ s->im = value; break; case 0x0c: /* ISC */ s->ris &= ~value; break; case 0x10: /* OSTAT */ s->ostat &= ~value; break; case 0x14: /* EMUX */ s->emux = value; break; case 0x18: /* USTAT */ s->ustat &= ~value; break; case 0x20: /* SSPRI */ s->sspri = value; break; case 0x28: /* PSSI */ cpu_abort(cpu_single_env, "Not implemented: ADC sample initiate\n"); break; case 0x30: /* SAC */ s->sac = value; break; default: cpu_abort(cpu_single_env, "stellaris_adc_write: Bad offset 0x%x\n", (int)offset); } stellaris_adc_update(s);}static CPUReadMemoryFunc *stellaris_adc_readfn[] = { stellaris_adc_read, stellaris_adc_read, stellaris_adc_read};static CPUWriteMemoryFunc *stellaris_adc_writefn[] = { stellaris_adc_write, stellaris_adc_write, stellaris_adc_write};static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq){ stellaris_adc_state *s; int iomemtype; qemu_irq *qi; s = (stellaris_adc_state *)qemu_mallocz(sizeof(stellaris_adc_state)); s->base = base; s->irq = irq; iomemtype = cpu_register_io_memory(0, stellaris_adc_readfn, stellaris_adc_writefn, s); cpu_register_physical_memory(base, 0x00001000, iomemtype); stellaris_adc_reset(s); qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1); return qi[0];}/* Some boards have both an OLED controller and SD card connected to the same SSI port, with the SD card chip select connected to a GPIO pin. Technically the OLED chip select is connected to the SSI Fss pin. We do not bother emulating that as both devices should never be selected simultaneously, and our OLED controller ignores stray 0xff commands that occur when deselecting the SD card. */typedef struct { ssi_xfer_cb xfer_cb[2]; void *opaque[2]; qemu_irq irq; int current_dev;} stellaris_ssi_bus_state;static void stellaris_ssi_bus_select(void *opaque, int irq, int level){ stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; s->current_dev = level;}static int stellaris_ssi_bus_xfer(void *opaque, int val){ stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val);}static void *stellaris_ssi_bus_init(qemu_irq *irqp, ssi_xfer_cb cb0, void *opaque0, ssi_xfer_cb cb1, void *opaque1){ qemu_irq *qi; stellaris_ssi_bus_state *s; s = (stellaris_ssi_bus_state *)qemu_mallocz(sizeof(stellaris_ssi_bus_state)); s->xfer_cb[0] = cb0; s->opaque[0] = opaque0; s->xfer_cb[1] = cb1; s->opaque[1] = opaque1; qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1); *irqp = *qi; return s;}/* Board init. */static stellaris_board_info stellaris_boards[] = { { "LM3S811EVB", 0, 0x0032000e, 0x001f001f, /* dc0 */ 0x001132bf, 0x01071013, 0x3f0f01ff, 0x0000001f, BP_OLED_I2C }, { "LM3S6965EVB", 0x10010002, 0x1073402e, 0x00ff007f, /* dc0 */ 0x001133ff, 0x030f5317, 0x0f0f87ff, 0x5000007f, BP_OLED_SSI | BP_GAMEPAD }};static void stellaris_init(const char *kernel_filename, const char *cpu_model, DisplayState *ds, stellaris_board_info *board){ static const int uart_irq[] = {5, 6, 33, 34}; static const int timer_irq[] = {19, 21, 23, 35}; static const uint32_t gpio_addr[7] = { 0x40004000, 0x40005000, 0x40006000, 0x40007000, 0x40024000, 0x40025000, 0x40026000}; static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; qemu_irq *pic; qemu_irq *gpio_in[5]; qemu_irq *gpio_out[5]; qemu_irq adc; int sram_size; int flash_size; i2c_bus *i2c; int i; flash_size = ((board->dc0 & 0xffff) + 1) << 1; sram_size = (board->dc0 >> 18) + 1; pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model); if (board->dc1 & (1 << 16)) { adc = stellaris_adc_init(0x40038000, pic[14]); } else { adc = NULL; } for (i = 0; i < 4; i++) { if (board->dc2 & (0x10000 << i)) { stellaris_gptm_init(0x40030000 + i * 0x1000, pic[timer_irq[i]], adc); } } stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr); for (i = 0; i < 7; i++) { if (board->dc4 & (1 << i)) { gpio_in[i] = pl061_init(gpio_addr[i], pic[gpio_irq[i]], &gpio_out[i]); } } if (board->dc2 & (1 << 12)) { i2c = i2c_init_bus(); stellaris_i2c_init(0x40020000, pic[8], i2c); if (board->peripherals & BP_OLED_I2C) { ssd0303_init(ds, i2c, 0x3d); } } for (i = 0; i < 4; i++) { if (board->dc2 & (1 << i)) { pl011_init(0x4000c000 + i * 0x1000, pic[uart_irq[i]], serial_hds[i], PL011_LUMINARY); } } if (board->dc2 & (1 << 4)) { if (board->peripherals & BP_OLED_SSI) { void * oled; void * sd; void *ssi_bus; int index; oled = ssd0323_init(ds, &gpio_out[GPIO_C][7]); index = drive_get_index(IF_SD, 0, 0); sd = ssi_sd_init(drives_table[index].bdrv); ssi_bus = stellaris_ssi_bus_init(&gpio_out[GPIO_D][0], ssi_sd_xfer, sd, ssd0323_xfer_ssi, oled); pl022_init(0x40008000, pic[7], stellaris_ssi_bus_xfer, ssi_bus); /* Make sure the select pin is high. */ qemu_irq_raise(gpio_out[GPIO_D][0]); } else { pl022_init(0x40008000, pic[7], NULL, NULL); } } if (board->dc4 & (1 << 28)) { /* FIXME: Obey network model. */ stellaris_enet_init(&nd_table[0], 0x40048000, pic[42]); } if (board->peripherals & BP_GAMEPAD) { qemu_irq gpad_irq[5]; static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d }; gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */ gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */ gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */ gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */ gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */ stellaris_gamepad_init(5, gpad_irq, gpad_keycode); }}/* FIXME: Figure out how to generate these from stellaris_boards. */static void lm3s811evb_init(ram_addr_t ram_size, int vga_ram_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model){ stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[0]);}static void lm3s6965evb_init(ram_addr_t ram_size, int vga_ram_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model){ stellaris_init(kernel_filename, cpu_model, ds, &stellaris_boards[1]);}QEMUMachine lm3s811evb_machine = { "lm3s811evb", "Stellaris LM3S811EVB", lm3s811evb_init, (64 * 1024 + 8 * 1024) | RAMSIZE_FIXED,};QEMUMachine lm3s6965evb_machine = { "lm3s6965evb", "Stellaris LM3S6965EVB", lm3s6965evb_init, (256 * 1024 + 64 * 1024) | RAMSIZE_FIXED,};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -