mbed LPC1114 emulator pre-alpha version
Dependencies: BaseV6M mbed F12RFileSystem F32RFileSystem ROMSLOT SDStorage
Fork of emu812 by
TOYOSHIKI TINY BASIC mbed Edition TTB_mbed_LPC1114.bin save as "LPC1114.IMG" .
EMU111x.cpp
- Committer:
- va009039
- Date:
- 2015-08-11
- Revision:
- 2:b8b4f07d4691
- Child:
- 3:5df725af50e0
File content as of revision 2:b8b4f07d4691:
// EMU111x.cpp 2015/8/8 #include "mbed.h" #include "EMU111x.h" #define V6M_LOG_LEVEL 2 #include "v6m_log.h" const int EMU111x_RAM_SIZE = (1024*4); const int EMU111x_FLASH_SIZE = (1024*32); const int EMU111x_ROM_SIZE = (1024*16); const uint32_t EMU111x_FLASH_BASE = 0x00000000; const uint32_t EMU111x_RAM_BASE = 0x10000000; const uint32_t EMU111x_ROM_BASE = 0x1fff0000; const uint32_t EMU111x_APB_BASE = 0x40000000; const uint32_t EMU111x_AHB_BASE = 0x50000000; const uint32_t EMU111x_SCS_BASE = 0xe000e000; EMU111x_SYSCON::EMU111x_SYSCON() { } void EMU111x_SYSCON::poke32(uint32_t a, uint32_t d) { switch(a&0xfff) { case 0x000: V6M_INFO("P: LPC_SYSCON->SYSMEMREMAP << %08x", d); break; case 0x004: V6M_INFO("P: LPC_SYSCON->PRESETCTRL << %08x", d); break; case 0x008: V6M_INFO("P: LPC_SYSCON->SYSPLLCTRL << %08x", d); break; case 0x040: V6M_INFO("P: LPC_SYSCON->SYSPLLCLKSEL << %08x", d); break; case 0x044: V6M_INFO("P: LPC_SYSCON->SYSPLLCLKUEN << %08x", d); break; case 0x070: V6M_INFO("P: LPC_SYSCON->MAINCLKSEL << %08x", d); break; case 0x074: V6M_INFO("P: LPC_SYSCON->MAINCLKUEN << %08x", d); break; case 0x078: V6M_INFO("P: LPC_SYSCON->SYSAHBCLKDIV << %08x", d); break; case 0x080: V6M_INFO("P: LPC_SYSCON->SYSAHBCLKCTRL << %08x", d); break; case 0x094: V6M_INFO("P: LPC_SYSCON->SSP0CLKDIV << %08x", d); break; case 0x098: V6M_INFO("P: LPC_SYSCON->UARTCLKDIV << %08x", d); break; case 0x238: V6M_INFO("P: LPC_SYSCON->PDRUNCFG << %08x", d); break; default: V6M_WARN("P: LPC_SYSCON %08x << %08x", a, d); break; } } uint32_t EMU111x_SYSCON::peek32(uint32_t a) { uint32_t d = 0x00; switch(a&0xfff) { case 0x000: V6M_INFO("P: LPC_SYSCON->SYSMEMREMAP >> %08x", a, d); break; case 0x004: V6M_INFO("P: LPC_SYSCON->PRESETCTRL >> %08x", a, d); break; case 0x00c: d = 0x01; V6M_INFO("P: LPC_SYSCON->SYSPLLSTAT >> %08x", a, d); break; case 0x044: d = 0x01; V6M_INFO("P: LPC_SYSCON->SYSPLLCLKUEN >> %08x", a, d); break; case 0x074: d = 0x01; V6M_INFO("P: LPC_SYSCON->MAINCLKUEN >> %08x", a, d); break; case 0x080: V6M_INFO("P: LPC_SYSCON->SYSAHBCLKCTRL >> %08x", a, d); break; case 0x238: V6M_INFO("P: LPC_SYSCON->PDRUNCFG >> %08x", d); break; default: V6M_WARN("P: LPC_SYSCON %08x >> %08x", a, d); break; } return d; } EMU111x_IOCON::EMU111x_IOCON() { PIO0_4 = 0xd0; PIO0_5 = 0xd0; PIO0_6 = 0xd0; PIO0_8 = 0xd0; PIO0_9 = 0xd0; R_PIO0_11 = 0xd0; SCK_LOC = 0x00; } void EMU111x_IOCON::poke32(uint32_t a, uint32_t d) { switch(a&0xff) { #define c(V,PIN) case V: PIN = d; V6M_INFO("P: LPC_IOCON->%s << %08x", #PIN, d); break; c(0x30, PIO0_4); c(0x34, PIO0_5); c(0x4c, PIO0_6); c(0x60, PIO0_8); c(0x64, PIO0_9); c(0x74, R_PIO0_11); c(0xa0, PIO1_5); c(0xa4, PIO1_6); c(0xa8, PIO1_7); c(0xb0, SCK_LOC); #undef c default: V6M_WARN("P: LPC_IOCON %08x << %08x", a, d); break; } } uint32_t EMU111x_IOCON::peek32(uint32_t a) { uint32_t d = 0x00; switch(a&0xff) { #define c(V,PIN) case V: d = PIN; V6M_INFO("P: LPC_IOCON->%s >> %08x", #PIN, d); break; c(0x30, PIO0_4); c(0x34, PIO0_5); c(0x4c, PIO0_6); c(0x60, PIO0_8); c(0x64, PIO0_9); c(0x74, R_PIO0_11); c(0xa0, PIO1_5); c(0xa4, PIO1_6); c(0xa8, PIO1_7); c(0xb0, SCK_LOC); #undef c default: V6M_WARN("P: LPC_IOCON %08x >> %08x", a, d); break; } return d; } EMU111x_GPIO::EMU111x_GPIO(EMU111x& mcu_, int port_):mcu(mcu_),port(port_) { data = 0x00; dir = 0x00; } void EMU111x_GPIO::poke32(uint32_t a, uint32_t d) { switch(a&0xffff) { case 0x3ffc: data = d; for(int pin = 0; pin < 12; pin++) { uint32_t mask = 1UL<<pin; if (dir & mask) { // output mcu.DigitalWrite_Callback(port, pin, (d&mask) ? 1 : 0); } } V6M_INFO("P: LPC_GPIO%d->DATA %08x << %08x", port, a, d); break; case 0x8000: dir = d; V6M_INFO("P: LPC_GPIO%d->DIR << %08x", port, d); break; default: V6M_WARN("P: LPC_GPIO%d %08x << %08x", port, a, d); break; } } static int pinpos(uint32_t data) { for(int pin = 0; pin < 12; pin++) { if (data & (1UL<<pin)) { return pin; } } return 0; } uint32_t EMU111x_GPIO::peek32(uint32_t a) { uint32_t d = 0x00; uint32_t mask; int pin; switch(a&0xffff) { case 0x0080: mask = (a>>2)&0xfff; pin = pinpos(mask); if (dir & mask) { // output d = data & mask; } else { // input if (mcu.DigitalRead_Callback(port, pin)) { d = mask; } } V6M_WARN("P: LPC_GPIO%d->MASKED_ACCESS[%03x] >> %08x", port, mask, d); break; case 0x3ffc: d = data; V6M_INFO("P: LPC_GPIO%d->DATA >> %08x", port, d); break; case 0x8000: d = dir; V6M_INFO("P: LPC_GPIO%d->DIR >> %08x", port, d); break; default: V6M_WARN("P: LPC_GPIO%d %08x >> %08x", port, a, d); break; } return d; } EMU111x_TMR32B::EMU111x_TMR32B(int ch_):ch(ch_) { V6M_ASSERT(ch == 0 || ch == 1); tc = 0; } void EMU111x_TMR32B::clock_in(uint32_t n) { V6M_ASSERT(n != 0); tc += n; } void EMU111x_TMR32B::poke32(uint32_t a, uint32_t d) { switch(a&0xff) { case 0x04: V6M_INFO("P: LPC_TMR32B->TCR << %08x", d); break; case 0x0c: V6M_INFO("P: LPC_TMR32B->PR << %08x", d); break; default: V6M_WARN("P: LPC_TMR32B %08x << %08x", a, d); break; } } uint32_t EMU111x_TMR32B::peek32(uint32_t a) { uint32_t d = 0x00; switch(a&0xff) { case 0x08: d = tc; V6M_INFO("P: LPC_TMR32B%d->TC >> %u", ch, d); break; default: V6M_WARN("P: LPC_TMR32B%d %08x >> %02x", ch, a, d); break; } return d; } EMU111x_UART::EMU111x_UART(EMU111x& mcu_):mcu(mcu_) { lcr = 0x00; } void EMU111x_UART::poke32(uint32_t a, uint32_t d) { switch(a&0xff) { case 0x00: mcu.SerialPutc_Callback(0, d); V6M_INFO("P: LPC_UART->THR << %08x", d); break; case 0x04: V6M_INFO("P: LPC_UART->IER << %08x", d); break; case 0x08: V6M_INFO("P: LPC_UART->FCR << %08x", d); break; case 0x0c: lcr = d; V6M_INFO("P: LPC_UART->LCR << %08x", d); break; case 0x28: fdr = d; V6M_INFO("P: LPC_UART->FDR << %08x", d); break; default: V6M_WARN("P: LPC_UART %08x << %08x", a, d); break; } } uint32_t EMU111x_UART::peek32(uint32_t a) { uint32_t d = 0x00; switch(a&0xff) { case 0x00: d = mcu.SerialGetc_Callback(0); V6M_INFO("P: LPC_UART->RBR >> %08x", a, d); break; case 0x0c: d = lcr; V6M_INFO("P: LPC_UART->LCR >> %08x", a, d); break; case 0x14: d = 0x20; if (mcu.SerialReadable_Callback(0)) { d |= 0x01; } V6M_INFO("P: LPC_UART->LSR >> %08x", a, d); break; default: V6M_WARN("P: LPC_UART %08x >> %08x", a, d); break; } return d; } EMU111x_I2C::EMU111x_I2C(EMU111x& mcu_):mcu(mcu_) { con = 0; stat = 0xf8; } void EMU111x_I2C::poke32(uint32_t a, uint32_t d) { switch(a&0xff) { case 0x00: // CONSET if (d == 0x40) { con = 0x40; } else if (d == 0x24) { // start con = 0x48; stat = 0x10; } else if (d == 0x10) { // stop if ((i2c_addr&0x01) == 0x00) { mcu.I2CWrite_Callback(i2c_addr, i2c_data, i2c_pos); } } else { V6M_ASSERT(0); } V6M_INFO("P: LPC_I2C->CONSET << %08x", d); break; case 0x08: // DAT if (stat == 0x10) { // start i2c_addr = d & 0xff; i2c_pos = 0; if (i2c_addr & 0x01) { i2c_size = mcu.I2CRead_Callback(i2c_addr, i2c_data, sizeof(i2c_data)); stat = 0x40; i2c_pos = 0; } else { stat = 0x18; } } else { if (i2c_pos < sizeof(i2c_data)) { i2c_data[i2c_pos++] = d & 0xff; } stat = 0x18; } V6M_INFO("P: LPC_I2C->DAT << %08x", d); break; case 0x10: V6M_INFO("P: LPC_I2C->SCLH << %08x", d); break; case 0x14: V6M_INFO("P: LPC_I2C->SCLL << %08x", d); break; case 0x18: V6M_INFO("P: LPC_I2C->CONCLR << %08x", d); break; default: V6M_WARN("P: LPC_I2C %08x << %08x", a, d); break; } } uint32_t EMU111x_I2C::peek32(uint32_t a) { uint32_t d = 0x00000000; switch(a&0xff) { case 0x00: d = con; V6M_INFO("P: LPC_I2C->CON >> %08x", d); break; case 0x04: d = stat; V6M_INFO("P: LPC_I2C->STAT >> %08x", d); break; case 0x08: if (i2c_pos < i2c_size) { d = i2c_data[i2c_pos++]; } if (i2c_pos < i2c_size) { stat = 0x50; } else { stat = 0x58; } V6M_INFO("P: LPC_I2C->DAT >> %08x", d); break; default: V6M_WARN("P: LPC_I2C %08x >> %08x", a, d); break; } return d; } EMU111x_SPI::EMU111x_SPI(EMU111x& mcu_, int ch_):mcu(mcu_),ch(ch_) { cr0 = 0; cr1 = 0; } void EMU111x_SPI::poke32(uint32_t a, uint32_t d) { switch(a&0xff) { case 0x00: cr0 = d; V6M_INFO("P: LPC_SPI%d->CR0 << %08x", ch, d); break; case 0x04: cr1 = d; V6M_INFO("P: LPC_SPI%d->CR1 << %08x", ch, d); break; case 0x08: dr = mcu.SPIWrite_Callback(ch, d); V6M_INFO("P: LPC_SPI%d->DR << %08x", ch, d); break; case 0x10: V6M_INFO("P: LPC_SPI%d->CPSR << %08x", ch, d); break; default: V6M_WARN("P: LPC_SPI%d %08x << %08x", ch, a, d); break; } } uint32_t EMU111x_SPI::peek32(uint32_t a) { uint32_t d = 0; switch(a&0xff) { case 0x00: d = cr0; V6M_INFO("P: LPC_SPI%d->CR0 >> %08x", ch, d); break; case 0x04: d = cr1; V6M_INFO("P: LPC_SPI%d->CR1 >> %08x", ch, d); break; case 0x08: d = dr; V6M_INFO("P: LPC_SPI%d->DR >> %08x", ch, d); break; case 0x0c: d = 0x06; V6M_INFO("P: LPC_SPI%d->SR >> %08x", ch, d); break; default: V6M_WARN("P: LPC_SPI%d %08x >> %08x", ch, a, d); break; } return d; } void EMU111x_NVIC::poke32(uint32_t a, uint32_t d) { switch(a) { case 0xe000e100: iser = d; V6M_INFO("P: NVIC->ISER[0] << %08x", d); break; default: V6M_WARN("P: NVIC %08x >> %08x", a, d); break; } } EMU111x::EMU111x():tmr32b1(1),uart(*this),i2c(*this),spi0(*this,0),spi1(*this,1),gpio0(*this,0),gpio1(*this,1) { flash = NULL; rom = NULL; ram = new uint8_t[EMU111x_RAM_SIZE]; } void EMU111x::poke32(uint32_t a, uint32_t d) { switch(a>>24) { case EMU111x_RAM_BASE>>24: V6M_ASSERT(a < (EMU111x_RAM_BASE+EMU111x_RAM_SIZE)); ram[a - EMU111x_RAM_BASE] = d; ram[a - EMU111x_RAM_BASE + 1] = d>>8; ram[a - EMU111x_RAM_BASE + 2] = d>>16; ram[a - EMU111x_RAM_BASE + 3] = d>>24; V6M_INFO("W: %08x << %08x", a, d); break; case EMU111x_APB_BASE>>24: switch((a>>12)&0xff) { case 0x00: i2c.poke32(a, d); break; case 0x08: uart.poke32(a, d); break; case 0x18: tmr32b1.poke32(a, d); break; case 0x40: spi0.poke32(a, d); break; case 0x44: iocon.poke32(a, d); break; case 0x48: syscon.poke32(a, d); break; case 0x58: spi1.poke32(a, d); break; default: V6M_WARN("P: %08x << %08x", a, d); break; } break; case EMU111x_AHB_BASE>>24: switch((a>>16)&0xff) { case 0: gpio0.poke32(a, d); break; case 1: gpio1.poke32(a, d); break; default: V6M_ERROR("P: %08x << %08x", a, d); break; } break; case EMU111x_FLASH_BASE>>24: case EMU111x_ROM_BASE>>24: V6M_ERROR("P: %08x << %08x", a, d); V6M_ASSERT(0); break; case EMU111x_SCS_BASE>>24: switch(a&0xffffff) { case 0x00e100: nvic.poke32(a, d); break; default: V6M_WARN("P: %08x << %08x", a, d); break; } break; default: V6M_WARN("P: %08x << %08x", a, d); break; } } uint32_t EMU111x::peek32(uint32_t a) { uint32_t d = 0x00; switch(a>>24) { case EMU111x_RAM_BASE>>24: V6M_ASSERT(a < (EMU111x_RAM_BASE+EMU111x_RAM_SIZE)); d = ram[a - EMU111x_RAM_BASE]; d |= ram[a - EMU111x_RAM_BASE + 1]<<8; d |= ram[a - EMU111x_RAM_BASE + 2]<<16; d |= ram[a - EMU111x_RAM_BASE + 3]<<24; V6M_INFO("R: %08x >> %08x", a, d); break; case EMU111x_FLASH_BASE>>24: V6M_ASSERT(a < (EMU111x_FLASH_BASE+EMU111x_FLASH_SIZE)); d = flash[a - EMU111x_FLASH_BASE]; d |= flash[a - EMU111x_FLASH_BASE + 1]<<8; d |= flash[a - EMU111x_FLASH_BASE + 2]<<16; d |= flash[a - EMU111x_FLASH_BASE + 3]<<24; break; case EMU111x_ROM_BASE>>24: V6M_ERROR("P: %08x << %08x", a, d); V6M_ASSERT(0); break; case EMU111x_APB_BASE>>24: switch((a>>12)&0xff) { case 0x00: d = i2c.peek32(a); break; case 0x08: d = uart.peek32(a); break; case 0x18: d = tmr32b1.peek32(a); break; case 0x40: d = spi0.peek32(a); break; case 0x44: d = iocon.peek32(a); break; case 0x48: d = syscon.peek32(a); break; case 0x58: d = spi1.peek32(a); break; default: V6M_WARN("P: %08x >> %08x", a, d); break; } break; case EMU111x_AHB_BASE>>24: switch((a>>16)&0xff) { case 0: d = gpio0.peek32(a); break; case 1: d = gpio1.peek32(a); break; default: V6M_ERROR("P: %08x >> %08x", a, d); break; } break; default: V6M_WARN("P: %08x >> %08x", a, d); break; } return d; } void EMU111x::poke8(uint32_t a, uint8_t d) { switch(a>>24) { case EMU111x_RAM_BASE>>24: V6M_ASSERT(a < (EMU111x_RAM_BASE+EMU111x_RAM_SIZE)); ram[a - EMU111x_RAM_BASE] = d; V6M_INFO("W: %08x << %02x", a, d); break; default: V6M_ERROR("P: %08x << %08x", a, d); V6M_ASSERT(0); break; } } uint8_t EMU111x::peek8(uint32_t a) { uint8_t d = 0x00; switch(a>>24) { case EMU111x_RAM_BASE>>24: V6M_ASSERT(a < (EMU111x_RAM_BASE+EMU111x_RAM_SIZE)); d = ram[a - EMU111x_RAM_BASE]; V6M_INFO("R: %08x >> %02x", a, d); break; case EMU111x_FLASH_BASE>>24: V6M_ASSERT(a < (EMU111x_FLASH_BASE+EMU111x_FLASH_SIZE)); d = flash[a - EMU111x_FLASH_BASE]; break; case EMU111x_ROM_BASE>>24: V6M_ASSERT(a < (EMU111x_ROM_BASE+EMU111x_ROM_SIZE)); d = flash[a - EMU111x_ROM_BASE]; break; default: V6M_ASSERT(0); break; } return d; } void EMU111x::clock_in(uint32_t n) { tmr32b1.clock_in(n); } void EMU111x::trace() { V6M_INFO("S: r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x r6=%08x r7=%08x", R[0],R[1],R[2],R[3],R[4],R[5],R[6],R[7]); V6M_INFO("S: r8=%08x r9=%08x r10=%08x r11=%08x r12=%08x sp=%08x lr=%08x pc=%08x", R[8],R[9],R[10],R[11],R[12],R[13],R[14],R[15]); V6M_INFO("S: xPSR=%08x N=%d Z=%d C=%d V=%d", R[16], N(), Z(), C(), V()); V6M_DEBUG("S: cycle=%d code=%02x code2nd=%02x im=%08x d=%d n=%d m=%d", cycle, code, code2nd, R[17], GetRegIndex(Rd), GetRegIndex(Rn), GetRegIndex(Rm)); }