diff --git a/10.01_base/2_src/arm/mailbox.cpp b/10.01_base/2_src/arm/mailbox.cpp index 57dc419..cebfc0c 100644 --- a/10.01_base/2_src/arm/mailbox.cpp +++ b/10.01_base/2_src/arm/mailbox.cpp @@ -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 ; } diff --git a/10.01_base/2_src/arm/unibusadapter.cpp b/10.01_base/2_src/arm/unibusadapter.cpp index da1023f..e8c86c7 100644 --- a/10.01_base/2_src/arm/unibusadapter.cpp +++ b/10.01_base/2_src/arm/unibusadapter.cpp @@ -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; diff --git a/10.01_base/2_src/arm/unibusadapter.hpp b/10.01_base/2_src/arm/unibusadapter.hpp index 0f16f23..420e3fa 100644 --- a/10.01_base/2_src/arm/unibusadapter.hpp +++ b/10.01_base/2_src/arm/unibusadapter.hpp @@ -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 diff --git a/10.01_base/2_src/pru1/pru1_main_unibus.c b/10.01_base/2_src/pru1/pru1_main_unibus.c index c32a539..3436d80 100644 --- a/10.01_base/2_src/pru1/pru1_main_unibus.c +++ b/10.01_base/2_src/pru1/pru1_main_unibus.c @@ -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" diff --git a/10.01_base/2_src/pru1/pru1_statemachine_dma.c b/10.01_base/2_src/pru1/pru1_statemachine_dma.c index f49316e..f9d62f5 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_dma.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_dma.c @@ -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] diff --git a/10.01_base/2_src/pru1/pru1_statemachine_slave.c b/10.01_base/2_src/pru1/pru1_statemachine_slave.c index d822a13..8fbff5d 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_slave.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_slave.c @@ -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 }