1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-04-03 20:32:28 +00:00

ACLO/DCLO/INIT moved from PRU to ARM

INTR/DMA request params linked to device params on change
This commit is contained in:
Joerg Hoppe
2019-08-19 13:12:42 +02:00
parent e2229871de
commit 3d1d9d3cf6
23 changed files with 183 additions and 409 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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: {

View File

@@ -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:

View File

@@ -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 <stdlib.h>
#include <stdint.h>
#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);
}

View File

@@ -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 <stdint.h>
#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

View File

@@ -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 <stdlib.h>
#include <stdint.h>
#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;
}

View File

@@ -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 <stdint.h>
#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

View File

@@ -29,13 +29,11 @@
#include <stdbool.h>
// 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];

View File

@@ -28,5 +28,38 @@
#include <stdint.h>
#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
;
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);

View File

@@ -4,7 +4,7 @@
Copyright Vulcan Inc. 2019 via Living Computers: Museum + Labs, Seattle, WA.
Contributed under the BSD 2-clause license.
*/
*/
#include <string.h>
#include <assert.h>
@@ -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)

View File

@@ -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) {

View File

@@ -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)
}

View File

@@ -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