diff --git a/10.01_base/2_src/pru1/Makefile b/10.01_base/2_src/pru1/Makefile index cb08013..c4490f4 100644 --- a/10.01_base/2_src/pru1/Makefile +++ b/10.01_base/2_src/pru1/Makefile @@ -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 diff --git a/10.01_base/2_src/pru1/pru1_main_test.c b/10.01_base/2_src/pru1/pru1_main_test.c index e60050d..d254d1d 100644 --- a/10.01_base/2_src/pru1/pru1_main_test.c +++ b/10.01_base/2_src/pru1/pru1_main_test.c @@ -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(); diff --git a/10.01_base/2_src/pru1/pru1_main_unibus.c b/10.01_base/2_src/pru1/pru1_main_unibus.c index 97cb395..8ba0cef 100644 --- a/10.01_base/2_src/pru1/pru1_main_unibus.c +++ b/10.01_base/2_src/pru1/pru1_main_unibus.c @@ -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(); diff --git a/10.01_base/2_src/pru1/pru1_statemachine_dma.c b/10.01_base/2_src/pru1/pru1_statemachine_dma.c index f42ef2a..365c73b 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_dma.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_dma.c @@ -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 } diff --git a/10.01_base/2_src/pru1/pru1_statemachine_init.c b/10.01_base/2_src/pru1/pru1_statemachine_init.c index bd7a8f0..a59a87d 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_init.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_init.c @@ -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 } diff --git a/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c b/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c index 6897944..3b21eab 100644 --- a/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c +++ b/10.01_base/2_src/pru1/pru1_statemachine_powercycle.c @@ -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; } diff --git a/10.01_base/2_src/pru1/pru1_timeouts.c b/10.01_base/2_src/pru1/pru1_timeouts.c new file mode 100644 index 0000000..9236fb1 --- /dev/null +++ b/10.01_base/2_src/pru1/pru1_timeouts.c @@ -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 +#include + +#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) ; +} diff --git a/10.01_base/2_src/pru1/pru1_timeouts.h b/10.01_base/2_src/pru1/pru1_timeouts.h new file mode 100644 index 0000000..c41f868 --- /dev/null +++ b/10.01_base/2_src/pru1/pru1_timeouts.h @@ -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 +#include + + +// 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 diff --git a/10.01_base/2_src/pru1/pru1_utils.h b/10.01_base/2_src/pru1/pru1_utils.h index 3a210ac..237bb10 100644 --- a/10.01_base/2_src/pru1/pru1_utils.h +++ b/10.01_base/2_src/pru1/pru1_utils.h @@ -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)) )