68340: deskeletonized the serial module as a device derived from the duart device defined in mc68681.cpp

This commit is contained in:
Joakim Larsson Edstrom 2017-09-04 22:09:00 +02:00
parent 1e4b7bea34
commit 5f7f9c4933
4 changed files with 234 additions and 37 deletions

View File

@ -1,6 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/* 68340 */
/* 68340
* TODO: - convert all modules to devices
*/
#include "emu.h"
#include "68340.h"
@ -78,23 +80,23 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
int base = m68340_base & 0xfffff000;
internal->install_readwrite_handler(base + 0x000, base + 0x03f,
read16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_r),this),
write16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_w),this),0xffffffff);
read16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_r),this),
write16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_w),this),0xffffffff);
internal->install_readwrite_handler(base + 0x010, base + 0x01f, // Intentionally punches a hole in previous address mapping
read8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_r),this),
write8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_w),this),0xffffffff);
read8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_r),this),
write8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_w),this),0xffffffff);
internal->install_readwrite_handler(base + 0x040, base + 0x05f,
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_r),this),
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_w),this));
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_r),this),
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_w),this));
internal->install_readwrite_handler(base + 0x600, base + 0x67f,
read16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_r),this),
write16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_w),this),0xffffffff);
read16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_r),this),
write16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_w),this),0xffffffff);
internal->install_readwrite_handler(base + 0x700, base + 0x723,
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_r),this),
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_w),this));
READ8_DEVICE_DELEGATE(m_serial, m68340_serial, read),
WRITE8_DEVICE_DELEGATE(m_serial, m68340_serial, write),0xffffffff);
internal->install_readwrite_handler(base + 0x780, base + 0x7bf,
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_r),this),
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_w),this));
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_r),this),
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_w),this));
}
@ -108,17 +110,27 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
}
static ADDRESS_MAP_START( m68340_internal_map, AS_PROGRAM, 32, m68340_cpu_device )
AM_RANGE(0x0003ff00, 0x0003ff03) AM_READWRITE( m68340_internal_base_r, m68340_internal_base_w)
ADDRESS_MAP_END
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
MACHINE_CONFIG_MEMBER( m68340_cpu_device::device_add_mconfig )
MCFG_DEVICE_ADD("serial", M68340_SERIAL_MODULE, 0)
MCFG_MC68681_IRQ_CALLBACK(DEVWRITELINE("serial", m68340_serial, irq_w))
MACHINE_CONFIG_END
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: fscpu32_device(mconfig, tag, owner, clock, M68340, 32,32, ADDRESS_MAP_NAME(m68340_internal_map))
, m_serial(*this, "serial")
, m_clock_mode(0)
, m_crystal(0)
, m_extal(0)
@ -135,7 +147,6 @@ m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char *
{
m68340SIM = nullptr;
m68340DMA = nullptr;
m68340SERIAL = nullptr;
m68340TIMER = nullptr;
m68340_base = 0;
}
@ -165,12 +176,10 @@ void m68340_cpu_device::device_start()
m68340SIM = new m68340_sim();
m68340DMA = new m68340_dma();
m68340SERIAL = new m68340_serial();
m68340TIMER = new m68340_timer();
m68340SIM->reset();
m68340DMA->reset();
m68340SERIAL->reset();
m68340TIMER->reset();
start_68340_sim();

View File

@ -51,6 +51,8 @@
class m68340_cpu_device : public fscpu32_device
{
friend class m68340_serial;
public:
m68340_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -80,8 +82,6 @@ public:
WRITE32_MEMBER( m68340_internal_base_w );
READ32_MEMBER( m68340_internal_dma_r );
WRITE32_MEMBER( m68340_internal_dma_w );
READ32_MEMBER( m68340_internal_serial_r );
WRITE32_MEMBER( m68340_internal_serial_w );
READ16_MEMBER( m68340_internal_sim_r );
READ8_MEMBER( m68340_internal_sim_ports_r );
READ32_MEMBER( m68340_internal_sim_cs_r );
@ -104,6 +104,9 @@ public:
protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
required_device<m68340_serial> m_serial;
TIMER_CALLBACK_MEMBER(periodic_interrupt_timer_callback);
TIMER_CALLBACK_MEMBER(timer1_callback);
@ -127,7 +130,6 @@ protected:
/* 68340 peripheral modules */
m68340_sim* m68340SIM;
m68340_dma* m68340DMA;
m68340_serial* m68340SERIAL;
m68340_timer* m68340TIMER;
uint32_t m68340_base;

View File

@ -1,31 +1,171 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
// copyright-holders:David Haywood, Joakim Larsson Edstrom
/* 68340 SERIAL module */
#include "emu.h"
#include "68340.h"
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
READ32_MEMBER( m68340_cpu_device::m68340_internal_serial_r )
//#define LOG_GENERAL (1U << 0) // Already defined in logmacro.h
#define LOG_SETUP (1U << 1)
#define LOG_READ (1U << 2)
#define LOG_SERIAL (1U << 3)
#define LOG_INT (1U << 4)
//#define VERBOSE (LOG_SETUP|LOG_READ|LOG_SERIAL|LOG_INT)
#define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here
#include "logmacro.h"
//#define LOG(...) LOGMASKED(LOG_GENERAL, __VA_ARGS__) // Already defined in logmacro.h
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
#define LOGSERIAL(...) LOGMASKED(LOG_SERIAL, __VA_ARGS__)
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
#ifdef _MSC_VER
#define FUNCNAME __func__
#else
#define FUNCNAME __PRETTY_FUNCTION__
#endif
void m68340_serial::device_start()
{
assert(m68340SERIAL);
//m68340_serial &serial = *m68340SERIAL;
int pc = space.device().safe_pc();
logerror("%08x m68340_internal_serial_r %08x, (%08x)\n", pc, offset*4,mem_mask);
return 0x00000000;
m_cpu = downcast<m68340_cpu_device *>(owner());
m68340_serial_device::device_start();
}
WRITE32_MEMBER( m68340_cpu_device::m68340_internal_serial_w )
READ8_MEMBER( m68340_serial::read )
{
assert(m68340SERIAL);
//m68340_serial &serial = *m68340SERIAL;
LOG("%s\n", FUNCNAME);
int val = 0;
int pc = space.device().safe_pc();
logerror("%08x m68340_internal_serial_w %08x, %08x (%08x)\n", pc, offset*4,data,mem_mask);
LOGR("%08x %s %08x, (%08x)\n", space.device().safe_pc(), FUNCNAME, offset, mem_mask);
/*Setting the STP bit stops all clocks within the serial module (including the crystal
or external clock and SCLK), except for the clock from the IMB. The clock from the IMB
remains active to allow CPU32 access to the MCR. The clock stops on the low phase of the
clock and remains stopped until the STP bit is cleared by the CPU32 or a hardware reset.
Accesses to serial module registers while in stop mode produce a bus error. */
if ( (m_mcrh & REG_MCRH_STP) && offset != REG_MCRH && offset != REG_MCRL)
{
logerror("Attempt to access timer registers while timer clocks are stopped, STP bit in MCR is set!");
return val; // TODO: Should cause BUSERROR
}
switch (offset)
{
case REG_MCRH:
val = m_mcrh;
LOGSERIAL("- %08x %s %04x, %04x (%04x) (MCRH - Module Configuration Register High byte)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask);
break;
case REG_MCRL:
val = m_mcrl;
LOGSERIAL("- %08x %s %04x, %04x (%04x) (MCRL - Module Configuration Register Low byte)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask);
break;
case REG_ILR:
val = m_ilr;
LOGSERIAL("- %08x %s %04x, %04x (%04x) (ILR - Interrupt Level Register)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask);
break;
case REG_IVR:
val = m_ivr;
LOGSERIAL("- %08x %s %04x, %04x (%04x) (IVR - Interrupt Vector Register)\n", space.device().safe_pc(), FUNCNAME, offset, val, mem_mask);
break;
}
LOGR(" * Reg %02x -> %02x - %s\n", offset, val,
(offset > 0x21) ? "Error - should not happen" :
std::array<char const *, 0x22>
{{
"MCRH", "MCRL", "n/a", "n/a", "ILR", "IVR", "hole", "hole", // 0x00 - 0x07
"hole", "hole", "hole", "hole", "hole", "hole", "hole", "hole", // 0x08 - 0x0f
"MR1A", "SRA", "n/a", "RBA", "IPCR", "ISR", "n/a", "n/a", // 0x10 - 0x17
"MR1B", "SRB", "n/a", "RBB", "n/a", "IP", "n/a", "n/a", // 0x18 - 0x1f
"MR2A", "MR2B" }}[offset]); // 0x20 - 0x21
return offset >= 0x10 && offset < 0x22 ? m68340_serial_device::read(space, offset - 0x10, mem_mask) : val;
}
void m68340_serial::reset()
WRITE8_MEMBER( m68340_serial::write )
{
LOG("\n%s\n", FUNCNAME);
LOGSETUP(" * Reg %02x <- %02x - %s\n", offset, data,
(offset > 0x21) ? "Error - should not happen" :
std::array<char const *, 0x22>
{{
"MCRH", "MCRL", "n/a", "n/a", "ILR", "IVR", "hole", "hole", // 0x00 - 0x07
"hole", "hole", "hole", "hole", "hole", "hole", "hole", "hole", // 0x08 - 0x0f
"MR1A", "CSRA", "CRA", "TBA", "ACR", "IER", "n/a", "n/a", // 0x10 - 0x17
"MR1B", "CSRB", "CRB", "TBB", "n/a", "OPCR", "OPS", "OPR", // 0x18 - 0x1f
"MR2A", "MR2B" }}[offset]); // 0x20 - 0x21
/*Setting the STP bit stops all clocks within the serial module (including the crystal
or external clock and SCLK), except for the clock from the IMB. The clock from the IMB
remains active to allow CPU32 access to the MCR. The clock stops on the low phase of the
clock and remains stopped until the STP bit is cleared by the CPU32 or a hardware reset.
Accesses to serial module registers while in stop mode produce a bus error. */
if ( (m_mcrh & REG_MCRH_STP) && offset != REG_MCRH && offset != REG_MCRL)
{
logerror("Attempt to access timer registers while timer clocks are stopped, STP bit in MCR is set!");
return; // TODO: Should cause BUSERROR
}
switch (offset)
{
case REG_MCRH:
m_mcrh = data;
LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (MCRH - Module Configuration Register High byte)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask);
LOGSERIAL("- Clocks are %s\n", data & REG_MCRH_STP ? "stopped" : "running");
LOGSERIAL("- Freeze signal %s - not implemented\n", data & REG_MCRH_FRZ1 ? "stops at character boundary" : "is ignored");
LOGSERIAL("- CTS capture clock: %s - not implemented\n", data & REG_MCRH_ICCS ? "SCLK" : "Crystal");
break;
case REG_MCRL:
m_mcrl = data;
LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (MCRL - Module Configuration Register Low byte)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask);
LOGSERIAL("- Supervisor registers %s - not implemented\n", data & REG_MCRL_SUPV ? "requries supervisor privileges" : "can be accessed by user privileged software");
LOGSERIAL("- Interrupt Arbitration level: %02x - not implemented\n", data & REG_MCRL_ARBLV);
break;
case REG_ILR:
m_ilr = data;
LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (ILR - Interrupt Level Register)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask);
LOGSERIAL("- Interrupt Level: %02x\n", data & REG_ILR_MASK);
break;
case REG_IVR:
m_ivr = data;
LOGSERIAL("PC: %08x %s %04x, %04x (%04x) (IVR - Interrupt Vector Register)\n", space.device().safe_pc(), FUNCNAME, offset, data, mem_mask);
LOGSERIAL("- Interrupt Vector: %02x\n", data);
break;
default:
if (offset >= 0x10 && offset < 0x22) m68340_serial_device::write(space, offset - 0x10, data, mem_mask);
}
}
WRITE_LINE_MEMBER( m68340_serial::irq_w )
{
LOGINT("IRQ!\n%s\n", FUNCNAME);
if (m_ilr > 0)
{
if (((m_cpu->m68340SIM->m_avr_rsr >> (8 + m_ilr)) & 1) != 0) // use autovector ?
{
LOGINT("- Autovector level %d\n", m_ilr);
m_cpu->set_input_line(m_ilr, HOLD_LINE);
}
else // otherwise not...
{
LOGINT("- Vector %02x level %d\n", m_ivr, m_ilr);
m_cpu->set_input_line_and_vector(m_ilr, HOLD_LINE, m_ivr);
}
}
}
m68340_serial::m68340_serial(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: m68340_serial_device(mconfig, "serial", owner, clock)
{
}
DEFINE_DEVICE_TYPE(M68340_SERIAL_MODULE, m68340_serial, "m68340 serial module", "Motorola 68340 Serial Module")

View File

@ -5,11 +5,57 @@
#pragma once
#include "machine/mc68681.h"
class m68340_serial
class m68340_cpu_device;
class m68340_serial : public m68340_serial_device
{
friend class m68340_cpu_device;
public:
void reset();
m68340_serial(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
READ8_MEMBER( read ) override;
WRITE8_MEMBER( write ) override;
DECLARE_WRITE_LINE_MEMBER(irq_w);
protected:
m68340_cpu_device *m_cpu;
// Module registers not in the DUART part
uint8_t m_mcrh;
uint8_t m_mcrl;
uint8_t m_ilr;
uint8_t m_ivr;
enum {
REG_MCRH = 0,
REG_MCRL = 1,
REG_ILR = 4,
REG_IVR = 5,
};
enum {
REG_MCRH_STP = 0x80,
REG_MCRH_FRZ1 = 0x40,
REG_MCRH_FRZ2 = 0x20,
REG_MCRH_ICCS = 0x10,
};
enum {
REG_MCRL_SUPV = 0x80,
REG_MCRL_ARBLV = 0x0f,
};
enum {
REG_ILR_MASK = 0x07
};
};
DECLARE_DEVICE_TYPE(M68340_SERIAL_MODULE, m68340_serial)
#endif // MAME_MACHINE_68340SER_H