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

PRU1: multiple parallel timeouts

This commit is contained in:
Joerg Hoppe
2019-07-03 21:48:49 +02:00
parent 3f783e5000
commit 471df2d8ea
9 changed files with 194 additions and 24 deletions

View File

@@ -75,6 +75,7 @@ OBJECTS_COMMON= \
$(OBJ_DIR)/pru1_statemachine_intr.object \
$(OBJ_DIR)/pru1_statemachine_powercycle.object \
$(OBJ_DIR)/pru1_statemachine_slave.object \
$(OBJ_DIR)/pru1_timeouts.object \
$(OBJ_DIR)/pru1_utils.object

View File

@@ -42,6 +42,7 @@
#include "resource_table_empty.h"
#include "pru1_utils.h"
#include "pru1_timeouts.h"
#include "pru_pru_mailbox.h"
#include "mailbox.h"
@@ -67,6 +68,8 @@ void main(void) {
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
timeout_init() ;
// clear all tables, as backup if ARM fails todo
iopageregisters_init();

View File

@@ -48,6 +48,7 @@
#include "resource_table_empty.h"
#include "pru1_utils.h"
#include "pru1_timeouts.h"
#include "pru_pru_mailbox.h"
#include "mailbox.h"
@@ -88,6 +89,8 @@ void main(void) {
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
timeout_init() ;
// clear all tables, as backup if ARM fails todo
iopageregisters_init();

View File

@@ -60,6 +60,7 @@
#include "mailbox.h"
#include "pru1_buslatches.h"
#include "pru1_utils.h"
#include "pru1_timeouts.h"
#include "pru1_statemachine_arbitration.h"
#include "pru1_statemachine_dma.h"
@@ -184,7 +185,7 @@ static statemachine_state_func sm_dma_state_1() {
} else {
// DATO to external slave
// wait for a slave SSYN
TIMEOUT_SET(NANOSECS(1000*UNIBUS_TIMEOUT_PERIOD_US));
timeout_set(TIMEOUT_DMA, MICROSECS(UNIBUS_TIMEOUT_PERIOD_US));
return (statemachine_state_func)&sm_dma_state_21; // wait SSYN DATAO
}
} else {
@@ -230,7 +231,7 @@ static statemachine_state_func sm_dma_state_1() {
} else {
// DATI to external slave
// wait for a slave SSYN
TIMEOUT_SET(NANOSECS(1000*UNIBUS_TIMEOUT_PERIOD_US));
timeout_set(TIMEOUT_DMA, MICROSECS(UNIBUS_TIMEOUT_PERIOD_US));
return (statemachine_state_func)&sm_dma_state_11; // wait SSYN DATI
}
}
@@ -239,7 +240,7 @@ static statemachine_state_func sm_dma_state_1() {
// DATI to external slave: MSYN set, wait for SSYN or timeout
static statemachine_state_func sm_dma_state_11() {
uint16_t tmpval;
sm_dma.state_timeout = TIMEOUT_REACHED;
sm_dma.state_timeout = timeout_reached(TIMEOUT_DMA);
// SSYN = latch[4], bit 5
if (!sm_dma.state_timeout && !(buslatches_getbyte(4) & BIT(5)))
return (statemachine_state_func)&sm_dma_state_11; // no SSYN yet: wait
@@ -262,7 +263,7 @@ static statemachine_state_func sm_dma_state_11() {
// DATO to external slave: wait for SSYN or timeout
static statemachine_state_func sm_dma_state_21() {
sm_dma.state_timeout = TIMEOUT_REACHED; // SSYN timeout?
sm_dma.state_timeout = timeout_reached(TIMEOUT_DMA); // SSYN timeout?
// SSYN = latch[4], bit 5
if (!sm_dma.state_timeout && !(buslatches_getbyte(4) & BIT(5)))
return (statemachine_state_func)&sm_dma_state_21; // no SSYN yet: wait
@@ -314,6 +315,7 @@ static statemachine_state_func sm_dma_state_99() {
// remove BBSY: latch[1], bit 6
buslatches_setbits(1, BIT(6), 0);
// SACK already de-asserted at wordcount==1
timeout_cleanup(TIMEOUT_DMA) ;
mailbox.dma.cur_status = final_dma_state; // signal to ARM
return NULL; // now stopped
}

View File

@@ -35,6 +35,7 @@
#include "mailbox.h"
#include "pru1_utils.h"
#include "pru1_timeouts.h"
#include "pru1_buslatches.h"
#include "pru1_statemachine_init.h"
@@ -66,7 +67,7 @@ static statemachine_state_func sm_init_state_1(void);
// setup
statemachine_state_func sm_init_start() {
TIMEOUT_SET(MILLISECS(INITPULSE_DELAY_MS))
timeout_set(TIMEOUT_INIT, MILLISECS(INITPULSE_DELAY_MS))
;
// INIT: latch[7], bit 3
buslatches_setbits(7, BIT(3), BIT(3)); // assert INIT
@@ -77,9 +78,10 @@ statemachine_state_func sm_init_start() {
static statemachine_state_func sm_init_state_1() {
if (!TIMEOUT_REACHED)
if (!timeout_reached(TIMEOUT_INIT))
return (statemachine_state_func)&sm_init_state_1; // wait
buslatches_setbits(7, BIT(3), 0); // deassert INIT
do_event_initializationsignals() ;
timeout_cleanup(TIMEOUT_INIT) ;
return NULL ; // ready
}

View File

@@ -47,6 +47,7 @@
#include "mailbox.h"
#include "pru1_utils.h"
#include "pru1_timeouts.h"
#include "pru1_buslatches.h"
#include "pru1_statemachine_init.h"
@@ -69,8 +70,7 @@ statemachine_state_func sm_powercycle_start() {
// "Line power shutdown": assert ACLO, then wait
static statemachine_state_func sm_powercycle_state_1() {
buslatches_setbits(7, BIT(4), BIT(4)); // ACLO asserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
; // wait for DC power shutdown
timeout_set(TIMEOUT_POWERCYCLE, MILLISECS(POWERCYCLE_DELAY_MS)) ; // wait for DC power shutdown
// DEBUG_OUT(0x01) ;
do_event_initializationsignals() ;
// DEBUG_OUT(0x02) ;
@@ -79,10 +79,10 @@ static statemachine_state_func sm_powercycle_state_1() {
// "Power supply switched off": assert DCLO, then wait
static statemachine_state_func sm_powercycle_state_2() {
if (!TIMEOUT_REACHED)
if (!timeout_reached(TIMEOUT_POWERCYCLE))
return (statemachine_state_func)&sm_powercycle_state_2; // wait
buslatches_setbits(7, BIT(5), BIT(5)); // DCLO asserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
timeout_set(TIMEOUT_POWERCYCLE, MILLISECS(POWERCYCLE_DELAY_MS))
; // system powered off
// DEBUG_OUT(0x03) ;
do_event_initializationsignals() ;
@@ -92,10 +92,10 @@ static statemachine_state_func sm_powercycle_state_2() {
// "Line power back again": deassert ACLO, then wait
static statemachine_state_func sm_powercycle_state_3() {
if (!TIMEOUT_REACHED)
if (!timeout_reached(TIMEOUT_POWERCYCLE))
return (statemachine_state_func)&sm_powercycle_state_3; // wait
buslatches_setbits(7, BIT(4), 0); // ACLO deasserted
TIMEOUT_SET(MILLISECS(POWERCYCLE_DELAY_MS))
timeout_set(TIMEOUT_POWERCYCLE, MILLISECS(POWERCYCLE_DELAY_MS))
; // "power supply stabilizing"
do_event_initializationsignals() ;
return (statemachine_state_func)&sm_powercycle_state_4;
@@ -103,10 +103,11 @@ static statemachine_state_func sm_powercycle_state_3() {
// "Logic power stabilized": deassert DCLO, ready
static statemachine_state_func sm_powercycle_state_4() {
if (!TIMEOUT_REACHED)
if (!timeout_reached(TIMEOUT_POWERCYCLE))
return (statemachine_state_func)&sm_powercycle_state_4;
buslatches_setbits(7, BIT(5), 0); // DCLO deasserted
do_event_initializationsignals() ;
timeout_cleanup(TIMEOUT_POWERCYCLE) ;
return NULL;
}

View File

@@ -0,0 +1,117 @@
/* pru1_timeouts.c: timeout conditions
Copyright (c) 2019, Joerg Hoppe
j_hoppe@t-online.de, www.retrocmp.com
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3-jul-2019 JH begin edit
Several timers are needed, but PRU hs only one
global cycle counter CYCLEOUNT. It is 32 bit and runs at 200 MHz,
so rollaround every 21 seconds.
Usage:
- if no timer is running, the first "timeout" reuqest clears CYCLEOUNT
- for each timer, the "timeout" cycle count is set
- tiemr msut be polled for timeout by user.
- a timer is considered "timed-out", if its timeout is 0.
- a global variable regsiteres the active running timeouts.
- a running timeout MUST be canceled, or polled until "timeout_rechaed" !!
The PRU CYCLECOUNT may not be reset if one timeout is active.
So the total run time of all parallel running timeous must not exceed 21 seconds
At least every 21 seconds all timers must be expired.
*/
#include <stdint.h>
#include <string.h>
#include "pru1_utils.h"
#include "pru1_timeouts.h" // own
// count running timers.
static uint8_t timeouts_active = 0 ;
// cycle end count for each active timeoput.
uint32_t timeout_target_cycles[TIMEOUT_COUNT] ;
// all functions receive a pointer to one of these array members
#define TIMEOUT_INTERNAL_CYCLES 24
void timeout_set(uint32_t *target_cycles_var, uint32_t delta_cycles) {
// stop timeout, if already running
if (*target_cycles_var > 0) {
*target_cycles_var = 0 ;
timeouts_active-- ; // was inactive
}
if (timeouts_active == 0) {
// must see this regulary, else count logic damaged!
// DEBUG_PIN_SET(1) ;
// first timeout: clear and restart counter
PRU1_CTRL.CTRL_bit.CTR_EN = 0;
PRU1_CTRL.CYCLE = 0 ;
}
/* 4 cycle used in TIMEOUT_REACHED */
if (delta_cycles < TIMEOUT_INTERNAL_CYCLES)
delta_cycles = 0 ;
else delta_cycles -= TIMEOUT_INTERNAL_CYCLES ;
*target_cycles_var = PRU1_CTRL.CYCLE + delta_cycles ;
PRU1_CTRL.CTRL_bit.CTR_EN = 1;
timeouts_active++ ; // now one more active
}
// msut be called, if timeout polled anymore for "timeout-reached()
void timeout_cleanup(uint32_t *target_cycles_var) {
if (*target_cycles_var > 0) {
*target_cycles_var = 0 ;
timeouts_active-- ; // was inactive
}
}
//
// test a timeout, wehter it reached its arg count nor or earlier
bool timeout_reached(uint32_t *target_cycles_var) {
// fast path: assume timeout_reached() is called
// because timeout is active
if ( PRU1_CTRL.CYCLE < *target_cycles_var)
return false ;
else if (*target_cycles_var == 0)
return true ; // already inactive
else {
// switched from "running" to "timeout reached"
*target_cycles_var = 0 ;
timeouts_active-- ;
return true ;
}
}
void timeout_init(void) {
timeouts_active = 0 ;
memset(timeout_target_cycles, 0, sizeof(uint32_t) * TIMEOUT_COUNT) ;
}

View File

@@ -0,0 +1,52 @@
/* pru1_timeouts.h: timeout conditions
Copyright (c) 2019, Joerg Hoppe
j_hoppe@t-online.de, www.retrocmp.com
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3-jul-2019 JH begin edit
*/
#ifndef _PRU1_TIMEOUTS_H_
#define _PRU1_TIMEOUTS_H_
#include <stdint.h>
#include <stdbool.h>
// predefined timeouts
#define TIMEOUT_COUNT 3
// fixed pointers
#define TIMEOUT_DMA (&timeout_target_cycles[0])
#define TIMEOUT_INIT (&timeout_target_cycles[1])
#define TIMEOUT_POWERCYCLE (&timeout_target_cycles[2])
// cycle end count for each active timeoput.
extern uint32_t timeout_target_cycles[TIMEOUT_COUNT] ;
// call all functions mit timeout_func(TIMEOUT_*,..)
// This allows the compiler to optimize the timeout_target_cycles[idx] expr
void timeout_init(void) ;
void timeout_set(uint32_t *target_cycles_var, uint32_t delta_cycles) ;
bool timeout_reached(uint32_t *target_cycles_var) ;
void timeout_cleanup(uint32_t *target_cycles_var) ;
#endif

View File

@@ -96,17 +96,6 @@ http://theembeddedkitchen.net/beaglelogic-building-a-logic-analyzer-with-the-pru
* introduces delay in PRU0 outputs!
*/
#define TIMEOUT_INTERNAL_CYCLES 24
#define TIMEOUT_SET(cycles) do { \
PRU1_CTRL.CTRL_bit.CTR_EN = 0; \
PRU1_CTRL.CYCLE = 0 ; \
timeout_target = ((cycles) > TIMEOUT_INTERNAL_CYCLES) ? ((cycles) - TIMEOUT_INTERNAL_CYCLES) : 0 ; /* 4 cycle used in TIMEOUT_REACHED */ \
PRU1_CTRL.CTRL_bit.CTR_EN = 1; \
} while(0)
#define TIMEOUT_REACHED \
( (PRU1_CTRL.CYCLE >= timeout_target))
// set PRU1_12 to 0 or 1
#define DEBUG_PIN_SET(val) ( (val) ? (__R30 |= (1 << 12) ) : (__R30 &= ~(1<< 12)) )