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

Cleanup incomplete commits

This commit is contained in:
Joerg Hoppe
2019-06-18 20:38:07 +02:00
parent a4dc6af85c
commit 1a79abb89f
55 changed files with 1241 additions and 94 deletions

View File

@@ -204,7 +204,7 @@ bool memoryimage_c::load_addr_value_text(const char *fname) {
fin = fopen(fname, "r");
if (!fin) {
printf("%s\n", fileErrorText("Error opening file %s for write", fname)) ;
printf("%s\n", fileErrorText("Error opening file %s for write", fname)) ;
return false;
}
entry_address = MEMORY_ADDRESS_INVALID; // not known
@@ -538,6 +538,7 @@ bool memoryimage_c::load_papertape(const char *fname) {
entry_address = MEMORY_ADDRESS_INVALID; // not yet known
stream_byte_index = 0;
block_byte_size = addr = 0 ; // -Wmaybe-uninitialized
while (!feof(fin)) {
b = fgetc(fin);
// ERROR("[0x%04x] state=%d b=0x%02x sum=0x%02x block_byte_idx=%d",

View File

@@ -134,6 +134,7 @@ int pru_c::start(enum prucode_enum prucode_id) {
// use stop() before restart()
assert(this->prucode_id == PRUCODE_NONE);
/* initialize PRU */
if ((rtn = prussdrv_init()) != 0) {
ERROR("prussdrv_init() failed");
@@ -152,6 +153,7 @@ int pru_c::start(enum prucode_enum prucode_id) {
goto error;
}
/*
http://credentiality2.blogspot.com/2015/09/beaglebone-pru-ddr-memory-access.html
* get pointer to shared DDR
@@ -165,6 +167,13 @@ int pru_c::start(enum prucode_enum prucode_id) {
ddrmem->base_physical = prussdrv_get_phys_addr((void *) (ddrmem->base_virtual));
ddrmem->info(); // may abort program
// get address of mail box struct in PRU
mailbox_connect();
// now all mailbox command fields initialized/cleared, PRUs can be started
// get address of device register descriptor struct in PRU
iopageregisters_connect();
// search code in dictionary
struct prucode_entry *pce;
for (pce = prucode; pce->id != prucode_id && pce->id != PRUCODE_EOD; pce++)
@@ -190,19 +199,20 @@ int pru_c::start(enum prucode_enum prucode_id) {
pce->pru1_entry)) != 0) {
FATAL("prussdrv_exec_program(PRU1) failed");
}
INFO("Loaded pru code with id = %d", prucode_id);
INFO("Loaded and started PRU code with id = %d", prucode_id);
timeout.wait_ms(100); // wait for PRU to come up, much too long
// get address of mail box struct in PRU
mailbox_connect();
// now all fields initialized/cleared
// get address of device register descriptor struct in PRU
iopageregisters_connect();
this->prucode_id = prucode_id;
// verify PRU1 is executing its command loop
mailbox->arm2pru_req = ARM2PRU_NOP;
timeout.wait_ms(1);
if (mailbox->arm2pru_req != ARM2PRU_NONE) {
FATAL("PRU1 is not executing its command loop");
goto error;
}
return rtn;
error: //

View File

@@ -157,7 +157,7 @@ void storagedrive_c::file_write(uint8_t *buffer, uint64_t position, unsigned len
// 3. write data
f.write((const char*) buffer, len);
if (f.fail())
ERROR("file_write() failure on %s", name);
ERROR("file_write() failure on %s", name.value.c_str());
f.flush();
}
@@ -177,7 +177,7 @@ void storagedrive_selftest_c::block_buffer_fill(unsigned block_number) {
assert((block_size % 4) == 0); // whole uint32
for (unsigned i = 0; i < block_size / 4; i++) {
// i counts dwords in buffer
// pattern: global incrementing uint32
// pattern: global incrementing uint32
uint32_t pattern = i + (block_number * block_size / 4);
((uint32_t*) block_buffer)[i] = pattern;
}
@@ -188,7 +188,7 @@ void storagedrive_selftest_c::block_buffer_check(unsigned block_number) {
assert((block_size % 4) == 0); // whole uint32
for (unsigned i = 0; i < block_size / 4; i++) {
// i counts dwords in buffer
// pattern: global incrementing uint32
// pattern: global incrementing uint32
uint32_t pattern_expected = i + (block_number * block_size / 4);
uint32_t pattern_found = ((uint32_t*) block_buffer)[i];
if (pattern_expected != pattern_found) {

View File

@@ -140,7 +140,7 @@ void unibus_c::interrupt(uint8_t priority, uint16_t vector) {
bool unibus_c::dma(enum unibus_c::arbitration_mode_enum arbitration_mode, uint8_t control,
uint32_t startaddr, unsigned blocksize) {
uint64_t dmatime_ns, totaltime_ns;
uint8_t dma_opcode;
uint8_t dma_opcode = ARBITRATION_MODE_NONE; // inihibit compiler warnings
// can access bus with DMA when there's a Bus Arbitrator
assert(pru->prucode_id == pru_c::PRUCODE_UNIBUS);

View File

@@ -0,0 +1,56 @@
/* pru0_main.c: endless loop, writes outputs on R30 from mailbox (C solution)
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.
12-nov-2018 JH entered beta phase
from d:\RetroCmp\dec\pdp11\UniBone\91_3rd_party\pru-c-compile\pru-software-support-package\examples\am335x\PRU_gpioToggle\
*/
#include <stdint.h>
#include <pru_cfg.h>
#include "resource_table_empty.h"
#include "pru_pru_mailbox.h"
volatile register uint32_t __R30;
volatile register uint32_t __R31;
void main(void) {
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
// loop forever
void pru0_dataout(void) ;
pru0_dataout() ;
#ifdef USED
// old code using shared RAM mailbox, not reached
while(1) {
__R30 = pru_pru_mailbox.pru0_r30 ;
}
#endif
}

View File

@@ -0,0 +1,210 @@
/* pru1_main.c: main loop with mailbox cmd interface. Test functions.
Copyright (c) 2018-2019, 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.
28-mar-2019 JH split off from "all-function" main
12-nov-2018 JH entered beta phase
Functions to test GPIOs, shared memory and mailbox.
Separated from "all-function" main() because of PRU code size limits.
Application has to load this into PRU1 depending on system state.
from d:\RetroCmp\dec\pdp11\UniBone\91_3rd_party\pru-c-compile\pru-software-support-package\examples\am335x\PRU_gpioToggle
Test GPIO, shared mem and interrupt
a) waits until ARM writes a value to mailbox.arm2pru_req
b) ACKs the value in mailbox.arm2pru_resp, clears arm2pru_req
c) toggles 1 mio times GPIO, with delay as set by ARM
d) signal EVENT0
e) goto a
*/
#include <stdint.h>
#include <stdbool.h>
#include <pru_cfg.h>
#include "resource_table_empty.h"
#include "pru1_utils.h"
#include "pru_pru_mailbox.h"
#include "mailbox.h"
#include "ddrmem.h"
#include "iopageregister.h"
#include "pru1_buslatches.h"
#include "pru1_statemachine_arbitration.h"
#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"
void main(void) {
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
// clear all tables, as backup if ARM fails todo
iopageregisters_init();
buslatches_reset(); // all deasserted
// init mailbox
mailbox.arm2pru_req = ARM2PRU_NONE;
mailbox.events.eventmask = 0;
mailbox.events.initialization_signals_prev = 0;
mailbox.events.initialization_signals_cur = 0;
while (1) {
// display opcode (active for one cycle
// __R30 = (mailbox.arm2pru_req & 0xf) << 8;
/*
mailbox.arm2pru_resp = mailbox.arm2pru_req ;
__R30 = (mailbox.arm2pru_resp & 0xf) << 8;
mailbox.arm2pru_resp = mailbox.arm2pru_req ;
}
*/
/*** Attention: arm2pru_req (and all mailbox vars) change at ANY TIME
* - ARM must set arm2pru_req as last operation on mailbox,
* memory barrier needed.
* - ARM may not access mailbox until arm2pru_req is 0
* - PRU only clears arm2pru_req after actual processing if mailbox
* ***/
switch (mailbox.arm2pru_req) {
case ARM2PRU_NONE: // == 0
// reloop
break;
case ARM2PRU_NOP: // needed to probe PRU run state
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_HALT:
__halt(); // that's it
break;
#ifdef USED
case ARM2PRU_MAILBOXTEST1:
// simulate a register read access.
#ifdef TEST_TIMEOUT
while (1) {
// toggle with REGSEL_0 = PRU1_8
__R30 |= (1 << 8);
// buslatches_setbits(1, BIT(6), BIT(6)) ;
TIMEOUT_SET(NANOSECS(1000));// 1 usec / level
while (!TIMEOUT_REACHED);
__R30 &= ~(1 << 8);
//buslatches_setbits(1, BIT(6), 0) ;
TIMEOUT_SET(NANOSECS(1000));
while (!TIMEOUT_REACHED);
}
#endif
// show on REG_DATAOUT
buslatches_pru0_dataout(mailbox.mailbox_test.addr);
// pru_pru_mailbox.pru0_r30 = mailbox.mailbox_test.addr & 0xff;
// __R30 = (mailbox.mailbox_test.addr & 0xf) << 8;
mailbox.mailbox_test.val = mailbox.mailbox_test.addr;
__R30 = (mailbox.arm2pru_req & 0xf) << 8; // optical ACK
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
#endif
case ARM2PRU_BUSLATCH_INIT: // set all mux registers to "neutral"
buslatches_reset();
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_BUSLATCH_SET: { // set a mux register
// don't feed "volatile" vars into buslatch_macros !!!
uint8_t reg_sel = mailbox.buslatch.addr & 7;
uint8_t bitmask = mailbox.buslatch.bitmask;
uint8_t val = mailbox.buslatch.val;
//buslatches.cur_reg_sel = 0xff; // force new setting of reg_sel
if (BUSLATCHES_REG_IS_BYTE(reg_sel))
buslatches_setbyte(reg_sel, val);
else
buslatches_setbits(reg_sel, bitmask, val);
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
}
case ARM2PRU_BUSLATCH_GET: {
// don't feed "volatile" vars into buslatch_macros !!!
uint8_t reg_sel = mailbox.buslatch.addr & 7;
// buslatches.cur_reg_sel = 0xff; // force new setting of reg_sel
mailbox.buslatch.val = buslatches_getbyte(reg_sel);
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
}
case ARM2PRU_BUSLATCH_EXERCISER: // exercise 8 byte accesses to mux registers
buslatches_exerciser() ;
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break ;
case ARM2PRU_BUSLATCH_TEST: {
buslatches_test(mailbox.buslatch_test.addr_0_7, mailbox.buslatch_test.addr_8_15,
mailbox.buslatch_test.data_0_7, mailbox.buslatch_test.data_8_15);
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();
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_DMA_ARB_NONE:
sm_dma_start(); // without NPR/NPG arbitration
// simply call current state function, until stopped
// parallel the BUS-slave statemachine is triggered
// by master logic.
while (!sm_dma.state())
;
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_DDR_FILL_PATTERN:
ddrmem_fill_pattern();
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_DDR_SLAVE_MEMORY:
// respond to UNIBUS cycles as slave and
// access DDR as UNIBUS memory.
// only debugging: all signals deasserted
buslatches_reset();
// do UNIBUS slave cycles, until ARM abort this by
// writing into mailbox.arm2pru_req
while (mailbox.arm2pru_req == ARM2PRU_DDR_SLAVE_MEMORY) {
sm_slave_start();
// do all states of an access, start when MSYN found.
while (!sm_slave.state())
;
}
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
} // switch
} // while
}

View File

@@ -0,0 +1,209 @@
/* pru1_main_unibus.c: main loop with mailbox cmd interface. UNIBUS devices with opt. phys. PDP-11 CPU.
Copyright (c) 2018-2019, 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.
28-mar-2019 JH split off from "all-function" main
12-nov-2018 JH entered beta phase
Master and slave functionality for UNIBUS devices.
Assumes a physical PDP-11 CPU is working as Arbitrator for
NPR/NG/SACK and BR/BG/SACK.
Needed if UniBone runs in a system running PDP-11 CPU
and simulated or physical devices do DMA or INTR.
Separated from "all-function" main() because of PRU code size limits.
Application has to load this into PRU1 depending on system state.
from d:\RetroCmp\dec\pdp11\UniBone\91_3rd_party\pru-c-compile\pru-software-support-package\examples\am335x\PRU_gpioToggle
Test GPIO, shared mem and interrupt
a) waits until ARM writes a value to mailbox.arm2pru_req
b) ACKs the value in mailbox.arm2pru_resp, clears arm2pru_req
c) toggles 1 mio times GPIO, with delay as set by ARM
d) signal EVENT0
e) goto a
*/
#include <stdint.h>
#include <stdbool.h>
#include <pru_cfg.h>
#include "resource_table_empty.h"
#include "pru1_utils.h"
#include "pru_pru_mailbox.h"
#include "mailbox.h"
#include "ddrmem.h"
#include "iopageregister.h"
#include "pru1_buslatches.h"
#include "pru1_statemachine_arbitration.h"
#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"
void main(void) {
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
// clear all tables, as backup if ARM fails todo
iopageregisters_init();
buslatches_reset(); // all deasserted, caches cleared
/* ARM must init mailbox, especially:
mailbox.arm2pru_req = ARM2PRU_NONE;
mailbox.events.eventmask = 0;
mailbox.events.initialization_signals_prev = 0;
mailbox.events.initialization_signals_cur = 0;
*/
/* start parallel emulation of all devices,
* Process __DMA and _INTR bus master operations
*
* ! Several state machines (DMA, Powercycle, INIT,) use the same global timeout.
* ! Never execute these in parallel !
*/
// Reset PDP-11 with power-cycle simulation.
// Necessary, as until now NPR/NPG/BG/BR/SACK lines were "unconnected"
// buslatches_powercycle();
// __delay_cycles(MILLISECS(100));
// execute 2x, because M9312 boot ROMs need this
// __delay_cycles(MILLISECS(250));
// buslatches_powercycle();
// buslatches_pulse_debug ;
// base operation: accept and execute slave cycles
sm_slave_start();
while (true) {
uint32_t arm2pru_req_cached;
// do all states of an access, start when MSYN found.
// slave cycles may trigger events to ARM, which changes "active" registers
// and issues interrupts
while (!sm_slave.state())
; // execute complete slave cycle, then check NPR/INTR
// update state of init lines
// INIT never asserted in the midst of a transaction, bit 3,4,5
do_event_initializationsignals();
// standard operation may be interrupt by other requests
arm2pru_req_cached = mailbox.arm2pru_req;
switch (arm2pru_req_cached) {
case ARM2PRU_NONE:
// pass BG[4-7] to next device, state machine "idle"
// pass all Arbitration GRANT IN to GRANT OUT for next device.
// This is not necessary while INTR or DMA is actiove:
// INTR is only 1 cycle, DMA has SACK set all the time, arbitration
// prohibited then.
sm_arb_state_idle();
// do only forward GRANT lines if not INTR is pending,
// else our GRANT would be passed too.
break; // fast case: only slave operation
case ARM2PRU_NOP: // needed to probe PRU run state
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_DMA_ARB_NONE: // ignore SACK condition
case ARM2PRU_DMA_ARB_MASTER: // also without arbitration, TODO!
sm_dma_start();
while (!sm_dma.state())
;
// a dma cycle into a device register may trigger an interrupt
// do not delete that condition
if (mailbox.arm2pru_req == arm2pru_req_cached)
mailbox.arm2pru_req = ARM2PRU_NONE; // clear request
break;
case ARM2PRU_DMA_ARB_CLIENT:
// start DMA cycle
// can not run parallel with INTR levels
sm_arb_start(ARBITRATION_PRIORITY_BIT_NP);
while (!sm_arb.state()) {
// sm_slave is most time critical, as it must keep track with MSYN/SSYN bus traffic.
// so give it more cpu cycles
while (!sm_slave.state())
;
}
// now SACK held and BBSY set, slave state machine ended, since BBSY found inactive
// debug pin reset by bus access
//DEBUG_PIN_SET(1) ;
sm_dma_start();
//DEBUG_PIN_SET(1) ;
while (!sm_dma.state())
//DEBUG_PIN_SET(1) ;
;// execute dma master cycles
// a dma cycle into a device register may trigger an interrupt
// do not delete that condition
if (mailbox.arm2pru_req == arm2pru_req_cached)
mailbox.arm2pru_req = ARM2PRU_NONE; // clear request
break;
case ARM2PRU_INTR:
// start one INTR cycle. May be raised in midst of slave cycle
// by ARM, if access to "active" register triggers INTR.
// no multiple levels simultaneously allowed, not parallel with DMA !
sm_arb_start(mailbox.intr.priority_bit);
// wait while INTR is accepted. This may take long time,
// if system is at high processor priority (PSW register)
while (!sm_arb.state()) {
// sm_slave is most time critical, as it must keep track with MSYN/SSYN bus traffic.
// so give it more cpu cycles
while (!sm_slave.state())
;
}
// now SACK held and BBSY set, slave state machine ended, since BBSY found inactive
sm_intr_start();
while (!sm_intr.state())
; // execute intr cycle as bus master
mailbox.arm2pru_req = ARM2PRU_NONE; // clear request
break;
case ARM2PRU_INITPULSE: // generate a pulse on UNIBUS INIT
// only busmaster may assert INIT. violated here!
sm_slave_start();
sm_init_start();
while (!sm_slave.state() || !sm_init.state())
;
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_POWERCYCLE: // do ACLO/DCLO power cycle
// Runs for 4* POWERCYCLE_DELAY_MS millsecs, approx 1 sec.
// perform slave states in parallel, so emulated memory
// is existent for power fail trap and reboot
sm_slave_start();
sm_powercycle_start();
while (!sm_slave.state() || !sm_powercycle.state())
;
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
default: // ignore all other requestes while executing emulation
;
} // switch
} // while (true)
// never reached
}