1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-01-11 23:52:51 +00:00

PRU statemachines easier to control from main thread

This commit is contained in:
Joerg Hoppe 2019-07-02 07:09:01 +02:00
parent e23b2cf4d3
commit 04869fb46f
20 changed files with 264 additions and 254 deletions

View File

@ -46,7 +46,8 @@ CFLAGS_OPTIMIZER=--opt_level=3 --opt_for_speed=5 --auto_inline --c_src_interli
#CFLAGS_OPTIMIZER=--opt_level=3 --auto_inline --c_src_interlist --optimizer_interlist --gen_opt_info=2
#Common compiler and linker flags (Defined in 'PRU Optimizing C/C++ Compiler User's Guide)
CFLAGS=-v3 $(CFLAGS_OPTIMIZER) \
--display_error_number --endian=little --hardware_mac=on --obj_directory=$(OBJ_DIR) --pp_directory=$(OBJ_DIR) -ppd -ppa
--display_error_number --emit_warnings_as_errors --verbose_diagnostics \
--endian=little --hardware_mac=on --obj_directory=$(OBJ_DIR) --pp_directory=$(OBJ_DIR) -ppd -ppa
#Linker flags (Defined in 'PRU Optimizing C/C++ Compiler User's Guide)
LFLAGS=--reread_libs --warn_sections --stack_size=$(STACK_SIZE) --heap_size=$(HEAP_SIZE)

View File

@ -56,6 +56,11 @@
#include "pru1_statemachine_init.h"
#include "pru1_statemachine_powercycle.h"
// supress warnigns about using void * as fucntion pinters
// sm_slave_state = (statemachine_state_func)&sm_slave_start;
// while (sm_slave_state = sm_slave_state()) << usage
#pragma diag_push
#pragma diag_remark=515
void main(void) {
@ -174,20 +179,22 @@ void main(void) {
buslatches_powercycle();
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
case ARM2PRU_DMA_ARB_NONE:
sm_dma_start(); // without NPR/NPG arbitration
case ARM2PRU_DMA_ARB_NONE: {
// without NPR/NPG arbitration
statemachine_state_func sm_dma_state = (statemachine_state_func)&sm_dma_start;
// simply call current state function, until stopped
// parallel the BUS-slave statemachine is triggered
// by master logic.
while (!sm_dma.state())
while (sm_dma_state = 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:
case ARM2PRU_DDR_SLAVE_MEMORY:
// respond to UNIBUS cycles as slave and
// access DDR as UNIBUS memory.
@ -197,9 +204,9 @@ void main(void) {
// 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();
statemachine_state_func sm_slave_state = (statemachine_state_func)&sm_slave_start;
// do all states of an access, start when MSYN found.
while (!sm_slave.state())
while (sm_slave_state = sm_slave_state())
;
}
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
@ -207,4 +214,5 @@ void main(void) {
} // switch
} // while
}
#pragma diag_pop

View File

@ -62,7 +62,63 @@
#include "pru1_statemachine_init.h"
#include "pru1_statemachine_powercycle.h"
#ifdef FUNCPTRTEST
////// TEST
// need a function returning a pointer to type of its own,
// with "statemachine_state_func" as forward
// typedef statemachine_state_func * (*statemachine_state_func)(void);
// Not possible?! So retirn void * and cast to void *(func(void) on use
typedef void * (*sm_state_func)(void);
sm_state_func sm_2(void); // forward
sm_state_func sm_1(void) {
//printf("1\n");
return (sm_state_func) &sm_2;
}
statemachine_state_func sm_2(void) {
//printf("2\n");
return NULL;
}
int xmain() {
//printf("Hello world ... from " __DATE__ " " __TIME__ "!\n");
//printf("My sizeof(long) is %u.\n", (unsigned) sizeof(long));
// excute 2 states indicectly
sm_state_func smfunc = (sm_state_func) &sm_1;
while ((smfunc = smfunc()))
;
}
#endif
// supress warnigns about using void * as fucntion pinters
// sm_slave_state = (statemachine_state_func)&sm_slave_start;
// while (sm_slave_state = sm_slave_state()) << usage
#pragma diag_push
#pragma diag_remark=515
void test(){
while(1) {
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
}
}
void main(void) {
// state function pointer for different state machines
statemachine_state_func sm_slave_state ;
statemachine_state_func sm_arb_state ;
statemachine_state_func sm_dma_state ;
statemachine_state_func sm_intr_state ;
statemachine_state_func sm_init_state ;
statemachine_state_func sm_powercycle_state ;
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
@ -96,15 +152,15 @@ void main(void) {
// 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())
sm_slave_state = (statemachine_state_func)&sm_slave_start;
while (sm_slave_state = sm_slave_state())
; // execute complete slave cycle, then check NPR/INTR
// update state of init lines
@ -129,9 +185,10 @@ void main(void) {
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())
sm_dma_state = (statemachine_state_func)&sm_dma_start;
while (sm_dma_state = 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)
@ -140,22 +197,24 @@ void main(void) {
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_arb_state = (statemachine_state_func)sm_arb_start(ARBITRATION_PRIORITY_BIT_NP);
while (sm_arb_state && (sm_arb_state = 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())
sm_slave_state = (statemachine_state_func)&sm_slave_start;
while (sm_slave_state = 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())
sm_dma_state = (statemachine_state_func)&sm_dma_start;
while (sm_dma_state = 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)
@ -165,37 +224,49 @@ void main(void) {
// 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);
sm_arb_state = (statemachine_state_func)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()) {
while (sm_arb_state && (sm_arb_state = 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())
sm_slave_state = (statemachine_state_func)&sm_slave_start;
while (sm_slave_state = sm_slave_state())
;
}
// now SACK held and BBSY set, slave state machine ended, since BBSY found inactive
sm_intr_start();
while (!sm_intr.state())
sm_intr_state = (statemachine_state_func)&sm_intr_start;
while (sm_intr_state = 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())
;
// while INIT cycle is running, do slave cycles
sm_init_state = (statemachine_state_func)&sm_init_start;
while(sm_init_state=sm_init_state()) {
if (sm_slave_state)
sm_slave_state = sm_slave_state() ;
else // restart
sm_slave_state = (statemachine_state_func)&sm_slave_start;
}
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())
;
// while power cycle is running, do slave cycles
sm_powercycle_state = (statemachine_state_func)&sm_powercycle_start;
while(sm_powercycle_state=sm_powercycle_state()) {
if (sm_slave_state)
sm_slave_state = sm_slave_state() ;
else // restart
sm_slave_state = (statemachine_state_func)&sm_slave_start;
}
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break;
@ -206,4 +277,5 @@ void main(void) {
// never reached
}
#pragma diag_pop

View File

@ -21,6 +21,7 @@
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 the Priority Arbitration protocol
@ -71,6 +72,7 @@
#define _PRU1_STATEMACHINE_ARBITRATION_C_
#include <stdlib.h>
#include <stdint.h>
#include "pru1_utils.h"
@ -83,61 +85,62 @@
statemachine_arbitration_t sm_arb;
// forwards ;
static uint8_t sm_arb_state_1(void);
static uint8_t sm_arb_state_2(void);
static uint8_t sm_arb_state_3(void);
static uint8_t sm_arb_state_4(void);
static statemachine_state_func sm_arb_state_1(void);
static statemachine_state_func sm_arb_state_2(void);
static statemachine_state_func sm_arb_state_3(void);
/********** NPR/NPG/SACK arbitrations **************/
void sm_arb_start(uint8_t priority_bit) {
statemachine_state_func sm_arb_start(uint8_t priority_bit) {
sm_arb.priority_bit = priority_bit; // single priority bit for this arbitration process
sm_arb.state = &sm_arb_state_1;
return (statemachine_state_func)&sm_arb_state_1;
}
// idle. call _start()
// execute in parallel with slave!
// pass BGIN[4-7],NPGIN to next device , if DMA engine idle
uint8_t sm_arb_state_idle() {
statemachine_state_func sm_arb_state_idle() {
uint8_t tmpval;
tmpval = buslatches_getbyte(0);
// forward all 5 GRANT IN inverted to GRANT OUT
buslatches_setbits(0, ARBITRATION_PRIORITY_MASK, ~tmpval)
;
return 1;
return (statemachine_state_func)&sm_arb_state_idle;
}
// wait for GRANT idle
// Assert REQUEST, wait for GRANT, assert SACK, wait for NPG==0, set SACK=0 ,
// execute in parallel with slave!
static uint8_t sm_arb_state_1() {
static statemachine_state_func sm_arb_state_1() {
uint8_t tmpval;
tmpval = buslatches_getbyte(0);
// forward all lines, until idle
buslatches_setbits(0, ARBITRATION_PRIORITY_MASK, ~tmpval) ;
// wait for GRANT idle, other cycle in progress?
if (tmpval & sm_arb.priority_bit)
return 0;
return (statemachine_state_func)&sm_arb_state_1; // wait
// no need to wait for SACK: arbitrator responds only with a GRANT IN
buslatches_setbits(1, sm_arb.priority_bit, sm_arb.priority_bit); // REQUEST = latch1
sm_arb.state = &sm_arb_state_2; // wait for GRANT IN active
return 0;
return (statemachine_state_func)&sm_arb_state_2; // wait for GRANT IN active
}
// wait for BG*,NPG or INIT
// execute in parallel with slave!
static uint8_t sm_arb_state_2() {
static statemachine_state_func sm_arb_state_2() {
uint8_t tmpval;
tmpval = buslatches_getbyte(0);
if (buslatches_getbyte(7) & BIT(3)) { // INIT stops transaction: latch[7], bit 3
// cleanup: clear all REQUESTS and SACK
// cleanup: clear all 5 BR/NPR and SACK
buslatches_setbits(1, ARBITRATION_PRIORITY_MASK| BIT(5), 0);
// forward all 5 GRANT IN inverted to GRANT OUT
buslatches_setbits(0, ARBITRATION_PRIORITY_MASK, ~tmpval) ;
// Todo: signal INIT to ARM!
sm_arb.state = &sm_arb_state_idle;
return 0 ;
return NULL ;
}
tmpval = buslatches_getbyte(0);
// forward all other BG lines
// preceding arbitration must see BG removed by master on SACK
@ -147,42 +150,36 @@ static uint8_t sm_arb_state_2() {
buslatches_setbits(0, ARBITRATION_PRIORITY_MASK, ~tmpval); // forward all without our GRANT
// set SACK
buslatches_setbits(1, BIT(5), BIT(5));
sm_arb.state = &sm_arb_state_3;
} else
return (statemachine_state_func)&sm_arb_state_3;
} else {
buslatches_setbits(0, ARBITRATION_PRIORITY_MASK, ~tmpval); // forward all
return 0;
return (statemachine_state_func)&sm_arb_state_2 ; // wait
}
}
// GRANT received. wait for previous bus master to complete transaction,
// then become bus master
// Forwarding of other GRANTs not necessary ... arbitrator granted us.
static uint8_t sm_arb_state_3() {
static statemachine_state_func sm_arb_state_3() {
if (buslatches_getbyte(7) & BIT(3)) { // INIT stops transaction: latch[7], bit 3
// cleanup: clear all REQUESTS and SACk
buslatches_setbits(1, ARBITRATION_PRIORITY_MASK| BIT(5), 0);
// Todo: signal INIT to ARM!
sm_arb.state = &sm_arb_state_idle;
return 1;
return NULL;
}
if (buslatches_getbyte(0) & sm_arb.priority_bit) // wait for GRANT IN to be deasserted
return 0;
return (statemachine_state_func)&sm_arb_state_3; // wait
// wait until old bus master cleared BBSY
if (buslatches_getbyte(1) & BIT(6))
return 0;
return (statemachine_state_func)&sm_arb_state_3; // wait
// wait until SSYN deasserted by old slave
if (buslatches_getbyte(4) & BIT(5))
return 0;
return (statemachine_state_func)&sm_arb_state_3; // wait
// now become new bus master: Set BBSY, Clear REQUEST
// BBSY= bit 6
buslatches_setbits(1, sm_arb.priority_bit | BIT(6), BIT(6));
// SACK is cleared later in "data transfer" statemachines (DMA or INTR)
sm_arb.state = &sm_arb_state_4; // bus mastership acquired
return 1;
}
// bus mastership acquired. DMA data transfer must terminate this state
static uint8_t sm_arb_state_4() {
return 1;
return NULL; // bus mastership acquired
}
#ifdef USED

View File

@ -20,18 +20,15 @@
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_ARBITRATION_H_
#define _PRU1_STATEMACHINE_ARBITRATION_H_
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_arb_state_func_ptr)(void);
#include "pru1_utils.h" // statemachine_state_func
typedef struct {
sm_arb_state_func_ptr state; // current state as ptr to "state function"
uint8_t priority_bit ; // single priority bit for this arbitration process
// one of ARBITRATION_PRIORITY_*
} statemachine_arbitration_t;
@ -41,7 +38,7 @@ typedef struct {
extern statemachine_arbitration_t sm_arb;
#endif
void sm_arb_start(uint8_t priority_bit);
uint8_t sm_arb_state_idle(void) ;
statemachine_state_func sm_arb_start(uint8_t priority_bit);
statemachine_state_func sm_arb_state_idle(void) ;
#endif

View File

@ -21,6 +21,7 @@
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
@ -51,6 +52,7 @@
*/
#define _PRU1_STATEMACHINE_DMA_C_
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
@ -72,31 +74,31 @@ statemachine_dma_t sm_dma;
/********** Master DATA cycles **************/
// forwards ;
static uint8_t sm_dma_state_1(void);
static uint8_t sm_dma_state_11(void);
static uint8_t sm_dma_state_21(void);
static uint8_t sm_dma_state_99(void);
static statemachine_state_func sm_dma_state_1(void);
static statemachine_state_func sm_dma_state_11(void);
static statemachine_state_func sm_dma_state_21(void);
static statemachine_state_func sm_dma_state_99(void);
// dma mailbox setup with
// startaddr, wordcount, cycle, words[] ?
// "cycle" must be UNIBUS_CONTROL_DATI or UNIBUS_CONTROL_DATO
// BBSY already set, SACK held asserted
void sm_dma_start() {
statemachine_state_func sm_dma_start() {
// assert BBSY: latch[1], bit 6
// buslatches_setbits(1, BIT(6), BIT(6));
mailbox.dma.cur_addr = mailbox.dma.startaddr;
sm_dma.dataptr = (uint16_t *) mailbox.dma.words; // point to start of data buffer
sm_dma.state = &sm_dma_state_1;
sm_dma.cur_wordsleft = mailbox.dma.wordcount;
mailbox.dma.cur_status = DMA_STATE_RUNNING;
// next call to sm_dma.state() starts state machine
return (statemachine_state_func)&sm_dma_state_1 ;
}
// place address and control bits onto bus, also data for DATO
// If slave address is internal (= implemented by UniBone),
// fast UNIBUS slave protocol is generated on the bus.
static uint8_t sm_dma_state_1() {
static statemachine_state_func sm_dma_state_1() {
uint32_t tmpval;
uint32_t addr = mailbox.dma.cur_addr; // non-volatile snapshot
uint16_t data;
@ -107,7 +109,7 @@ static uint8_t sm_dma_state_1() {
// should test SACK and BBSY !
if (mailbox.dma.cur_status != DMA_STATE_RUNNING || mailbox.dma.wordcount == 0)
return 1; // still stopped
return NULL; // still stopped
if (sm_dma.cur_wordsleft == 1) {
@ -178,12 +180,12 @@ static uint8_t sm_dma_state_1() {
while (mailbox.events.eventmask) ;
buslatches_setbits(4, BIT(5), 0); // slave deassert SSYN
sm_dma.state = &sm_dma_state_99; // next word
return (statemachine_state_func)&sm_dma_state_99; // next word
} else {
// DATO to external slave
// wait for a slave SSYN
TIMEOUT_SET(NANOSECS(1000*UNIBUS_TIMEOUT_PERIOD_US));
sm_dma.state = &sm_dma_state_21; // wait SSYN DATAO
return (statemachine_state_func)&sm_dma_state_21; // wait SSYN DATAO
}
} else {
// DATI or DATIP
@ -224,25 +226,23 @@ static uint8_t sm_dma_state_1() {
while (mailbox.events.eventmask) ;
buslatches_setbits(4, BIT(5), 0); // slave deassert SSYN
sm_dma.state = &sm_dma_state_99; // next word
return (statemachine_state_func)&sm_dma_state_99; // next word
} else {
// DATI to external slave
// wait for a slave SSYN
TIMEOUT_SET(NANOSECS(1000*UNIBUS_TIMEOUT_PERIOD_US));
sm_dma.state = &sm_dma_state_11; // wait SSYN DATI
return (statemachine_state_func)&sm_dma_state_11; // wait SSYN DATI
}
}
return 0; // still running
}
// DATI to external slave: MSYN set, wait for SSYN or timeout
static uint8_t sm_dma_state_11() {
static statemachine_state_func sm_dma_state_11() {
uint16_t tmpval;
sm_dma.state_timeout = TIMEOUT_REACHED;
// SSYN = latch[4], bit 5
if (!sm_dma.state_timeout && !(buslatches_getbyte(4) & BIT(5)))
return 0; // no SSYN yet: wait
return (statemachine_state_func)&sm_dma_state_11; // no SSYN yet: wait
// SSYN set by slave (or timeout). read data
__delay_cycles(NANOSECS(75) - 6); // assume 2*3 cycles for buslatches_getbyte
@ -257,16 +257,15 @@ static uint8_t sm_dma_state_11() {
buslatches_setbits(4, BIT(4), 0);
// DATI: remove address,control, MSYN,SSYN from bus, 75ns after MSYN inactive
__delay_cycles(NANOSECS(75) - 8); // assume 8 cycles for state change
sm_dma.state = &sm_dma_state_99;
return 0; // still running
return (statemachine_state_func)&sm_dma_state_99;
}
// DATO to external slave: wait for SSYN or timeout
static uint8_t sm_dma_state_21() {
static statemachine_state_func sm_dma_state_21() {
sm_dma.state_timeout = TIMEOUT_REACHED; // SSYN timeout?
// SSYN = latch[4], bit 5
if (!sm_dma.state_timeout && !(buslatches_getbyte(4) & BIT(5)))
return 0; // no SSYN yet: wait
return (statemachine_state_func)&sm_dma_state_21; // no SSYN yet: wait
// SSYN set by slave (or timeout): negate MSYN, remove DATA from bus
buslatches_setbits(4, BIT(4), 0); // deassert MSYN
@ -274,12 +273,11 @@ static uint8_t sm_dma_state_21() {
buslatches_setbyte(6, 0);
// DATO: remove address,control, MSYN,SSYN from bus, 75ns after MSYN inactive
__delay_cycles(NANOSECS(75) - 8); // assume 8 cycles for state change
sm_dma.state = &sm_dma_state_99;
return 0; // still running
return (statemachine_state_func)&sm_dma_state_99;
}
// word is transfered, or timeout.
static uint8_t sm_dma_state_99() {
static statemachine_state_func sm_dma_state_99() {
uint8_t final_dma_state;
// from state_12, state_21
@ -302,14 +300,12 @@ static uint8_t sm_dma_state_99() {
buslatches_setbits(1, BIT(5), 0); // deassert SACK = latch[1], bit 5
} else
final_dma_state = DMA_STATE_RUNNING; // more words: continue
}
sm_dma.state = &sm_dma_state_1; // in any case, reloop
if (final_dma_state == DMA_STATE_RUNNING) {
// dataptr and wordsleft already incremented
// dataptr and words_left already incremented
mailbox.dma.cur_addr += 2; // signal progress to ARM
return 0;
return (statemachine_state_func)&sm_dma_state_1; // reloop
} else {
// remove addr and control from bus
buslatches_setbyte(2, 0);
@ -317,10 +313,9 @@ static uint8_t sm_dma_state_99() {
buslatches_setbits(4, 0x3f, 0);
// remove BBSY: latch[1], bit 6
buslatches_setbits(1, BIT(6), 0);
// terminate arbitration state
sm_arb.state = &sm_arb_state_idle;
// SACK already de-asserted at wordcount==1
mailbox.dma.cur_status = final_dma_state; // signal to ARM
return 1; // now stopped
return NULL; // now stopped
}
}

View File

@ -21,6 +21,7 @@
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
*/
@ -28,14 +29,11 @@
#define _PRU1_STATEMACHINE_DMA_H_
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_dma_state_func_ptr)(void);
#include "pru1_utils.h" // statemachine_state_func
// Transfers a block of worst as data cycles
typedef struct {
sm_dma_state_func_ptr state; // current state as ptr to "state fucntion"
uint8_t state_timeout; // timeout occured?
uint16_t *dataptr ; // points to current word in mailbox.words[] ;
uint16_t cur_wordsleft; // # of words left to transfer
@ -48,6 +46,6 @@ extern statemachine_dma_t sm_dma;
#endif
void sm_dma_start(void) ;
statemachine_state_func sm_dma_start(void) ;
#endif

View File

@ -21,6 +21,7 @@
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
@ -29,6 +30,7 @@
#define _PRU1_STATEMACHINE_INIT_C_
#include <stdlib.h>
#include <stdint.h>
#include "mailbox.h"
@ -59,33 +61,25 @@ void do_event_initializationsignals() {
statemachine_init_t sm_init;
// forwards
uint8_t sm_init_state_idle(void);
static uint8_t sm_init_state_1(void);
static statemachine_state_func sm_init_state_1(void);
// setup
void sm_init_start() {
statemachine_state_func sm_init_start() {
TIMEOUT_SET(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
do_event_initializationsignals() ;
sm_init.state = &sm_init_state_1;
return (statemachine_state_func)&sm_init_state_1;
}
uint8_t sm_init_state_idle() {
return 1; // ready
}
static uint8_t sm_init_state_1() {
static statemachine_state_func sm_init_state_1() {
if (!TIMEOUT_REACHED)
return 0;
return (statemachine_state_func)&sm_init_state_1; // wait
buslatches_setbits(7, BIT(3), 0); // deassert INIT
do_event_initializationsignals() ;
sm_init.state = &sm_init_state_idle;
return 1;
return NULL ; // ready
}

View File

@ -21,6 +21,7 @@
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_
@ -28,24 +29,17 @@
#include <stdint.h>
#include "pru1_utils.h" // statemachine_state_func
#define INITPULSE_DELAY_MS 250 // length of INIT pulse
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_powercycle_init_func_ptr)(void);
typedef struct {
sm_powercycle_init_func_ptr state; // current state as ptr to "state function"
} statemachine_init_t;
#ifndef _PRU1_STATEMACHINE_INIT_C_
extern uint8_t prev_initialization_signals ;
extern statemachine_init_t sm_init;
#endif
void do_event_initializationsignals(void) ;
void sm_init_start();
statemachine_state_func sm_init_start();
#endif

View File

@ -21,6 +21,7 @@
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
State machines to transfer an interrupt vector.
@ -30,6 +31,7 @@
*/
#define _PRU1_STATEMACHINE_INTR_C_
#include <stdlib.h>
#include <stdint.h>
//#include "devices.h"
@ -37,30 +39,23 @@
#include "pru1_buslatches.h"
#include "pru1_utils.h"
#include "pru1_statemachine_arbitration.h"
//#include "pru1_statemachine_arbitration.h"
#include "pru1_statemachine_intr.h"
statemachine_intr_t sm_intr;
// forwards
static uint8_t sm_intr_state_idle(void);
static uint8_t sm_intr_state_1(void);
static uint8_t sm_intr_state_2(void);
static statemachine_state_func sm_intr_state_1(void);
static statemachine_state_func sm_intr_state_2(void);
// BBSY already set, SACK held asserted
void sm_intr_start() {
statemachine_state_func sm_intr_start() {
// BBSY already asserted. : latch[1], bit 6
// buslatches_setbits(1, BIT(6), BIT(6));
sm_intr.state = &sm_intr_state_1;
return (statemachine_state_func)&sm_intr_state_1;
// next call to sm_intr.state() starts state machine
}
static uint8_t sm_intr_state_idle() {
return 1;
}
// place vector onto data, then set INTR
static uint8_t sm_intr_state_1() {
static statemachine_state_func sm_intr_state_1() {
uint16_t vector = mailbox.intr.vector;
buslatches_setbyte(5, vector & 0xff); // DATA[0..7] = latch[5]
@ -75,25 +70,24 @@ static uint8_t sm_intr_state_1() {
buslatches_setbits(1, BIT(5), 0); // SACK = latch[1], bit 5
// wait for processor to accept vector (no timeout?)
sm_intr.state = &sm_intr_state_2;
return 0;
return (statemachine_state_func)&sm_intr_state_2;
}
// wait for SSYN
static uint8_t sm_intr_state_2() {
static statemachine_state_func sm_intr_state_2() {
if (!(buslatches_getbyte(4) & BIT(5)))
return 0;
return (statemachine_state_func)&sm_intr_state_2; // wait
// received SSYN
//remove vector, then remove INTR
// remove vector, then remove INTR
buslatches_setbyte(5, 0); // DATA[0..7] = latch[5]
buslatches_setbyte(6, 0); // DATA[8..15] = latch[6]
buslatches_setbits(7, BIT(0), 0); // INTR = latch 7, bit 0
// deassert BBSY
buslatches_setbits(1, BIT(6), 0);
// SACK already removed
sm_intr.state = &sm_intr_state_idle;
return 1;
return NULL; // ready
// master still drives SSYN
}

View File

@ -21,23 +21,17 @@
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_INTR_H_
#define _PRU1_STATEMACHINE_INTR_H_
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_intr_state_func_ptr)(void);
#include "pru1_utils.h" // statemachine_state_func
// Transfers a block of worst as data cycles
typedef struct {
sm_intr_state_func_ptr state; // current state as ptr to "state fucntion"
} statemachine_intr_t;
#ifndef _PRU1_STATEMACHINE_INTR_C_
extern statemachine_dma_t sm_intr;
#endif
void sm_intr_start(void);
statemachine_state_func sm_intr_start(void);
#endif

View File

@ -21,6 +21,7 @@
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
@ -41,9 +42,9 @@
#define _PRU1_STATEMACHINE_POWERCYCLE_C_
#include <stdlib.h>
#include <stdint.h>
#include "mailbox.h"
#include "pru1_utils.h"
@ -52,70 +53,60 @@
#include "pru1_statemachine_powercycle.h"
statemachine_powercycle_t sm_powercycle;
// forwards ; /
uint8_t sm_powercycle_state_idle(void);
static uint8_t sm_powercycle_state_1(void);
static uint8_t sm_powercycle_state_2(void);
static uint8_t sm_powercycle_state_3(void);
static uint8_t sm_powercycle_state_4(void);
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
void sm_powercycle_start() {
sm_powercycle.state = &sm_powercycle_state_1;
statemachine_state_func sm_powercycle_start() {
return (statemachine_state_func)&sm_powercycle_state_1;
// next call to sm_slave.state() starts state machine
}
uint8_t sm_powercycle_state_idle() {
return 1; // ready
}
// "Line power shutdown": assert ACLO, then wait
static uint8_t sm_powercycle_state_1() {
static statemachine_state_func sm_powercycle_state_1() {
buslatches_setbits(7, BIT(4), BIT(4)); // ACLO asserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // wait for DC power shutdown
sm_powercycle.state = &sm_powercycle_state_2;
// DEBUG_OUT(0x01) ;
do_event_initializationsignals() ;
// DEBUG_OUT(0x02) ;
return 0;
return (statemachine_state_func)&sm_powercycle_state_2;
}
// "Power supply switched off": assert DCLO, then wait
static uint8_t sm_powercycle_state_2() {
static statemachine_state_func sm_powercycle_state_2() {
if (!TIMEOUT_REACHED)
return 0;
return (statemachine_state_func)&sm_powercycle_state_2; // wait
buslatches_setbits(7, BIT(5), BIT(5)); // DCLO asserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // system powered off
sm_powercycle.state = &sm_powercycle_state_3;
// DEBUG_OUT(0x03) ;
do_event_initializationsignals() ;
// DEBUG_OUT(0x04) ;
return 0;
return (statemachine_state_func)&sm_powercycle_state_3;
}
// "Line power back again": deassert ACLO, then wait
static uint8_t sm_powercycle_state_3() {
static statemachine_state_func sm_powercycle_state_3() {
if (!TIMEOUT_REACHED)
return 0;
return (statemachine_state_func)&sm_powercycle_state_3; // wait
buslatches_setbits(7, BIT(4), 0); // ACLO deasserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // "power supply stabilizing"
sm_powercycle.state = &sm_powercycle_state_4;
do_event_initializationsignals() ;
return 0;
return (statemachine_state_func)&sm_powercycle_state_4;
}
// "Logic power stabilized": deassert DCLO, ready
static uint8_t sm_powercycle_state_4() {
static statemachine_state_func sm_powercycle_state_4() {
if (!TIMEOUT_REACHED)
return 0;
return (statemachine_state_func)&sm_powercycle_state_4;
buslatches_setbits(7, BIT(5), 0); // DCLO deasserted
sm_powercycle.state = &sm_powercycle_state_idle;
do_event_initializationsignals() ;
return 1;
return NULL;
}

View File

@ -21,26 +21,18 @@
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
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_powercycle_state_func_ptr)(void);
typedef struct {
sm_powercycle_state_func_ptr state; // current state as ptr to "state function"
} statemachine_powercycle_t;
#ifndef _PRU1_STATEMACHINE_POWERCYCLE_C_
extern statemachine_powercycle_t sm_powercycle;
#endif
void sm_powercycle_start();
statemachine_state_func sm_powercycle_start();
#endif

View File

@ -21,6 +21,7 @@
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 slave DATO* or DATI* cycles.
@ -35,6 +36,7 @@
#define _PRU1_STATEMACHINE_SLAVE_C_
#include <stdlib.h>
#include <stdint.h>
#include "pru1_utils.h"
@ -46,22 +48,15 @@
#include "pru1_buslatches.h"
#include "pru1_statemachine_slave.h"
statemachine_slave_t sm_slave;
// forwards ;
static uint8_t sm_slave_state_1(void);
static uint8_t sm_slave_state_10(void);
static uint8_t sm_slave_state_20(void);
static uint8_t sm_slave_state_99(void);
//statemachine_state_func sm_slave_start(void);
static statemachine_state_func sm_slave_state_10(void);
static statemachine_state_func sm_slave_state_20(void);
static statemachine_state_func sm_slave_state_99(void);
// setup with
void sm_slave_start() {
sm_slave.state = &sm_slave_state_1;
// next call to sm_slave.state() starts state machine
}
// check for MSYN active
static uint8_t sm_slave_state_1() {
statemachine_state_func sm_slave_start() {
uint8_t latch2val, latch3val, latch4val;
// uint8_t iopage;
uint32_t addr;
@ -76,10 +71,10 @@ static uint8_t sm_slave_state_1() {
// MSYN active ?
if (!(latch4val & BIT(4)))
return 1; // still idle
return NULL; // still idle
if (latch4val & BIT(5))
// SSYN active: cycle answered by other bus slave
return 1; // still idle
return NULL; // still idle
// checking against SSYN guarantees address if valid if fetched now.
// However, another Bus slave can SSYN immediately
@ -118,12 +113,11 @@ static uint8_t sm_slave_state_1() {
//DEBUG_PIN_PULSE ; // trigger scope/LA. auto cleared on next reg_sel
// set SSYN = latch[4], bit 5
buslatches_setbits(4, BIT(5), BIT(5));
sm_slave.state = &sm_slave_state_20;
return (statemachine_state_func)&sm_slave_state_20;
// perhaps PRU2ARM_INTERRUPT now active
} else
// no address match: wait for MSYN to go inactive
sm_slave.state = &sm_slave_state_99;
break;
return (statemachine_state_func)&sm_slave_state_99;
case UNIBUS_CONTROL_DATO:
// fetch data in any case
// DATA[0..7] = latch[5]
@ -136,12 +130,11 @@ static uint8_t sm_slave_state_1() {
// SSYN = latch[4], bit 5
buslatches_setbits(4, BIT(5), BIT(5));
// wait for MSYN to go inactive, then SSYN inactive
sm_slave.state = &sm_slave_state_10;
return (statemachine_state_func)&sm_slave_state_10;
// perhaps PRU2ARM_INTERRUPT now active
} else
// no address match: wait for MSYN to go inactive
sm_slave.state = &sm_slave_state_99;
break;
return (statemachine_state_func)&sm_slave_state_99;
case UNIBUS_CONTROL_DATOB:
// A00 = 1, odd address: get upper byte
// A00 = 0: even address, get lower byte
@ -157,42 +150,40 @@ static uint8_t sm_slave_state_1() {
// SSYN = latch[4], bit 5
buslatches_setbits(4, BIT(5), BIT(5));
// wait for MSYN to go inactive, then SSYN inactive
sm_slave.state = &sm_slave_state_10;
return (statemachine_state_func)&sm_slave_state_10;
// perhaps PRU2ARM_INTERRUPT now active
} else
// no address match: wait for MSYN to go inactive
sm_slave.state = &sm_slave_state_99;
break;
return (statemachine_state_func)&sm_slave_state_99;
}
return 0; // busy
return NULL ; // not reached
}
// End DATO: wait for MSYN to go inactive, then SSYN inactive
// also wait for EVENT ACK
static uint8_t sm_slave_state_10() {
static statemachine_state_func sm_slave_state_10() {
// MSYN = latch[4], bit 4
if (buslatches_getbyte(4) & BIT(4))
return 0; // MSYN still active
return (statemachine_state_func)&sm_slave_state_10; // wait, MSYN still active
if (mailbox.events.eventmask)
return 0; // long SSYN delay until ARM acknowledges all events
return (statemachine_state_func)&sm_slave_state_10; // wait, long SSYN delay until ARM acknowledges all events
// if ARM was triggered by event and changed the device state,
// now an Interrupt arbitration may be pending!
// clear SSYN = latch[4], bit 5
buslatches_setbits(4, BIT(5), 0);
sm_slave.state = &sm_slave_state_1;
return 1; // ready }
return NULL; // ready
}
// End DATI: wait for MSYN to go inactive, then SSYN and DATA inactive
// also wait for EVENT ACK
static uint8_t sm_slave_state_20() {
static statemachine_state_func sm_slave_state_20() {
// MSYN = latch[4], bit 4
if (buslatches_getbyte(4) & BIT(4))
return 0; // MSYN still active
return (statemachine_state_func)&sm_slave_state_20; // wait, MSYN still active
if (mailbox.events.eventmask)
return 0; // long SSYN delay until ARM acknowledges event
return (statemachine_state_func)&sm_slave_state_20; // wait, long SSYN delay until ARM acknowledges event
// if ARM was triggered by event and changed the device state,
// now an Interrupt arbitration may be pending!
@ -203,16 +194,14 @@ static uint8_t sm_slave_state_20() {
buslatches_setbyte(6, 0);
// clear SSYN = latch[4], bit 5
buslatches_setbits(4, BIT(5), 0);
sm_slave.state = &sm_slave_state_1;
return 1; // ready }
return NULL; // ready
}
// end of inactive cycle: wait for MSYN to go inactive
static uint8_t sm_slave_state_99() {
static statemachine_state_func sm_slave_state_99() {
// MSYN = latch[4], bit 4
if (buslatches_getbyte(4) & BIT(4))
return 0; // MSYN still active
return (statemachine_state_func)&sm_slave_state_99; // wait, MSYN still active
sm_slave.state = &sm_slave_state_1;
return 1; // ready }
return NULL; // ready
}

View File

@ -21,27 +21,15 @@
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_SLAVE_H_
#define _PRU1_STATEMACHINE_SLAVE_H_
#include <stdint.h>
#include "pru1_utils.h" // statemachine_state_func
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_slave_state_func_ptr)(void);
typedef struct {
sm_slave_state_func_ptr state; // current state as ptr to "state function"
// uint32_t addr; // adress fetched from bus on MSYN
// uint8_t control; // C1,C0 fetched from bus on MSYN
// uint16_t data; // data fetched from bus on MSYN/ to be written to BUS on SSYN
} statemachine_slave_t;
#ifndef _PRU1_STATEMACHINE_SLAVE_C_
extern statemachine_slave_t sm_slave;
#endif
void sm_slave_start();
statemachine_state_func sm_slave_start(void);
#endif

View File

@ -37,6 +37,12 @@ volatile register uint32_t __R30;
volatile register uint32_t __R31;
// execution of a state. return : next state; or NULL if statemachine stopped
// return type is void *, but should be statemachine_state_func_ptr recursively
// typedef statemachine_state_func * (*statemachine_state_func)(void);
// Not possible?! So return void * and cast to void *(func(void) on use
typedef void * (*statemachine_state_func)(void);
#define MILLION 1000000L

View File

@ -176,7 +176,7 @@ void cpu_c::on_init_changed(void) {
// write all registers to "reset-values"
if (init_asserted) {
reset_unibus_registers();
INFO("demo_io_c::on_init()");
INFO("cpu::on_init()");
}
}

View File

@ -51,7 +51,7 @@ public:
parameter_bool_c runmode = parameter_bool_c(this, "run", "r",/*readonly*/
false, "1 = CPU running, 0 = halt");
parameter_bool_c init = parameter_bool_c(this, "init", "i",/*readonly*/
false, "1 = CPU initalizing");
false, "1 = CPU initializing");
struct Bus bus; // UNIBU Sinterface of CPU
struct KA11 ka11; // Angelos CPU state

View File

@ -111,7 +111,7 @@ public:
// working position
blockaddr_c cur_blockaddr;
// initalize drive
// initialize drive
virtual void init(unsigned unitnr) = 0;
// read access
virtual void readtrack(unsigned unitnr, uint8_t *data) = 0;

View File

@ -39,7 +39,7 @@ public:
// implement abstracts
// initalize drive
// initialize drive
virtual void init(unsigned unitnr);
// read access
virtual void readtrack(unsigned unitnr, uint8_t *data);