From 3d1d9d3cf6f983274019fe37095d84af2b2c26ab Mon Sep 17 00:00:00 2001 From: Joerg Hoppe Date: Mon, 19 Aug 2019 13:12:42 +0200 Subject: [PATCH] ACLO/DCLO/INIT moved from PRU to ARM INTR/DMA request params linked to device params on change --- 10.01_base/2_src/arm/device.cpp | 2 +- 10.01_base/2_src/arm/priorityrequest.cpp | 3 + 10.01_base/2_src/arm/unibus.cpp | 41 +++++-- 10.01_base/2_src/arm/unibusadapter.cpp | 2 +- 10.01_base/2_src/arm/unibusdevice.cpp | 17 ++- 10.01_base/2_src/arm/unibusdevice.hpp | 2 +- 10.01_base/2_src/pru1/Makefile | 2 - 10.01_base/2_src/pru1/pru1_main_test.c | 27 +++-- 10.01_base/2_src/pru1/pru1_main_unibus.c | 36 +++--- .../2_src/pru1/pru1_statemachine_init.c | 100 ---------------- .../2_src/pru1/pru1_statemachine_init.h | 45 -------- .../2_src/pru1/pru1_statemachine_powercycle.c | 109 ------------------ .../2_src/pru1/pru1_statemachine_powercycle.h | 37 ------ 10.01_base/2_src/pru1/pru1_timeouts.h | 6 +- 10.01_base/2_src/pru1/pru1_utils.c | 33 ++++++ 10.01_base/2_src/pru1/pru1_utils.h | 3 + 10.01_base/2_src/shared/mailbox.h | 22 ++-- 10.02_devices/2_src/dl11w.cpp | 33 +++--- 10.02_devices/2_src/dl11w.hpp | 21 ---- 10.02_devices/2_src/rk11.cpp | 15 ++- 10.02_devices/2_src/rl11.cpp | 22 ++-- 10.02_devices/2_src/uda.cpp | 12 +- 10.03_app_demo/2_src/menu_devices.cpp | 2 +- 23 files changed, 183 insertions(+), 409 deletions(-) delete mode 100644 10.01_base/2_src/pru1/pru1_statemachine_init.c delete mode 100644 10.01_base/2_src/pru1/pru1_statemachine_init.h delete mode 100644 10.01_base/2_src/pru1/pru1_statemachine_powercycle.c delete mode 100644 10.01_base/2_src/pru1/pru1_statemachine_powercycle.h diff --git a/10.01_base/2_src/arm/device.cpp b/10.01_base/2_src/arm/device.cpp index e7bcb1f..d360ebe 100644 --- a/10.01_base/2_src/arm/device.cpp +++ b/10.01_base/2_src/arm/device.cpp @@ -149,7 +149,7 @@ bool device_c::on_param_changed(parameter_c *param) { } // all devices forward their "on_param_changed" to parent classes, // until a class rejects a value. - // device_c is the grand pratnes and produces "OK" for unknown or passive parameters + // device_c is the grand parent and produces "OK" for unknown or passive parameters return true; } diff --git a/10.01_base/2_src/arm/priorityrequest.cpp b/10.01_base/2_src/arm/priorityrequest.cpp index d239ab8..d81d4aa 100644 --- a/10.01_base/2_src/arm/priorityrequest.cpp +++ b/10.01_base/2_src/arm/priorityrequest.cpp @@ -47,6 +47,8 @@ priority_request_c::~priority_request_c() { void priority_request_c::set_priority_slot(uint8_t priority_slot) { assert(priority_slot > 0); // 0 reserved assert(priority_slot < PRIORITY_SLOT_COUNT); + if (this->slot == priority_slot) + return ; // called on every on_param_change() unibusdevice_c *ubdevice = unibusdevice_c::find_by_request_slot(priority_slot); if (ubdevice && ubdevice != this->device) { WARNING("Slot %u already used by device %s", (unsigned) priority_slot, ubdevice->name.value.c_str()); @@ -105,3 +107,4 @@ void intr_request_c::set_vector(uint16_t vector) { this->vector = vector; } + diff --git a/10.01_base/2_src/arm/unibus.cpp b/10.01_base/2_src/arm/unibus.cpp index 4ee85d1..e358615 100644 --- a/10.01_base/2_src/arm/unibus.cpp +++ b/10.01_base/2_src/arm/unibus.cpp @@ -94,23 +94,44 @@ char *unibus_c::control2text(uint8_t control) { return buffer; } -/* pulse INIT cycle for a number of milliseconds - * Duration see INITPULSE_DELAY_MS +/* pulse INIT cycle for 50 milliseconds ... source? */ void unibus_c::init(void) { - /* - // INIT: latch[7], bit 3 - buslatches_setval(7, BIT(3), BIT(3)); - timeout.wait_ms(duration_ms); - buslatches_setval(7, BIT(3), 0); - */ - mailbox_execute(ARM2PRU_INITPULSE); + timeout_c timeout; + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_INIT; + mailbox->initializationsignal.val = 1; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout.wait_ms(50); + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_INIT; + mailbox->initializationsignal.val = 0; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); } /* Simulate a power cycle + * Sequence: + * 1. Line power fail -> ACLO active + * 2. Power supply capacitors empty -> DCLO active + * 3. Line power back -> ACLO inactive + * 4. Logic power OK -> DCLO inactive */ void unibus_c::powercycle(void) { - mailbox_execute(ARM2PRU_POWERCYCLE); + timeout_c timeout; + const unsigned delay_ms = 100; // time between phases + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_ACLO; + mailbox->initializationsignal.val = 1; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout.wait_ms(delay_ms); + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_DCLO; + mailbox->initializationsignal.val = 1; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout.wait_ms(delay_ms); + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_ACLO; + mailbox->initializationsignal.val = 0; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); + timeout.wait_ms(delay_ms); + mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_DCLO; + mailbox->initializationsignal.val = 0; + mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET); } void unibus_c::set_arbitration_mode(arbitration_mode_enum arbitration_mode) { diff --git a/10.01_base/2_src/arm/unibusadapter.cpp b/10.01_base/2_src/arm/unibusadapter.cpp index d5e7904..da1023f 100644 --- a/10.01_base/2_src/arm/unibusadapter.cpp +++ b/10.01_base/2_src/arm/unibusadapter.cpp @@ -1008,7 +1008,7 @@ void unibusadapter_c::worker(unsigned instance) { if (mailbox->events.event_init) { any_event = true; // robust: any change in ACLO/DCL=INIT updates state of all 3. - // Initial DCLO-cycle to PDP_11 intialize these states + // Initial DCLO-cycle to PDP_11 initialize these states if (mailbox->events.initialization_signals_cur & INITIALIZATIONSIGNAL_INIT) { if (!line_INIT) init_raising_edge = true; diff --git a/10.01_base/2_src/arm/unibusdevice.cpp b/10.01_base/2_src/arm/unibusdevice.cpp index 9be9cf4..4bef6d3 100644 --- a/10.01_base/2_src/arm/unibusdevice.cpp +++ b/10.01_base/2_src/arm/unibusdevice.cpp @@ -43,6 +43,7 @@ unibusdevice_c::unibusdevice_c() : register_count = 0; // device is not yet enabled, UNIBUS properties can be set base_addr.readonly = false; + priority_slot.readonly = false; intr_vector.readonly = false; intr_level.readonly = false; default_base_addr = 0; @@ -80,13 +81,17 @@ bool unibusdevice_c::on_param_changed(parameter_c *param) { } // define default values for device BASE address and INTR -void unibusdevice_c::set_default_bus_params(uint32_t default_base_addr, unsigned priority_slot, +void unibusdevice_c::set_default_bus_params(uint32_t default_base_addr, unsigned default_priority_slot, unsigned default_intr_vector, unsigned default_intr_level) { - assert(priority_slot <= PRIORITY_SLOT_COUNT); // bitmask! - this->default_base_addr = this->base_addr.value = default_base_addr; - this->default_priority_slot = this->intr_vector.value = priority_slot; - this->default_intr_vector = this->intr_vector.value = default_intr_vector; - this->default_intr_level = this->intr_level.value = default_intr_level; + assert(default_priority_slot <= PRIORITY_SLOT_COUNT); // bitmask! + this->default_base_addr = default_base_addr; + this->default_priority_slot = default_priority_slot; + this->default_intr_vector = this->intr_vector.new_value = default_intr_vector; + this->default_intr_level = this->intr_level.new_value = default_intr_level; + base_addr.set(default_base_addr) ; + priority_slot.set(default_priority_slot) ; + this->on_param_changed(&this->intr_vector) ; + this->on_param_changed(&this->intr_level) ; } void unibusdevice_c::install(void) { diff --git a/10.01_base/2_src/arm/unibusdevice.hpp b/10.01_base/2_src/arm/unibusdevice.hpp index 33dc5c8..09498cd 100644 --- a/10.01_base/2_src/arm/unibusdevice.hpp +++ b/10.01_base/2_src/arm/unibusdevice.hpp @@ -95,7 +95,7 @@ private: public: uint8_t handle; // assigned by "unibus.adapter.register - // !!! slot, vector, level READONLY. If user shoudl change, + // !!! slot, vector, level READONLY. If user should change, // !! add logic to update dma_request_c and intr_request_c // 0 = not "Plugged" in to UNIBUS diff --git a/10.01_base/2_src/pru1/Makefile b/10.01_base/2_src/pru1/Makefile index c4490f4..1e66ac6 100644 --- a/10.01_base/2_src/pru1/Makefile +++ b/10.01_base/2_src/pru1/Makefile @@ -71,9 +71,7 @@ OBJECTS_COMMON= \ $(OBJ_DIR)/pru1_pru_mailbox.object \ $(OBJ_DIR)/pru1_statemachine_arbitration.object \ $(OBJ_DIR)/pru1_statemachine_dma.object \ - $(OBJ_DIR)/pru1_statemachine_init.object \ $(OBJ_DIR)/pru1_statemachine_intr.object \ - $(OBJ_DIR)/pru1_statemachine_powercycle.object \ $(OBJ_DIR)/pru1_statemachine_slave.object \ $(OBJ_DIR)/pru1_timeouts.object \ $(OBJ_DIR)/pru1_utils.object diff --git a/10.01_base/2_src/pru1/pru1_main_test.c b/10.01_base/2_src/pru1/pru1_main_test.c index 7aa8f92..f9119ff 100644 --- a/10.01_base/2_src/pru1/pru1_main_test.c +++ b/10.01_base/2_src/pru1/pru1_main_test.c @@ -55,8 +55,6 @@ #include "pru1_statemachine_dma.h" #include "pru1_statemachine_intr.h" #include "pru1_statemachine_slave.h" -#include "pru1_statemachine_init.h" -#include "pru1_statemachine_powercycle.h" // Supress warnings about using void * as function pointers // sm_slave_state = (statemachine_state_func)&sm_slave_start; @@ -162,16 +160,21 @@ void main(void) { mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done break; } - case ARM2PRU_INITPULSE: // generate a pulse on UNIBUS INIT - // INIT: latch[7], bit 3 - buslatches_setbits(7, BIT(3), BIT(3)); // assert INIT - __delay_cycles(MILLISECS(250)); // INIT is 250ms - buslatches_setbits(7, BIT(3), 0); // deassert INIT - mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done - break; - - case ARM2PRU_POWERCYCLE: // do ACLO/DCLO power cycle - buslatches_powercycle(); + case ARM2PRU_INITALIZATIONSIGNAL_SET: + switch (mailbox.initializationsignal.id) { + case INITIALIZATIONSIGNAL_ACLO: + // assert/deassert ACLO + buslatches_setbits(7, BIT(4), mailbox.initializationsignal.val? BIT(4):0); + break; + case INITIALIZATIONSIGNAL_DCLO: + // assert/deassert DCLO + buslatches_setbits(7, BIT(5), mailbox.initializationsignal.val? BIT(5):0); + break; + case INITIALIZATIONSIGNAL_INIT: + // assert/deassert INIT + buslatches_setbits(7, BIT(3), mailbox.initializationsignal.val? BIT(3):0); + break; + } mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done break; case ARM2PRU_DMA: { 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 6d0c201..c32a539 100644 --- a/10.01_base/2_src/pru1/pru1_main_unibus.c +++ b/10.01_base/2_src/pru1/pru1_main_unibus.c @@ -60,8 +60,6 @@ #include "pru1_statemachine_dma.h" #include "pru1_statemachine_intr.h" #include "pru1_statemachine_slave.h" -#include "pru1_statemachine_init.h" -#include "pru1_statemachine_powercycle.h" // supress warnigns about using void * as function pointers // sm_slave_state = (statemachine_state_func)&sm_slave_start; @@ -78,7 +76,7 @@ High speed not necessary: Bus master will wait with MSYN if UniBone not responding. wathcin BG/BPG signals, catching requested GRANts and forwardinf other GRANTS - - monitorinf INIT and AC_LO/DC_LO + - monitoring INIT and AC_LO/DC_LO - watching fpr AMR2PRU commands 2. "BBSYWAIT": UNibone got PRIORITY GRAMT, has set SACK and released BR/NPR waits for current BUS master to relaeasy BBSY (ony DATI/DATO cycle max) @@ -95,8 +93,6 @@ void main(void) { statemachine_arb_worker_func sm_arb_worker = &sm_arb_worker_client; statemachine_state_func sm_data_slave_state = NULL; statemachine_state_func sm_data_master_state = NULL; - statemachine_state_func sm_init_state = NULL; - statemachine_state_func sm_powercycle_state = NULL; // these are function pointers: could be 16bit on PRU? /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ @@ -132,13 +128,6 @@ void main(void) { // Acess to interna lregsitres may may issue AMR2PRU opcode, so exit loop then ;// execute complete slave cycle, then check NPR/INTR - // one phase of INIT or power cycle - if (sm_powercycle_state) - sm_powercycle_state = sm_powercycle_state(); - else if (sm_init_state) - // init only if no power cycle, power cycle overrides INIT - sm_init_state = sm_init_state(); - // signal INT or PWR FAIL to ARM do_event_initializationsignals(); @@ -249,14 +238,21 @@ void main(void) { // no completion event, could interfer with othe INTRs? mailbox.arm2pru_req = ARM2PRU_NONE; // done break; - case ARM2PRU_INITPULSE: - if (!sm_init_state) - sm_init_state = (statemachine_state_func) &sm_init_start; - // INIT aborts DMA - mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done - break; - case ARM2PRU_POWERCYCLE: - sm_powercycle_state = (statemachine_state_func) &sm_powercycle_start; + case ARM2PRU_INITALIZATIONSIGNAL_SET: + switch (mailbox.initializationsignal.id) { + case INITIALIZATIONSIGNAL_ACLO: + // assert/deassert ACLO + buslatches_setbits(7, BIT(4), mailbox.initializationsignal.val? BIT(4):0); + break; + case INITIALIZATIONSIGNAL_DCLO: + // assert/deassert DCLO + buslatches_setbits(7, BIT(5), mailbox.initializationsignal.val? BIT(5):0); + break; + case INITIALIZATIONSIGNAL_INIT: + // assert/deassert INIT + buslatches_setbits(7, BIT(3), mailbox.initializationsignal.val? BIT(3):0); + break; + } mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done break; case ARM2PRU_HALT: diff --git a/10.01_base/2_src/pru1/pru1_statemachine_init.c b/10.01_base/2_src/pru1/pru1_statemachine_init.c deleted file mode 100644 index 76ab6ff..0000000 --- a/10.01_base/2_src/pru1/pru1_statemachine_init.c +++ /dev/null @@ -1,100 +0,0 @@ -/* pru1_statemachine_init.c: state machine for pulse on INIT - - Copyright (c) 2018, Joerg Hoppe - j_hoppe@t-online.de, www.retrocmp.com - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - 29-jun-2019 JH rework: state returns ptr to next state func - 12-nov-2018 JH entered beta phase - - Statemachine for a pulse on UNIBUS INIT - ! Uses single global timeout, don't run in parallel with other statemachines using timeout ! - */ - -#define _PRU1_STATEMACHINE_INIT_C_ - -#include -#include - -#include "mailbox.h" -#include "pru1_utils.h" -#include "pru1_timeouts.h" - -#include "pru1_buslatches.h" -#include "pru1_statemachine_init.h" -#include "pru1_statemachine_arbitration.h" - -/*** detection of changes in INIT,DCLO,ACLO ***/ - -// detect signal change of INIT,DCLO,ACLO and sent event -// history initialized (among others) by powercycle -// Assume this events come so slow, no one gets raised until -// prev event processed. -void do_event_initializationsignals() { - uint8_t mb_cur = mailbox.events.initialization_signals_cur; // as saved - uint8_t bus_cur = buslatches_getbyte(7) & 0x38; // now sampled - - if (bus_cur & INITIALIZATIONSIGNAL_INIT) - sm_arb.request_mask = 0 ; // INIT clears all PRIORITY request signals - // SACK cleared later on end of INTR/DMA transaction - - if (bus_cur != mb_cur) { - // save old state, so ARM can detect what changed - mailbox.events.initialization_signals_prev = mb_cur; - mailbox.events.initialization_signals_cur = bus_cur; - // trigger the correct event: power and/or INIT - if ((mb_cur ^ bus_cur) & (INITIALIZATIONSIGNAL_DCLO | INITIALIZATIONSIGNAL_ACLO)) - // AC_LO or DC_LO changed - mailbox.events.event_power = 1; - if ((mb_cur ^ bus_cur) & INITIALIZATIONSIGNAL_INIT) - // INIT changed - mailbox.events.event_init = 1; - PRU2ARM_INTERRUPT - ; - } -} - -// forwards -static statemachine_state_func sm_init_state_1(void); - -// setup -statemachine_state_func sm_init_start() { - timeout_set(TIMEOUT_INIT, MILLISECS(INITPULSE_DELAY_MS)); - // INIT: latch[7], bit 3 - buslatches_setbits(7, BIT(3), BIT(3)); // assert INIT - mailbox.events.initialization_signals_prev &= ~INITIALIZATIONSIGNAL_INIT; // force INIT event - return (statemachine_state_func) &sm_init_state_1; -} - -static statemachine_state_func sm_init_state_1() { - if (!timeout_reached(TIMEOUT_INIT)) - return (statemachine_state_func) &sm_init_state_1; // wait - buslatches_setbits(7, BIT(3), 0); // deassert INIT - timeout_cleanup(TIMEOUT_INIT); - return NULL; // ready -} - -// terminate INIT -// To be called from Powercycle? -void sm_init_reset() { - buslatches_setbits(7, BIT(3), 0); // deassert INIT - do_event_initializationsignals(); - timeout_cleanup(TIMEOUT_INIT); -} diff --git a/10.01_base/2_src/pru1/pru1_statemachine_init.h b/10.01_base/2_src/pru1/pru1_statemachine_init.h deleted file mode 100644 index bbfd850..0000000 --- a/10.01_base/2_src/pru1/pru1_statemachine_init.h +++ /dev/null @@ -1,45 +0,0 @@ -/* pru1_statemachine_init.h: state machine for pulse on INIT - - Copyright (c) 2018, Joerg Hoppe - j_hoppe@t-online.de, www.retrocmp.com - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - 29-jun-2019 JH rework: state returns ptr to next state func - 12-nov-2018 JH entered beta phase - */ -#ifndef _PRU1_STATEMACHINE_INIT_H_ -#define _PRU1_STATEMACHINE_INIT_H_ - -#include - -#include "pru1_utils.h" // statemachine_state_func - -#define INITPULSE_DELAY_MS 250 // length of INIT pulse - -#ifndef _PRU1_STATEMACHINE_INIT_C_ -extern uint8_t prev_initialization_signals; -#endif - -void do_event_initializationsignals(void); - -void sm_init_reset(void); -statemachine_state_func sm_init_start(); - -#endif diff --git a/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c b/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c deleted file mode 100644 index 948eee4..0000000 --- a/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c +++ /dev/null @@ -1,109 +0,0 @@ -/* pru1_statemachine_powercycle.c: state machine to generate an ACLO/DCLO pseudo power cycle - - Copyright (c) 2018, Joerg Hoppe - j_hoppe@t-online.de, www.retrocmp.com - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - 29-jun-2019 JH rework: state returns ptr to next state func - 12-nov-2018 JH entered beta phase - - - Statemachine for execution of an ACLO/DCLO pseudo power cycle. - // ACLO: latch[7], bit 4 - // DCLO: latch[7], bit 5 - buslatches_setbits(7, BIT(4), BIT(4)); // ACLO asserted - __delay_cycles(MILLISECS(250)) ; // "power supply shuts down" - buslatches_setbits(7, BIT(5), BIT(5)); // DCLO asserted - __delay_cycles(MILLISECS(250)) ; // "power is OFF now" - buslatches_setbits(7, BIT(4), 0); // ACLO deasserted - __delay_cycles(MILLISECS(250)) ; // "power supply stabilizing" - buslatches_setbits(7, BIT(5), 0); // DCLO deasserted - // CPU has to generate INIT and BBSY - - ! Uses single global timeout, don't run in parallel with other statemachines using timeout ! - */ - -#define _PRU1_STATEMACHINE_POWERCYCLE_C_ - -#include -#include - -#include "mailbox.h" -#include "pru1_utils.h" -#include "pru1_timeouts.h" - -#include "pru1_buslatches.h" -#include "pru1_statemachine_init.h" - -#include "pru1_statemachine_powercycle.h" - -// forwards ; / -static statemachine_state_func sm_powercycle_state_1(void); -static statemachine_state_func sm_powercycle_state_2(void); -static statemachine_state_func sm_powercycle_state_3(void); -static statemachine_state_func sm_powercycle_state_4(void); - -// setup with -statemachine_state_func sm_powercycle_start() { - return (statemachine_state_func) &sm_powercycle_state_1; - // next call to sm_slave.state() starts state machine -} - -// "Line power shutdown": assert ACLO, then wait -static statemachine_state_func sm_powercycle_state_1() { - buslatches_setbits(7, BIT(4), BIT(4)); // ACLO asserted - timeout_set(TIMEOUT_POWERCYCLE, MILLISECS(POWERCYCLE_DELAY_MS)); // wait for DC power shutdown - // DEBUG_OUT(0x01) ; - // DEBUG_OUT(0x02) ; - return (statemachine_state_func) &sm_powercycle_state_2; -} - -// "Power supply switched off": assert DCLO, then wait -static statemachine_state_func sm_powercycle_state_2() { - if (!timeout_reached(TIMEOUT_POWERCYCLE)) - return (statemachine_state_func) &sm_powercycle_state_2; // wait - buslatches_setbits(7, BIT(5), BIT(5)); // DCLO asserted - timeout_set(TIMEOUT_POWERCYCLE, MILLISECS(POWERCYCLE_DELAY_MS)); // system powered off - // DEBUG_OUT(0x03) ; - // DEBUG_OUT(0x04) ; - // make sure we don't "come up from power" with INIT already set. - sm_init_reset(); - - return (statemachine_state_func) &sm_powercycle_state_3; -} - -// "Line power back again": deassert ACLO, then wait -static statemachine_state_func sm_powercycle_state_3() { - if (!timeout_reached(TIMEOUT_POWERCYCLE)) - return (statemachine_state_func) &sm_powercycle_state_3; // wait - buslatches_setbits(7, BIT(4), 0); // ACLO deasserted - timeout_set(TIMEOUT_POWERCYCLE, MILLISECS(POWERCYCLE_DELAY_MS)); // "power supply stabilizing" - return (statemachine_state_func) &sm_powercycle_state_4; -} - -// "Logic power stabilized": deassert DCLO, ready -static statemachine_state_func sm_powercycle_state_4() { - if (!timeout_reached(TIMEOUT_POWERCYCLE)) - return (statemachine_state_func) &sm_powercycle_state_4; - buslatches_setbits(7, BIT(5), 0); // DCLO deasserted - timeout_cleanup(TIMEOUT_POWERCYCLE); - return NULL; -} - diff --git a/10.01_base/2_src/pru1/pru1_statemachine_powercycle.h b/10.01_base/2_src/pru1/pru1_statemachine_powercycle.h deleted file mode 100644 index bc96363..0000000 --- a/10.01_base/2_src/pru1/pru1_statemachine_powercycle.h +++ /dev/null @@ -1,37 +0,0 @@ -/* pru1_statemachine_powercycle.h: state machine to generate an ACLO/DCLO pseudo power cycle - - Copyright (c) 2018, Joerg Hoppe - j_hoppe@t-online.de, www.retrocmp.com - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - 29-jun-2019 JH rework: state returns ptr to next state func - 12-nov-2018 JH entered beta phase - */ -#ifndef _PRU1_STATEMACHINE_POWERCYCLE_H_ -#define _PRU1_STATEMACHINE_POWERCYCLE_H_ - -#include -#include "pru1_utils.h" // statemachine_state_func - -#define POWERCYCLE_DELAY_MS 100 // wait period in millsecs between ACLO/DCLO transitions - -statemachine_state_func sm_powercycle_start(); - -#endif diff --git a/10.01_base/2_src/pru1/pru1_timeouts.h b/10.01_base/2_src/pru1/pru1_timeouts.h index 4ce669a..91008bf 100644 --- a/10.01_base/2_src/pru1/pru1_timeouts.h +++ b/10.01_base/2_src/pru1/pru1_timeouts.h @@ -29,13 +29,11 @@ #include // predefined timeouts -#define TIMEOUT_COUNT 4 +#define TIMEOUT_COUNT 2 // fixed pointers #define TIMEOUT_DMA (&timeout_target_cycles[0]) -#define TIMEOUT_INIT (&timeout_target_cycles[1]) -#define TIMEOUT_POWERCYCLE (&timeout_target_cycles[2]) -#define TIMEOUT_SACK (&timeout_target_cycles[3]) +#define TIMEOUT_SACK (&timeout_target_cycles[1]) // cycle end count for each active timeoput. extern uint32_t timeout_target_cycles[TIMEOUT_COUNT]; diff --git a/10.01_base/2_src/pru1/pru1_utils.c b/10.01_base/2_src/pru1/pru1_utils.c index edd9f70..a681e1d 100644 --- a/10.01_base/2_src/pru1/pru1_utils.c +++ b/10.01_base/2_src/pru1/pru1_utils.c @@ -28,5 +28,38 @@ #include +#include "mailbox.h" +#include "pru1_buslatches.h" +#include "pru1_statemachine_arbitration.h" #include "pru1_utils.h" + +// detect signal change of INIT,DCLO,ACLO and sent event +// history initialized (among others) by powercycle +// Assume this events come so slow, no one gets raised until +// prev event processed. +void do_event_initializationsignals() { + uint8_t mb_cur = mailbox.events.initialization_signals_cur; // as saved + uint8_t bus_cur = buslatches_getbyte(7) & 0x38; // now sampled + + if (bus_cur & INITIALIZATIONSIGNAL_INIT) + sm_arb.request_mask = 0 ; // INIT clears all PRIORITY request signals + // SACK cleared later on end of INTR/DMA transaction + + if (bus_cur != mb_cur) { + // save old state, so ARM can detect what changed + mailbox.events.initialization_signals_prev = mb_cur; + mailbox.events.initialization_signals_cur = bus_cur; + // trigger the correct event: power and/or INIT + if ((mb_cur ^ bus_cur) & (INITIALIZATIONSIGNAL_DCLO | INITIALIZATIONSIGNAL_ACLO)) + // AC_LO or DC_LO changed + mailbox.events.event_power = 1; + if ((mb_cur ^ bus_cur) & INITIALIZATIONSIGNAL_INIT) + // INIT changed + mailbox.events.event_init = 1; + PRU2ARM_INTERRUPT + ; + } +} + + diff --git a/10.01_base/2_src/pru1/pru1_utils.h b/10.01_base/2_src/pru1/pru1_utils.h index a60d0f7..d0c6733 100644 --- a/10.01_base/2_src/pru1/pru1_utils.h +++ b/10.01_base/2_src/pru1/pru1_utils.h @@ -125,4 +125,7 @@ typedef void * (*statemachine_state_func)(void); __R31 = PRU2ARM_INTERRUPT_PRU0_R31_VEC_VALID |PRU2ARM_INTERRUPT_SIGNUM ; /* 35 */ \ } while(0) +void do_event_initializationsignals(void) ; + + #endif diff --git a/10.01_base/2_src/shared/mailbox.h b/10.01_base/2_src/shared/mailbox.h index 1ab0200..0cee708 100644 --- a/10.01_base/2_src/shared/mailbox.h +++ b/10.01_base/2_src/shared/mailbox.h @@ -40,8 +40,7 @@ #define ARM2PRU_BUSLATCH_GET 6 // read a mux register #define ARM2PRU_BUSLATCH_EXERCISER 7 // exercise 8 accesses to mux registers #define ARM2PRU_BUSLATCH_TEST 8 // read a mux register -#define ARM2PRU_INITPULSE 9 // pulse UNIBUS INIT -#define ARM2PRU_POWERCYCLE 10 // ACLO/DCLO power cycle simulation +#define ARM2PRU_INITALIZATIONSIGNAL_SET 9 // set an ACL=/DCLO/INIT signal #define ARM2PRU_ARB_MODE_NONE 11 // DMA without NPR/NPG/SACK arbitration #define ARM2PRU_ARB_MODE_CLIENT 12 // DMA with arbitration by external Arbitrator #define ARM2PRU_ARB_MODE_MASTER 13 // DMA as Arbitrator @@ -52,6 +51,14 @@ #define ARM2PRU_DDR_FILL_PATTERN 18 // fill DDR with test pattern #define ARM2PRU_DDR_SLAVE_MEMORY 19 // use DDR as UNIBUS slave memory + +// signal IDs for ARM2PRU_INITALIZATIONSIGNAL_* +// states of initialization section lines. Bitmask = latch[7] +#define INITIALIZATIONSIGNAL_INIT (1 << 3) +#define INITIALIZATIONSIGNAL_ACLO (1 << 4) +#define INITIALIZATIONSIGNAL_DCLO (1 << 5) + + // possible states of DMA machine #define DMA_STATE_READY 0 // idle #define DMA_STATE_ARBITRATING 1 // in NPR/NPG/SACK arbitration @@ -107,6 +114,11 @@ typedef struct { uint8_t data_8_15; } mailbox_buslatch_test_t; +typedef struct { + uint16_t id; // which signal to set or get? one of INITIALIZATIONSIGNAL_* + uint16_t val; // value set/get. +} mailbox_initializationsignal_t; + // data for bus arbitrator typedef struct { @@ -158,11 +170,6 @@ typedef struct { // multiple of 32 bit now } mailbox_intr_t; -// states of initialization section lines. Bitmask = latch[7] -#define INITIALIZATIONSIGNAL_INIT (1 << 3) -#define INITIALIZATIONSIGNAL_ACLO (1 << 4) -#define INITIALIZATIONSIGNAL_DCLO (1 << 5) - typedef struct { // trigger flags raised by PRU, reset by ARM // differemt events can be raised asynchronically and concurrent, @@ -234,6 +241,7 @@ typedef struct { mailbox_buslatch_t buslatch; mailbox_buslatch_test_t buslatch_test; mailbox_buslatch_exerciser_t buslatch_exerciser; + mailbox_initializationsignal_t initializationsignal ; }; } mailbox_t; diff --git a/10.02_devices/2_src/dl11w.cpp b/10.02_devices/2_src/dl11w.cpp index 9f82576..3e4c694 100644 --- a/10.02_devices/2_src/dl11w.cpp +++ b/10.02_devices/2_src/dl11w.cpp @@ -70,15 +70,6 @@ slu_c::slu_c() : // SLU has 2 Interrupt vectors: base = RCV, base+= XMT // put in slot 1, closest to CPU set_default_bus_params(SLU_ADDR, SLU_SLOT, SLU_VECTOR, SLU_LEVEL); // base addr, intr-vector, intr level - rcvintr_request.set_priority_slot(default_priority_slot); - rcvintr_request.set_level(default_intr_level); - rcvintr_request.set_vector(default_intr_vector); - // XMT INTR: lower priority->netx slot, and next vector - xmtintr_request.set_priority_slot(default_priority_slot + 1); - xmtintr_request.set_level(default_intr_level); - xmtintr_request.set_vector(default_intr_vector + 4); - - // init parameters // controller has some register register_count = slu_idx_count; @@ -152,6 +143,16 @@ bool slu_c::on_param_changed(parameter_c *param) { mode.readonly = false; INFO("Serial port %s closed", serialport.value.c_str()); } + } else if (param == &priority_slot) { + rcvintr_request.set_priority_slot(priority_slot.new_value); + // XMT INTR: lower priority => nxt slot, and next vector + xmtintr_request.set_priority_slot(priority_slot.new_value + 1); + } else if (param == &intr_vector) { + rcvintr_request.set_vector(intr_vector.new_value); + xmtintr_request.set_vector(intr_vector.new_value + 4); + } else if (param == &intr_level) { + rcvintr_request.set_level(intr_level.new_value); + xmtintr_request.set_level(intr_level.new_value); } return unibusdevice_c::on_param_changed(param); // more actions (for enable) } @@ -471,9 +472,6 @@ ltc_c::ltc_c() : log_label = "ltc"; // slot = 3: set_default_bus_params(LTC_ADDR, LTC_SLOT, LTC_VECTOR, LTC_LEVEL); // base addr, intr-vector, intr level - intr_request.set_priority_slot(default_priority_slot); - intr_request.set_level(default_intr_level); - intr_request.set_vector(default_intr_vector); // controller has only one register register_count = 1; @@ -501,8 +499,15 @@ bool ltc_c::on_param_changed(parameter_c *param) { if (param == &frequency) { // accept only these return (frequency.new_value == 50 || frequency.new_value == 60); - } else - return unibusdevice_c::on_param_changed(param); // more actions (for enable) + } else if (param == &priority_slot) { + intr_request.set_priority_slot(priority_slot.new_value); + } else if (param == &intr_level) { + intr_request.set_level(intr_level.new_value); + } else if (param == &intr_vector) { + intr_request.set_vector(intr_vector.new_value); + } + + return unibusdevice_c::on_param_changed(param); // more actions (for enable) } // calc static INTR condition level. diff --git a/10.02_devices/2_src/dl11w.hpp b/10.02_devices/2_src/dl11w.hpp index 7b61613..ea19985 100644 --- a/10.02_devices/2_src/dl11w.hpp +++ b/10.02_devices/2_src/dl11w.hpp @@ -167,27 +167,6 @@ public: parameter_bool_c break_enable = parameter_bool_c(this, "break", "b", /*readonly*/false, "Enable BREAK transmission (M7856 SW4-1)"); -#ifdef USED - // @David: duplicating device registers as parameters is not necessary ... - // they can be seen with "exam" anyhow. - parameter_unsigned_c rcsr = parameter_unsigned_c(this, "Receiver Status Register", "rcsr", /*readonly*/ - false, "", "%o", "Internal state", 32, 8); - parameter_unsigned_c rbuf = parameter_unsigned_c(this, "Receiver Buffer Register", "rbuf", /*readonly*/ - false, "", "%o", "Internal state", 32, 8); - parameter_unsigned_c xcsr = parameter_unsigned_c(this, "Transmitter Status Register", - "xcsr", /*readonly*/false, "", "%o", "Internal state", 32, 8); - parameter_unsigned_c xbuf = parameter_unsigned_c(this, "Transmitter Buffer Register", - "xbuf", /*readonly*/false, "", "%o", "Internal state", 32, 8); - - parameter_bool_c xmit_interrupt_enable = parameter_bool_c(this, "XMIT interrupt enable", - "xie",/*readonly*/false, "1 = enable interrupt"); - parameter_bool_c rcvr_interrupt_enable = parameter_bool_c(this, "RCVR interrupt enable", - "rie",/*readonly*/false, "1 = enable interrupt"); - parameter_bool_c slu_maint = parameter_bool_c(this, "XCSR Maintenance", "maint",/*readonly*/ - false, "1 = enable Maintenance mode enabled"); - parameter_bool_c rdr_enable = parameter_bool_c(this, "RDR enable", "rdre",/*readonly*/false, - "1 = enable reader enable"); -#endif // background worker function void worker(unsigned instance) override; void worker_rcv(void); diff --git a/10.02_devices/2_src/rk11.cpp b/10.02_devices/2_src/rk11.cpp index 5d99707..374c6f4 100755 --- a/10.02_devices/2_src/rk11.cpp +++ b/10.02_devices/2_src/rk11.cpp @@ -4,7 +4,7 @@ Copyright Vulcan Inc. 2019 via Living Computers: Museum + Labs, Seattle, WA. Contributed under the BSD 2-clause license. -*/ + */ #include #include @@ -28,10 +28,6 @@ rk11_c::rk11_c() : // base addr, intr-vector, intr level set_default_bus_params(0777400, 10, 0220, 5) ; - dma_request.set_priority_slot(default_priority_slot) ; - intr_request.set_priority_slot(default_priority_slot) ; - intr_request.set_level(default_intr_level) ; - intr_request.set_vector(default_intr_vector) ; // The RK11 controller has seven registers, // We allocate 8 because one address in the address space is unused. @@ -124,6 +120,14 @@ rk11_c::~rk11_c() // verify "new_value", must output error messages bool rk11_c::on_param_changed(parameter_c *param) { // no own parameter or "enable" logic + if (param == &priority_slot) { + dma_request.set_priority_slot(priority_slot.new_value); + intr_request.set_priority_slot(priority_slot.new_value); + } else if (param == &intr_level) { + intr_request.set_level(intr_level.new_value); + } else if (param == &intr_vector) { + intr_request.set_vector(intr_vector.new_value); + } return storagecontroller_c::on_param_changed(param) ; // more actions (for enable) } @@ -189,6 +193,7 @@ void rk11_c::dma_transfer(DMARequest &request) } } + // If an IBA DMA read from memory, we need to fill the request buffer // with the single word returned from memory by the DMA operation. if (request.iba && !request.write) diff --git a/10.02_devices/2_src/rl11.cpp b/10.02_devices/2_src/rl11.cpp index 405be10..4bafd18 100644 --- a/10.02_devices/2_src/rl11.cpp +++ b/10.02_devices/2_src/rl11.cpp @@ -138,10 +138,6 @@ RL11_c::RL11_c(void) : // base addr, intr-vector, intr level set_default_bus_params(0774400, 15, 0160, 5); - dma_request.set_priority_slot(default_priority_slot); - intr_request.set_priority_slot(default_priority_slot); - intr_request.set_level(default_intr_level); - intr_request.set_vector(default_intr_vector); // add 4 RL disk drives drivecount = 4; @@ -206,7 +202,15 @@ bool RL11_c::on_param_changed(parameter_c *param) { // disabled disconnect_from_panel(); } + } else if (param == &priority_slot) { + dma_request.set_priority_slot(priority_slot.new_value); + intr_request.set_priority_slot(priority_slot.new_value); + } else if (param == &intr_level) { + intr_request.set_level(intr_level.new_value); + } else if (param == &intr_vector) { + intr_request.set_vector(intr_vector.new_value); } + return storagecontroller_c::on_param_changed(param); // more actions (for enable) } @@ -847,11 +851,11 @@ void RL11_c::worker(unsigned instance) { // may still be inactive, when PRU updatesit with iNTR delayed. // enable operation of pending on_after_register_access() /* - if (!(busreg_CS->active_dati_flipflops & 0x80)) { // CRDY must be set - ERROR("CRDY not set, CS=%06o", busreg_CS->active_dati_flipflops); - logger->dump(logger->default_filepath); - } - */ + if (!(busreg_CS->active_dati_flipflops & 0x80)) { // CRDY must be set + ERROR("CRDY not set, CS=%06o", busreg_CS->active_dati_flipflops); + logger->dump(logger->default_filepath); + } + */ res = pthread_cond_wait(&on_after_register_access_cond, &on_after_register_access_mutex); if (res != 0) { diff --git a/10.02_devices/2_src/uda.cpp b/10.02_devices/2_src/uda.cpp index d7a12d9..7030b30 100644 --- a/10.02_devices/2_src/uda.cpp +++ b/10.02_devices/2_src/uda.cpp @@ -48,10 +48,6 @@ uda_c::uda_c() : // base addr, intr-vector, intr level set_default_bus_params(0772150, 20, 0154, 5) ; - dma_request.set_priority_slot(default_priority_slot) ; - intr_request.set_priority_slot(default_priority_slot) ; - intr_request.set_level(default_intr_level) ; - intr_request.set_vector(default_intr_vector) ; // The UDA50 controller has two registers. register_count = 2; @@ -99,6 +95,14 @@ uda_c::~uda_c() bool uda_c::on_param_changed(parameter_c *param) { // no own parameter or "enable" logic + if (param == &priority_slot) { + dma_request.set_priority_slot(priority_slot.new_value); + intr_request.set_priority_slot(priority_slot.new_value); + } else if (param == &intr_level) { + intr_request.set_level(intr_level.new_value); + } else if (param == &intr_vector) { + intr_request.set_vector(intr_vector.new_value); + } return storagecontroller_c::on_param_changed(param) ; // more actions (for enable) } diff --git a/10.03_app_demo/2_src/menu_devices.cpp b/10.03_app_demo/2_src/menu_devices.cpp index 966dbb6..a78f3a4 100644 --- a/10.03_app_demo/2_src/menu_devices.cpp +++ b/10.03_app_demo/2_src/menu_devices.cpp @@ -444,7 +444,7 @@ void application_c::menu_devices(bool with_CPU) { if (timeout) printf("Bus timeout at %06o.\n", mailbox->dma.cur_addr); } else if (!strcasecmp(s_opcode, "e") && n_fields <= 2) { - bool timeout; + bool timeout = false; uint32_t addr; unibusdevice_register_t *reg = NULL ; if (n_fields == 2) { // single reg number or address given