1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-04-25 11:41:54 +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 #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) #Common compiler and linker flags (Defined in 'PRU Optimizing C/C++ Compiler User's Guide)
CFLAGS=-v3 $(CFLAGS_OPTIMIZER) \ 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) #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) 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_init.h"
#include "pru1_statemachine_powercycle.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) { void main(void) {
@@ -174,20 +179,22 @@ void main(void) {
buslatches_powercycle(); buslatches_powercycle();
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break; break;
case ARM2PRU_DMA_ARB_NONE: case ARM2PRU_DMA_ARB_NONE: {
sm_dma_start(); // without NPR/NPG arbitration // without NPR/NPG arbitration
statemachine_state_func sm_dma_state = (statemachine_state_func)&sm_dma_start;
// simply call current state function, until stopped // simply call current state function, until stopped
// parallel the BUS-slave statemachine is triggered // parallel the BUS-slave statemachine is triggered
// by master logic. // by master logic.
while (!sm_dma.state()) while (sm_dma_state = sm_dma_state())
; ;
}
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break; break;
case ARM2PRU_DDR_FILL_PATTERN: case ARM2PRU_DDR_FILL_PATTERN:
ddrmem_fill_pattern(); ddrmem_fill_pattern();
mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break; break;
case ARM2PRU_DDR_SLAVE_MEMORY: case ARM2PRU_DDR_SLAVE_MEMORY:
// respond to UNIBUS cycles as slave and // respond to UNIBUS cycles as slave and
// access DDR as UNIBUS memory. // access DDR as UNIBUS memory.
@@ -197,9 +204,9 @@ void main(void) {
// do UNIBUS slave cycles, until ARM abort this by // do UNIBUS slave cycles, until ARM abort this by
// writing into mailbox.arm2pru_req // writing into mailbox.arm2pru_req
while (mailbox.arm2pru_req == ARM2PRU_DDR_SLAVE_MEMORY) { 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. // 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 mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
@@ -207,4 +214,5 @@ void main(void) {
} // switch } // switch
} // while } // while
} }
#pragma diag_pop

View File

@@ -62,7 +62,63 @@
#include "pru1_statemachine_init.h" #include "pru1_statemachine_init.h"
#include "pru1_statemachine_powercycle.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) { 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 */ /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
@@ -96,15 +152,15 @@ void main(void) {
// buslatches_pulse_debug ; // buslatches_pulse_debug ;
// base operation: accept and execute slave cycles // base operation: accept and execute slave cycles
sm_slave_start();
while (true) { while (true) {
uint32_t arm2pru_req_cached; uint32_t arm2pru_req_cached;
// do all states of an access, start when MSYN found. // do all states of an access, start when MSYN found.
// slave cycles may trigger events to ARM, which changes "active" registers // slave cycles may trigger events to ARM, which changes "active" registers
// and issues interrupts // 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 ; // execute complete slave cycle, then check NPR/INTR
// update state of init lines // update state of init lines
@@ -129,9 +185,10 @@ void main(void) {
break; break;
case ARM2PRU_DMA_ARB_NONE: // ignore SACK condition case ARM2PRU_DMA_ARB_NONE: // ignore SACK condition
case ARM2PRU_DMA_ARB_MASTER: // also without arbitration, TODO! case ARM2PRU_DMA_ARB_MASTER: // also without arbitration, TODO!
sm_dma_start(); sm_dma_state = (statemachine_state_func)&sm_dma_start;
while (!sm_dma.state()) while (sm_dma_state = sm_dma_state())
; ;
// a dma cycle into a device register may trigger an interrupt // a dma cycle into a device register may trigger an interrupt
// do not delete that condition // do not delete that condition
if (mailbox.arm2pru_req == arm2pru_req_cached) if (mailbox.arm2pru_req == arm2pru_req_cached)
@@ -140,22 +197,24 @@ void main(void) {
case ARM2PRU_DMA_ARB_CLIENT: case ARM2PRU_DMA_ARB_CLIENT:
// start DMA cycle // start DMA cycle
// can not run parallel with INTR levels // 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. // sm_slave is most time critical, as it must keep track with MSYN/SSYN bus traffic.
// so give it more cpu cycles // 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 // now SACK held and BBSY set, slave state machine ended, since BBSY found inactive
// debug pin reset by bus access // debug pin reset by bus access
//DEBUG_PIN_SET(1) ; //DEBUG_PIN_SET(1) ;
sm_dma_start(); sm_dma_state = (statemachine_state_func)&sm_dma_start;
//DEBUG_PIN_SET(1) ; while (sm_dma_state = sm_dma_state())
while (!sm_dma.state())
//DEBUG_PIN_SET(1) ; //DEBUG_PIN_SET(1) ;
;// execute dma master cycles ;// execute dma master cycles
// a dma cycle into a device register may trigger an interrupt // a dma cycle into a device register may trigger an interrupt
// do not delete that condition // do not delete that condition
if (mailbox.arm2pru_req == arm2pru_req_cached) 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 // start one INTR cycle. May be raised in midst of slave cycle
// by ARM, if access to "active" register triggers INTR. // by ARM, if access to "active" register triggers INTR.
// no multiple levels simultaneously allowed, not parallel with DMA ! // 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, // wait while INTR is accepted. This may take long time,
// if system is at high processor priority (PSW register) // 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. // sm_slave is most time critical, as it must keep track with MSYN/SSYN bus traffic.
// so give it more cpu cycles // 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 // now SACK held and BBSY set, slave state machine ended, since BBSY found inactive
sm_intr_start(); sm_intr_state = (statemachine_state_func)&sm_intr_start;
while (!sm_intr.state()) while (sm_intr_state = sm_intr_state())
; // execute intr cycle as bus master ; // execute intr cycle as bus master
mailbox.arm2pru_req = ARM2PRU_NONE; // clear request mailbox.arm2pru_req = ARM2PRU_NONE; // clear request
break; break;
case ARM2PRU_INITPULSE: // generate a pulse on UNIBUS INIT case ARM2PRU_INITPULSE: // generate a pulse on UNIBUS INIT
// only busmaster may assert INIT. violated here! // only busmaster may assert INIT. violated here!
sm_slave_start();
sm_init_start(); // while INIT cycle is running, do slave cycles
while (!sm_slave.state() || !sm_init.state()) 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 mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break; break;
case ARM2PRU_POWERCYCLE: // do ACLO/DCLO power cycle case ARM2PRU_POWERCYCLE: // do ACLO/DCLO power cycle
// Runs for 4* POWERCYCLE_DELAY_MS millsecs, approx 1 sec. // Runs for 4* POWERCYCLE_DELAY_MS millsecs, approx 1 sec.
// perform slave states in parallel, so emulated memory // perform slave states in parallel, so emulated memory
// is existent for power fail trap and reboot // is existent for power fail trap and reboot
sm_slave_start();
sm_powercycle_start(); // while power cycle is running, do slave cycles
while (!sm_slave.state() || !sm_powercycle.state()) 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 mailbox.arm2pru_req = ARM2PRU_NONE; // ACK: done
break; break;
@@ -206,4 +277,5 @@ void main(void) {
// never reached // never reached
} }
#pragma diag_pop

View File

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

View File

@@ -20,18 +20,15 @@
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 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. 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 12-nov-2018 JH entered beta phase
*/ */
#ifndef _PRU1_STATEMACHINE_ARBITRATION_H_ #ifndef _PRU1_STATEMACHINE_ARBITRATION_H_
#define _PRU1_STATEMACHINE_ARBITRATION_H_ #define _PRU1_STATEMACHINE_ARBITRATION_H_
#include "pru1_utils.h" // statemachine_state_func
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_arb_state_func_ptr)(void);
typedef struct { 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 uint8_t priority_bit ; // single priority bit for this arbitration process
// one of ARBITRATION_PRIORITY_* // one of ARBITRATION_PRIORITY_*
} statemachine_arbitration_t; } statemachine_arbitration_t;
@@ -41,7 +38,7 @@ typedef struct {
extern statemachine_arbitration_t sm_arb; extern statemachine_arbitration_t sm_arb;
#endif #endif
void sm_arb_start(uint8_t priority_bit); statemachine_state_func sm_arb_start(uint8_t priority_bit);
uint8_t sm_arb_state_idle(void) ; statemachine_state_func sm_arb_state_idle(void) ;
#endif #endif

View File

@@ -21,6 +21,7 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 12-nov-2018 JH entered beta phase
@@ -51,6 +52,7 @@
*/ */
#define _PRU1_STATEMACHINE_DMA_C_ #define _PRU1_STATEMACHINE_DMA_C_
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@@ -72,31 +74,31 @@ statemachine_dma_t sm_dma;
/********** Master DATA cycles **************/ /********** Master DATA cycles **************/
// forwards ; // forwards ;
static uint8_t sm_dma_state_1(void); static statemachine_state_func sm_dma_state_1(void);
static uint8_t sm_dma_state_11(void); static statemachine_state_func sm_dma_state_11(void);
static uint8_t sm_dma_state_21(void); static statemachine_state_func sm_dma_state_21(void);
static uint8_t sm_dma_state_99(void); static statemachine_state_func sm_dma_state_99(void);
// dma mailbox setup with // dma mailbox setup with
// startaddr, wordcount, cycle, words[] ? // startaddr, wordcount, cycle, words[] ?
// "cycle" must be UNIBUS_CONTROL_DATI or UNIBUS_CONTROL_DATO // "cycle" must be UNIBUS_CONTROL_DATI or UNIBUS_CONTROL_DATO
// BBSY already set, SACK held asserted // BBSY already set, SACK held asserted
void sm_dma_start() { statemachine_state_func sm_dma_start() {
// assert BBSY: latch[1], bit 6 // assert BBSY: latch[1], bit 6
// buslatches_setbits(1, BIT(6), BIT(6)); // buslatches_setbits(1, BIT(6), BIT(6));
mailbox.dma.cur_addr = mailbox.dma.startaddr; mailbox.dma.cur_addr = mailbox.dma.startaddr;
sm_dma.dataptr = (uint16_t *) mailbox.dma.words; // point to start of data buffer 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; sm_dma.cur_wordsleft = mailbox.dma.wordcount;
mailbox.dma.cur_status = DMA_STATE_RUNNING; mailbox.dma.cur_status = DMA_STATE_RUNNING;
// next call to sm_dma.state() starts state machine // 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 // place address and control bits onto bus, also data for DATO
// If slave address is internal (= implemented by UniBone), // If slave address is internal (= implemented by UniBone),
// fast UNIBUS slave protocol is generated on the bus. // 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 tmpval;
uint32_t addr = mailbox.dma.cur_addr; // non-volatile snapshot uint32_t addr = mailbox.dma.cur_addr; // non-volatile snapshot
uint16_t data; uint16_t data;
@@ -107,7 +109,7 @@ static uint8_t sm_dma_state_1() {
// should test SACK and BBSY ! // should test SACK and BBSY !
if (mailbox.dma.cur_status != DMA_STATE_RUNNING || mailbox.dma.wordcount == 0) 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) { if (sm_dma.cur_wordsleft == 1) {
@@ -178,12 +180,12 @@ static uint8_t sm_dma_state_1() {
while (mailbox.events.eventmask) ; while (mailbox.events.eventmask) ;
buslatches_setbits(4, BIT(5), 0); // slave deassert SSYN 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 { } else {
// DATO to external slave // DATO to external slave
// wait for a slave SSYN // wait for a slave SSYN
TIMEOUT_SET(NANOSECS(1000*UNIBUS_TIMEOUT_PERIOD_US)); 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 { } else {
// DATI or DATIP // DATI or DATIP
@@ -224,25 +226,23 @@ static uint8_t sm_dma_state_1() {
while (mailbox.events.eventmask) ; while (mailbox.events.eventmask) ;
buslatches_setbits(4, BIT(5), 0); // slave deassert SSYN 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 { } else {
// DATI to external slave // DATI to external slave
// wait for a slave SSYN // wait for a slave SSYN
TIMEOUT_SET(NANOSECS(1000*UNIBUS_TIMEOUT_PERIOD_US)); 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 // 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; uint16_t tmpval;
sm_dma.state_timeout = TIMEOUT_REACHED; sm_dma.state_timeout = TIMEOUT_REACHED;
// SSYN = latch[4], bit 5 // SSYN = latch[4], bit 5
if (!sm_dma.state_timeout && !(buslatches_getbyte(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 // SSYN set by slave (or timeout). read data
__delay_cycles(NANOSECS(75) - 6); // assume 2*3 cycles for buslatches_getbyte __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); buslatches_setbits(4, BIT(4), 0);
// DATI: remove address,control, MSYN,SSYN from bus, 75ns after MSYN inactive // DATI: remove address,control, MSYN,SSYN from bus, 75ns after MSYN inactive
__delay_cycles(NANOSECS(75) - 8); // assume 8 cycles for state change __delay_cycles(NANOSECS(75) - 8); // assume 8 cycles for state change
sm_dma.state = &sm_dma_state_99; return (statemachine_state_func)&sm_dma_state_99;
return 0; // still running
} }
// DATO to external slave: wait for SSYN or timeout // 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? sm_dma.state_timeout = TIMEOUT_REACHED; // SSYN timeout?
// SSYN = latch[4], bit 5 // SSYN = latch[4], bit 5
if (!sm_dma.state_timeout && !(buslatches_getbyte(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 // SSYN set by slave (or timeout): negate MSYN, remove DATA from bus
buslatches_setbits(4, BIT(4), 0); // deassert MSYN buslatches_setbits(4, BIT(4), 0); // deassert MSYN
@@ -274,12 +273,11 @@ static uint8_t sm_dma_state_21() {
buslatches_setbyte(6, 0); buslatches_setbyte(6, 0);
// DATO: remove address,control, MSYN,SSYN from bus, 75ns after MSYN inactive // DATO: remove address,control, MSYN,SSYN from bus, 75ns after MSYN inactive
__delay_cycles(NANOSECS(75) - 8); // assume 8 cycles for state change __delay_cycles(NANOSECS(75) - 8); // assume 8 cycles for state change
sm_dma.state = &sm_dma_state_99; return (statemachine_state_func)&sm_dma_state_99;
return 0; // still running
} }
// word is transfered, or timeout. // 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; uint8_t final_dma_state;
// from state_12, state_21 // 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 buslatches_setbits(1, BIT(5), 0); // deassert SACK = latch[1], bit 5
} else } else
final_dma_state = DMA_STATE_RUNNING; // more words: continue 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) { 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 mailbox.dma.cur_addr += 2; // signal progress to ARM
return 0; return (statemachine_state_func)&sm_dma_state_1; // reloop
} else { } else {
// remove addr and control from bus // remove addr and control from bus
buslatches_setbyte(2, 0); buslatches_setbyte(2, 0);
@@ -317,10 +313,9 @@ static uint8_t sm_dma_state_99() {
buslatches_setbits(4, 0x3f, 0); buslatches_setbits(4, 0x3f, 0);
// remove BBSY: latch[1], bit 6 // remove BBSY: latch[1], bit 6
buslatches_setbits(1, BIT(6), 0); buslatches_setbits(1, BIT(6), 0);
// terminate arbitration state // SACK already de-asserted at wordcount==1
sm_arb.state = &sm_arb_state_idle;
mailbox.dma.cur_status = final_dma_state; // signal to ARM 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. 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 12-nov-2018 JH entered beta phase
*/ */
@@ -28,14 +29,11 @@
#define _PRU1_STATEMACHINE_DMA_H_ #define _PRU1_STATEMACHINE_DMA_H_
#include "pru1_utils.h" // statemachine_state_func
// execution of a state. return : 1, if statemachine stopped
typedef uint8_t (*sm_dma_state_func_ptr)(void);
// Transfers a block of worst as data cycles // Transfers a block of worst as data cycles
typedef struct { typedef struct {
sm_dma_state_func_ptr state; // current state as ptr to "state fucntion"
uint8_t state_timeout; // timeout occured? uint8_t state_timeout; // timeout occured?
uint16_t *dataptr ; // points to current word in mailbox.words[] ; uint16_t *dataptr ; // points to current word in mailbox.words[] ;
uint16_t cur_wordsleft; // # of words left to transfer uint16_t cur_wordsleft; // # of words left to transfer
@@ -48,6 +46,6 @@ extern statemachine_dma_t sm_dma;
#endif #endif
void sm_dma_start(void) ; statemachine_state_func sm_dma_start(void) ;
#endif #endif

View File

@@ -21,6 +21,7 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 12-nov-2018 JH entered beta phase
Statemachine for a pulse on UNIBUS INIT Statemachine for a pulse on UNIBUS INIT
@@ -29,6 +30,7 @@
#define _PRU1_STATEMACHINE_INIT_C_ #define _PRU1_STATEMACHINE_INIT_C_
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "mailbox.h" #include "mailbox.h"
@@ -59,33 +61,25 @@ void do_event_initializationsignals() {
statemachine_init_t sm_init;
// forwards // forwards
uint8_t sm_init_state_idle(void); static statemachine_state_func sm_init_state_1(void);
static uint8_t sm_init_state_1(void);
// setup // setup
void sm_init_start() { statemachine_state_func sm_init_start() {
TIMEOUT_SET(MILLISECS(INITPULSE_DELAY_MS)) TIMEOUT_SET(MILLISECS(INITPULSE_DELAY_MS))
; ;
// INIT: latch[7], bit 3 // INIT: latch[7], bit 3
buslatches_setbits(7, BIT(3), BIT(3)); // assert INIT buslatches_setbits(7, BIT(3), BIT(3)); // assert INIT
mailbox.events.initialization_signals_prev &= ~INITIALIZATIONSIGNAL_INIT ; // force INIT event mailbox.events.initialization_signals_prev &= ~INITIALIZATIONSIGNAL_INIT ; // force INIT event
do_event_initializationsignals() ; 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) if (!TIMEOUT_REACHED)
return 0; return (statemachine_state_func)&sm_init_state_1; // wait
buslatches_setbits(7, BIT(3), 0); // deassert INIT buslatches_setbits(7, BIT(3), 0); // deassert INIT
do_event_initializationsignals() ; do_event_initializationsignals() ;
sm_init.state = &sm_init_state_idle; return NULL ; // ready
return 1;
} }

View File

@@ -21,6 +21,7 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 12-nov-2018 JH entered beta phase
*/ */
#ifndef _PRU1_STATEMACHINE_INIT_H_ #ifndef _PRU1_STATEMACHINE_INIT_H_
@@ -28,24 +29,17 @@
#include <stdint.h> #include <stdint.h>
#include "pru1_utils.h" // statemachine_state_func
#define INITPULSE_DELAY_MS 250 // length of INIT pulse #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_ #ifndef _PRU1_STATEMACHINE_INIT_C_
extern uint8_t prev_initialization_signals ; extern uint8_t prev_initialization_signals ;
extern statemachine_init_t sm_init;
#endif #endif
void do_event_initializationsignals(void) ; void do_event_initializationsignals(void) ;
void sm_init_start(); statemachine_state_func sm_init_start();
#endif #endif

View File

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

View File

@@ -21,23 +21,17 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 12-nov-2018 JH entered beta phase
*/ */
#ifndef _PRU1_STATEMACHINE_INTR_H_ #ifndef _PRU1_STATEMACHINE_INTR_H_
#define _PRU1_STATEMACHINE_INTR_H_ #define _PRU1_STATEMACHINE_INTR_H_
// execution of a state. return : 1, if statemachine stopped #include "pru1_utils.h" // statemachine_state_func
typedef uint8_t (*sm_intr_state_func_ptr)(void);
// Transfers a block of worst as data cycles // 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 #endif

View File

@@ -21,6 +21,7 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 12-nov-2018 JH entered beta phase
@@ -41,9 +42,9 @@
#define _PRU1_STATEMACHINE_POWERCYCLE_C_ #define _PRU1_STATEMACHINE_POWERCYCLE_C_
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "mailbox.h" #include "mailbox.h"
#include "pru1_utils.h" #include "pru1_utils.h"
@@ -52,70 +53,60 @@
#include "pru1_statemachine_powercycle.h" #include "pru1_statemachine_powercycle.h"
statemachine_powercycle_t sm_powercycle;
// forwards ; / // forwards ; /
uint8_t sm_powercycle_state_idle(void); static statemachine_state_func sm_powercycle_state_1(void);
static uint8_t sm_powercycle_state_1(void); static statemachine_state_func sm_powercycle_state_2(void);
static uint8_t sm_powercycle_state_2(void); static statemachine_state_func sm_powercycle_state_3(void);
static uint8_t sm_powercycle_state_3(void); static statemachine_state_func sm_powercycle_state_4(void);
static uint8_t sm_powercycle_state_4(void);
// setup with // setup with
void sm_powercycle_start() { statemachine_state_func sm_powercycle_start() {
sm_powercycle.state = &sm_powercycle_state_1; return (statemachine_state_func)&sm_powercycle_state_1;
// next call to sm_slave.state() starts state machine // 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 // "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 buslatches_setbits(7, BIT(4), BIT(4)); // ACLO asserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS)) TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // wait for DC power shutdown ; // wait for DC power shutdown
sm_powercycle.state = &sm_powercycle_state_2;
// DEBUG_OUT(0x01) ; // DEBUG_OUT(0x01) ;
do_event_initializationsignals() ; do_event_initializationsignals() ;
// DEBUG_OUT(0x02) ; // DEBUG_OUT(0x02) ;
return 0; return (statemachine_state_func)&sm_powercycle_state_2;
} }
// "Power supply switched off": assert DCLO, then wait // "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) if (!TIMEOUT_REACHED)
return 0; return (statemachine_state_func)&sm_powercycle_state_2; // wait
buslatches_setbits(7, BIT(5), BIT(5)); // DCLO asserted buslatches_setbits(7, BIT(5), BIT(5)); // DCLO asserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS)) TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // system powered off ; // system powered off
sm_powercycle.state = &sm_powercycle_state_3;
// DEBUG_OUT(0x03) ; // DEBUG_OUT(0x03) ;
do_event_initializationsignals() ; do_event_initializationsignals() ;
// DEBUG_OUT(0x04) ; // DEBUG_OUT(0x04) ;
return 0; return (statemachine_state_func)&sm_powercycle_state_3;
} }
// "Line power back again": deassert ACLO, then wait // "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) if (!TIMEOUT_REACHED)
return 0; return (statemachine_state_func)&sm_powercycle_state_3; // wait
buslatches_setbits(7, BIT(4), 0); // ACLO deasserted buslatches_setbits(7, BIT(4), 0); // ACLO deasserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS)) TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // "power supply stabilizing" ; // "power supply stabilizing"
sm_powercycle.state = &sm_powercycle_state_4;
do_event_initializationsignals() ; do_event_initializationsignals() ;
return 0; return (statemachine_state_func)&sm_powercycle_state_4;
} }
// "Logic power stabilized": deassert DCLO, ready // "Logic power stabilized": deassert DCLO, ready
static uint8_t sm_powercycle_state_4() { static statemachine_state_func sm_powercycle_state_4() {
if (!TIMEOUT_REACHED) if (!TIMEOUT_REACHED)
return 0; return (statemachine_state_func)&sm_powercycle_state_4;
buslatches_setbits(7, BIT(5), 0); // DCLO deasserted buslatches_setbits(7, BIT(5), 0); // DCLO deasserted
sm_powercycle.state = &sm_powercycle_state_idle;
do_event_initializationsignals() ; 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. 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 12-nov-2018 JH entered beta phase
*/ */
#ifndef _PRU1_STATEMACHINE_POWERCYCLE_H_ #ifndef _PRU1_STATEMACHINE_POWERCYCLE_H_
#define _PRU1_STATEMACHINE_POWERCYCLE_H_ #define _PRU1_STATEMACHINE_POWERCYCLE_H_
#include <stdint.h> #include <stdint.h>
#include "pru1_utils.h" // statemachine_state_func
#define POWERCYCLE_DELAY_MS 100 // wait period in millsecs between ACLO/DCLO transitions #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 { statemachine_state_func sm_powercycle_start();
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();
#endif #endif

View File

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

View File

@@ -21,27 +21,15 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 12-nov-2018 JH entered beta phase
*/ */
#ifndef _PRU1_STATEMACHINE_SLAVE_H_ #ifndef _PRU1_STATEMACHINE_SLAVE_H_
#define _PRU1_STATEMACHINE_SLAVE_H_ #define _PRU1_STATEMACHINE_SLAVE_H_
#include <stdint.h> #include <stdint.h>
#include "pru1_utils.h" // statemachine_state_func
// execution of a state. return : 1, if statemachine stopped statemachine_state_func sm_slave_start(void);
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();
#endif #endif

View File

@@ -37,6 +37,12 @@ volatile register uint32_t __R30;
volatile register uint32_t __R31; 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 #define MILLION 1000000L

View File

@@ -176,7 +176,7 @@ void cpu_c::on_init_changed(void) {
// write all registers to "reset-values" // write all registers to "reset-values"
if (init_asserted) { if (init_asserted) {
reset_unibus_registers(); 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*/ parameter_bool_c runmode = parameter_bool_c(this, "run", "r",/*readonly*/
false, "1 = CPU running, 0 = halt"); false, "1 = CPU running, 0 = halt");
parameter_bool_c init = parameter_bool_c(this, "init", "i",/*readonly*/ 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 Bus bus; // UNIBU Sinterface of CPU
struct KA11 ka11; // Angelos CPU state struct KA11 ka11; // Angelos CPU state

View File

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

View File

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