1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-02-26 16:54:04 +00:00

Power OFF event now from ACLO

PRU bugfix: if DMA cycle started by register access cycle
Extended interface for emulated CPU
This commit is contained in:
Joerg Hoppe
2019-08-22 17:30:21 +02:00
parent fa454f646c
commit f938c8ba8a
6 changed files with 66 additions and 33 deletions

View File

@@ -102,8 +102,13 @@ void mailbox_test1() {
* mailbox union members must have been filled.
*/
//uint32_t xxx;
pthread_mutex_t arm2pru_mutex = PTHREAD_MUTEX_INITIALIZER ;
bool mailbox_execute(uint8_t request) {
// write to arm2pru_req must be last memory operation
pthread_mutex_lock(&arm2pru_mutex) ;
__sync_synchronize();
while (mailbox->arm2pru_req != ARM2PRU_NONE)
; // wait to complete
@@ -121,5 +126,7 @@ bool mailbox_execute(uint8_t request) {
; // wait until processed
*/
// result false = error
return (mailbox->arm2pru_req == ARM2PRU_NONE) ;
bool result = (mailbox->arm2pru_req == ARM2PRU_NONE) ;
pthread_mutex_unlock(&arm2pru_mutex) ;
return result ;
}

View File

@@ -85,6 +85,7 @@ unibusadapter_c::unibusadapter_c() :
devices[i] = NULL;
line_INIT = false;
line_DCLO = false;
line_ACLO = false ;
requests_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -756,14 +757,14 @@ void unibusadapter_c::worker_init_event() {
pthread_mutex_unlock(&requests_mutex);
}
void unibusadapter_c::worker_power_event() {
void unibusadapter_c::worker_power_event(bool power_down) {
unsigned device_handle;
unibusdevice_c *device;
// notify device on change of DC_LO line
DEBUG("worker_power_event(): DCLO %s", line_DCLO ? "asserted" : "deasserted");
DEBUG("worker_power_event(power_down=%d)", power_down);
for (device_handle = 0; device_handle <= MAX_DEVICE_HANDLE; device_handle++)
if ((device = devices[device_handle])) {
device->power_down = line_DCLO;
device->power_down = power_down;
device->on_power_changed();
}
@@ -1004,6 +1005,8 @@ void unibusadapter_c::worker(unsigned instance) {
bool init_falling_edge = false;
bool dclo_raising_edge = false;
bool dclo_falling_edge = false;
bool aclo_raising_edge = false;
bool aclo_falling_edge = false;
// DEBUG("mailbox->events: mask=0x%x", mailbox->events.eventmask);
if (mailbox->events.event_init) {
any_event = true;
@@ -1031,16 +1034,27 @@ void unibusadapter_c::worker(unsigned instance) {
dclo_falling_edge = true;
line_DCLO = false;
}
if (mailbox->events.initialization_signals_cur & INITIALIZATIONSIGNAL_ACLO) {
if (!line_ACLO)
aclo_raising_edge = true;
line_ACLO = true;
} else {
if (line_ACLO)
aclo_falling_edge = true;
line_ACLO = false;
}
mailbox->events.event_power = 0; // PRU may re-raise and change mailbox now
DEBUG(
"EVENT_INITIALIZATIONSIGNALS: (sigprev=0x%x,) cur=0x%x, init_raise=%d, init_fall=%d, dclo_raise=%d, dclo_fall=%d",
"EVENT_INITIALIZATIONSIGNALS: (sigprev=0x%x,) cur=0x%x, init_raise=%d, init_fall=%d, dclo_raise/fall=%d%/d, aclo_raise/fall=%d/%d",
mailbox->events.initialization_signals_prev,
mailbox->events.initialization_signals_cur, init_raising_edge,
init_falling_edge, dclo_raising_edge, dclo_falling_edge);
init_falling_edge, dclo_raising_edge, dclo_falling_edge, aclo_raising_edge, aclo_falling_edge);
}
if (dclo_raising_edge || dclo_falling_edge)
worker_power_event(); // power signal power change
if (dclo_raising_edge)
worker_power_event(true); // power signal power change
else if (aclo_falling_edge)
worker_power_event(false); // power signal power change
if (init_falling_edge) // INIT asserted -> deasserted. DATI/DATO cycle only possible after that.
worker_init_event();
if (mailbox->events.event_deviceregister) {
@@ -1050,7 +1064,7 @@ void unibusadapter_c::worker(unsigned instance) {
// DEBUG("EVENT_DEVICEREGISTER: control=%d, addr=%06o", (int)mailbox->events.unibus_control, mailbox->events.addr);
worker_deviceregister_event();
// ARM2PRU opcodes raised by device logic are processed in midst of bus cycle
mailbox->events.event_deviceregister = 0; // PRU continous bus cycle with SSYN now
mailbox->events.event_deviceregister = 0; // PRU continues bus cycle with SSYN now
}
if (mailbox->events.event_dma) {
any_event = true;

View File

@@ -62,7 +62,7 @@ private:
pthread_mutex_t requests_mutex;
void worker_init_event(void);
void worker_power_event(void);
void worker_power_event(bool power_down);
void worker_deviceregister_event(void);
void worker_dma_chunk_complete_event(bool cpu_DATA_transfer);
void worker_intr_complete_event(uint8_t level_index);
@@ -80,6 +80,7 @@ public:
volatile bool line_INIT; // current state of these UNIBUS signals
volatile bool line_DCLO;
volatile bool line_ACLO;
void on_power_changed(void) override; // must implement
void on_init_changed(void) override; // must implement

View File

@@ -125,31 +125,35 @@ void main(void) {
while ((sm_data_slave_state = sm_data_slave_state())
&& !mailbox.events.event_deviceregister)
// throws signals to ARM,
// Acess to interna lregsitres may may issue AMR2PRU opcode, so exit loop then
// Acess to internal registers may may issue AMR2PRU opcode, so exit loop then
;// execute complete slave cycle, then check NPR/INTR
// signal INT or PWR FAIL to ARM
do_event_initializationsignals();
// Priority Arbitration
// execute one of the arbitration workers
uint8_t grant_mask = sm_arb_worker();
// sm_arb_worker()s include State 2 "BBSYWAIT".
// So now SACK maybe set, even if grant_mask is still 0
// Delay INTR or DMA while BUS halted via SSYN.
// ARM may start DMA within deviceregister event!
if (!mailbox.events.event_deviceregister) {
// execute one of the arbitration workers
uint8_t grant_mask = sm_arb_worker();
// sm_arb_worker()s include State 2 "BBSYWAIT".
// So now SACK maybe set, even if grant_mask is still 0
if (grant_mask & PRIORITY_ARBITRATION_BIT_NP) {
sm_data_master_state = (statemachine_state_func) &sm_dma_start;
// can data_master_state be overwritten in the midst of a running data_master_state ?
// no: when running, SACK is set, no new GRANTs
} else if (grant_mask & PRIORITY_ARBITRATION_INTR_MASK) {
// convert bit in grant_mask to INTR index
uint8_t idx = PRIORITY_ARBITRATION_INTR_BIT2IDX(grant_mask);
// now transfer INTR vector for interupt of GRANted level.
// vector and ARM context have been setup by ARM before ARM2PRU_INTR already
sm_intr.vector = mailbox.intr.vector[idx];
sm_intr.level_index = idx; // to be returned to ARM on complete
if (grant_mask & PRIORITY_ARBITRATION_BIT_NP) {
sm_data_master_state = (statemachine_state_func) &sm_dma_start;
// can data_master_state be overwritten in the midst of a running data_master_state ?
// no: when running, SACK is set, no new GRANTs
} else if (grant_mask & PRIORITY_ARBITRATION_INTR_MASK) {
// convert bit in grant_mask to INTR index
uint8_t idx = PRIORITY_ARBITRATION_INTR_BIT2IDX(grant_mask);
// now transfer INTR vector for interupt of GRANted level.
// vector and ARM context have been setup by ARM before ARM2PRU_INTR already
sm_intr.vector = mailbox.intr.vector[idx];
sm_intr.level_index = idx; // to be returned to ARM on complete
sm_data_master_state = (statemachine_state_func) &sm_intr_start;
sm_data_master_state = (statemachine_state_func) &sm_intr_start;
}
}
} else {
// State 3 "MASTER"

View File

@@ -150,7 +150,7 @@ static statemachine_state_func sm_dma_state_1() {
tmpval |= BIT(3); // DATO: c1=1, c0=0
// bit 2,4,5 == 0 -> C0,MSYN,SSYN not asserted
buslatches_setbits(4, 0x3f, tmpval);
// write data. SSYN may still be active???
// write data. SSYN may still be active and cleared now? by sm_slave_10 etc?
// data = mailbox.dma.words[sm_dma.cur_wordidx];
data = *sm_dma.dataptr;
buslatches_setbyte(5, data & 0xff); // DATA[0..7] = latch[5]

View File

@@ -52,7 +52,7 @@
//statemachine_state_func sm_slave_start(void);
static statemachine_state_func sm_slave_state_10(void);
static statemachine_state_func sm_slave_state_20(void);
static statemachine_state_func sm_slave_state_99(void);
//static statemachine_state_func sm_slave_state_99(void);
// check for MSYN active
statemachine_state_func sm_slave_start() {
@@ -115,7 +115,8 @@ statemachine_state_func sm_slave_start() {
// perhaps PRU2ARM_INTERRUPT now active
} else
// no address match: wait for MSYN to go inactive
return (statemachine_state_func) &sm_slave_state_99;
// return (statemachine_state_func) &sm_slave_state_99;
return NULL ;
case UNIBUS_CONTROL_DATO:
// fetch data in any case
// DATA[0..7] = latch[5]
@@ -131,7 +132,8 @@ statemachine_state_func sm_slave_start() {
// perhaps PRU2ARM_INTERRUPT now active
} else
// no address match: wait for MSYN to go inactive
return (statemachine_state_func) &sm_slave_state_99;
// return (statemachine_state_func) &sm_slave_state_99;
return NULL ;
case UNIBUS_CONTROL_DATOB:
// A00 = 1, odd address: get upper byte
// A00 = 0: even address, get lower byte
@@ -151,7 +153,8 @@ statemachine_state_func sm_slave_start() {
// perhaps PRU2ARM_INTERRUPT now active
} else
// no address match: wait for MSYN to go inactive
return (statemachine_state_func) &sm_slave_state_99;
// return (statemachine_state_func) &sm_slave_state_99;
return NULL ;
}
return NULL; // not reached
}
@@ -198,11 +201,15 @@ static statemachine_state_func sm_slave_state_20() {
return NULL; // ready
}
// end of inactive cycle: wait for MSYN to go inactive
// Not necessary, start() state simply checks addr again if MSYN still set.
static statemachine_state_func sm_slave_state_99() {
// MSYN = latch[4], bit 4
if (buslatches_getbyte(4) & BIT(4))
if (buslatches_getbyte(4) & BIT(4)) {
return (statemachine_state_func) &sm_slave_state_99; // wait, MSYN still active
}
// PRU_DEBUG_PIN(1) ;
return NULL; // ready
}