From: ljsebald <ljs...@us...> - 2023-10-23 02:11:12
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 1526b24db29723634ae096a139f70a918eb428fd (commit) via 9a4aa4d69b7af66eb7835fc32cacbc2035b340e9 (commit) from 8bce82fca68ebfcba54214a1122197b7464dd2d3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 1526b24db29723634ae096a139f70a918eb428fd Author: Falco Girgis <gyr...@gm...> Date: Sun Oct 22 21:09:35 2023 -0500 Watchdog Timer Driver (#324) * Added Watchdog driver files wdt.h and wdt.c. * Initial attempt at driver API + example 1) Initial API for driver is done 2) Initial implementation is mostly done, partially tested 3) added an example to the "basic" directory for demonstrating its usage 4) Watchdog timer mode seems to work fine 5) Interval timer mode doesn't seem to be firing interrupts as expected, WIP * Interval timer mode and example are working * usec configurable interval timer working - User can now request an arbitrary interval in microseconds for their callback to get invoked after in interval mode (and it'll do the best it can at the given resolution) - Began documenting a bunch of the API - Fixed wdt_disable() which was still leaving the watchdog running when using interval timer mode. * Driver implementation and documentation complete - Finished Doxygen documentation and commenting driver - Added extra parameter to wdt_enable_timer() for specifying interval timer interupt priority - Got rid of all magic numbers/values - Reset initialized flag to 0 in irq_shutdown() - Fixed compilation of watchdog timer example (still need to finish it, though) * Finished example/test scenario - Completed an example demonstrating usage of the WDT in both modes. - Commented the thing thoroughly to explain what's happening. * Typo fixes + comment clarification. * Apply suggestions from code review Co-authored-by: Andress Barajas <and...@gm...> * Updated CHANGELOG --------- Co-authored-by: Andress Barajas <and...@gm...> commit 9a4aa4d69b7af66eb7835fc32cacbc2035b340e9 Author: Andress Barajas <and...@gm...> Date: Sun Oct 22 18:58:20 2023 -0700 Examples refresh (#328) * Added press start to exit to some examples. Removed -n from pvr examples to make it easier to profile ----------------------------------------------------------------------- Summary of changes: doc/CHANGELOG | 1 + examples/dreamcast/basic/Makefile | 3 + .../basic/threading/compiler_tls/Makefile | 25 ++- .../basic/{threading/once => watchdog}/Makefile | 9 +- examples/dreamcast/basic/watchdog/watchdog.c | 161 +++++++++++++++++++ .../dreamcast/kgl/basic/elements/gl-elements.c | 19 +++ .../dreamcast/kgl/basic/zclip_arrays/gl-arrays.c | 19 +++ examples/dreamcast/kgl/demos/blur/radial_blur.c | 20 ++- .../demos/multitexture-arrays/gl-multitex-arrays.c | 19 +++ .../multitexture-elements/gl-multitex-elements.c | 19 +++ examples/dreamcast/libdream/cdfs/cdfs.c | 1 + examples/dreamcast/pvr/bumpmap/Makefile | 2 +- examples/dreamcast/pvr/cheap_shadow/Makefile | 2 +- examples/dreamcast/pvr/modifier_volume/Makefile | 2 +- .../dreamcast/pvr/modifier_volume_tex/Makefile | 2 +- examples/dreamcast/pvr/plasma/Makefile | 2 +- examples/dreamcast/pvr/pvrmark/Makefile | 2 +- examples/dreamcast/pvr/pvrmark_strips/Makefile | 2 +- .../dreamcast/pvr/pvrmark_strips_direct/Makefile | 2 +- .../dreamcast/pvr/yuv_converter/YUV420/Makefile | 2 +- .../dreamcast/pvr/yuv_converter/YUV422/Makefile | 2 +- examples/dreamcast/sound/hello-mp3/Makefile | 1 - include/kos.h | 1 + kernel/arch/dreamcast/include/arch/timer.h | 6 - kernel/arch/dreamcast/include/arch/wdt.h | 172 +++++++++++++++++++++ kernel/arch/dreamcast/kernel/Makefile | 2 +- kernel/arch/dreamcast/kernel/irq.c | 2 + kernel/arch/dreamcast/kernel/wdt.c | 154 ++++++++++++++++++ 28 files changed, 617 insertions(+), 37 deletions(-) copy examples/dreamcast/basic/{threading/once => watchdog}/Makefile (71%) create mode 100644 examples/dreamcast/basic/watchdog/watchdog.c create mode 100644 kernel/arch/dreamcast/include/arch/wdt.h create mode 100644 kernel/arch/dreamcast/kernel/wdt.c diff --git a/doc/CHANGELOG b/doc/CHANGELOG index d051ba0..b52310c 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -191,6 +191,7 @@ KallistiOS version 2.1.0 ----------------------------------------------- - *** Added GCC builtin functions for supporting all of C11 atomics [FG] - *** Added toolchain and KOS support for C/C++ compiler-level TLS [CP && FG] - DC Added vmu functions to check/enable/disable the extra 41 blocks [AB] +- *** Added driver for the SH4's Watchdog Timer peripheral [FG] KallistiOS version 2.0.0 ----------------------------------------------- - DC Broadband Adapter driver fixes [Megan Potter == MP] diff --git a/examples/dreamcast/basic/Makefile b/examples/dreamcast/basic/Makefile index 4224e29..45715c8 100644 --- a/examples/dreamcast/basic/Makefile +++ b/examples/dreamcast/basic/Makefile @@ -13,6 +13,7 @@ all: $(KOS_MAKE) -C mmu $(KOS_MAKE) -C stackprotector $(KOS_MAKE) -C memtest32 + $(KOS_MAKE) -C watchdog clean: $(KOS_MAKE) -C exec clean @@ -23,6 +24,7 @@ clean: $(KOS_MAKE) -C mmu clean $(KOS_MAKE) -C stackprotector clean $(KOS_MAKE) -C memtest32 clean + $(KOS_MAKE) -C watchdog clean dist: $(KOS_MAKE) -C exec dist @@ -33,3 +35,4 @@ dist: $(KOS_MAKE) -C mmu dist $(KOS_MAKE) -C stackprotector dist $(KOS_MAKE) -C memtest32 dist + $(KOS_MAKE) -C watchdog dist diff --git a/examples/dreamcast/basic/threading/compiler_tls/Makefile b/examples/dreamcast/basic/threading/compiler_tls/Makefile index 6e3e692..356a853 100644 --- a/examples/dreamcast/basic/threading/compiler_tls/Makefile +++ b/examples/dreamcast/basic/threading/compiler_tls/Makefile @@ -6,26 +6,25 @@ # Copyright (C) 2023 Colton Pawielski # -EXAMPLE_NAME=compiler_tls +TARGET = compiler_tls.elf +OBJS = compiler_tls.o -all: rm-elf $(EXAMPLE_NAME).elf +all: rm-elf $(TARGET) include $(KOS_BASE)/Makefile.rules -OBJS = $(EXAMPLE_NAME).o - -clean: - -rm -f $(EXAMPLE_NAME).elf $(OBJS) +clean: rm-elf + -rm -f $(OBJS) rm-elf: - -rm -f $(EXAMPLE_NAME).elf + -rm -f $(TARGET) -$(EXAMPLE_NAME).elf: $(OBJS) - $(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(EXAMPLE_NAME).elf -ftls-model=local-exec $(KOS_START) $(OBJS) $(DATAOBJS) $(OBJEXTRA) $(KOS_LIBS) -Wl,-Map=$(EXAMPLE_NAME).map +$(TARGET): $(OBJS) + kos-cc -o $(TARGET) -ftls-model=local-exec $(OBJS) -Wl,-Map=compiler_tls.map -run: $(EXAMPLE_NAME).elf - $(KOS_LOADER) $(EXAMPLE_NAME).elf +run: $(TARGET) + $(KOS_LOADER) $(TARGET) -dist: +dist: $(TARGET) -rm -f $(OBJS) - $(KOS_STRIP) $(EXAMPLE_NAME).elf + $(KOS_STRIP) $(TARGET) diff --git a/examples/dreamcast/basic/threading/once/Makefile b/examples/dreamcast/basic/watchdog/Makefile similarity index 71% copy from examples/dreamcast/basic/threading/once/Makefile copy to examples/dreamcast/basic/watchdog/Makefile index 52d83b3..54ac0b2 100644 --- a/examples/dreamcast/basic/threading/once/Makefile +++ b/examples/dreamcast/basic/watchdog/Makefile @@ -1,11 +1,11 @@ # KallistiOS ##version## # -# basic/threading/once/Makefile -# Copyright (C) 2009 Lawrence Sebald +# examples/dreamcast/basic/watchdog/Makefile +# Copyright (c) 2023 Falco Girgis # -TARGET = once_test.elf -OBJS = once_test.o +TARGET = watchdog.elf +OBJS = watchdog.o all: rm-elf $(TARGET) @@ -26,4 +26,3 @@ run: $(TARGET) dist: $(TARGET) -rm -f $(OBJS) $(KOS_STRIP) $(TARGET) - diff --git a/examples/dreamcast/basic/watchdog/watchdog.c b/examples/dreamcast/basic/watchdog/watchdog.c new file mode 100644 index 0000000..9a72812 --- /dev/null +++ b/examples/dreamcast/basic/watchdog/watchdog.c @@ -0,0 +1,161 @@ +/* KallistiOS ##version## + + watchdog.c + Copyright (C) 2023 Falco Girgis + +*/ + +/* This program serves as both an example of using the Watchdog Timer + peripheral on the Dreamcast's SH4 CPU as well as a test to validate + the behavior of its driver in KOS. + + NOTE: + At the time this is being written, there are no Dreamcast emulators + out there which are bothering to emulate the SH4 WDT, since apparently + no commercial games actually used it. Special care has been taken to + fail the tests gracefully when there is no functioning WDT. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdatomic.h> +#include <time.h> + +#include <arch/wdt.h> +#include <dc/maple/controller.h> + +/* Microsecond-based units */ +#define MSEC 1000 +#define SEC (1000 * MSEC) + +/* Test configuration constants */ +#define WDT_PET_COUNT 2000 +#define WDT_INTERVAL (500 * MSEC) +#define WDT_SECONDS 10 +#define WDT_COUNT_MAX ((WDT_SECONDS * SEC) / WDT_INTERVAL) + +/* User callback to be invoked from the WDT's interval timer + interrupt when the requested microsecond period has elapsed. + Our generic userdata pointer is passed back to us as void*. + We use it to store our atomic counter to count the number + of times this callback has been invoked. + + NOTE: Since we're accessing both from within and outside + of the interrupt, we make it atomic to ensure that it + doesn't get updated while it's being read or vice-versa. */ +static void wdt_timeout(void *user_data) { + ++(*(atomic_uint *)user_data); +} + +/* Main entry point */ +int main(int argc, char *argv[]) { + bool success = true; + + /* Press all buttons simultaneously to exit early. */ + cont_btn_callback(0, CONT_START | CONT_A | CONT_B | CONT_X | CONT_Y, + (cont_btn_callback_t)exit); + + /* Note that is EXTREMELY important that the WDT gets disabled + when it is done being used, otherwise it can continue running + after the application exits and can interfere with DC-Load + operation. Since we have multiple exit points (one from returning + from main and one from the button callback), the safest thing to do + is to register wdt_disable() to be called automatically upon exit. */ + atexit(wdt_disable); + + printf("\nEnabling WDT in watchdog mode!\n"); + + /* Enable watchdog mode with a period of 5.25ms, causing a manual + reset interrupt signal to be raised upon timeout. This will + cause your Dreamcast to reboot immediately. */ + wdt_enable_watchdog(0, WDT_CLK_DIV_4096, WDT_RST_MANUAL); + + /* Continually "pet" the watchdog timer in a loop, resetting its + counter value and preventing a timeout (and reboot). We also + store its max value as we're iterating. */ + uint8_t max_count = 0; + for(int p = 0; p < WDT_PET_COUNT; ++p) { + const uint8_t current_count = wdt_get_counter(); + + if(current_count > max_count) + max_count = current_count; + + wdt_pet(); + } + + /* Immediately disable the WDT once we're done with it. */ + wdt_disable(); + + /* Ensure that the WDT's counter wasn't stuck at zero the whole + time and that it was actually updating as expected. */ + if(!max_count) { + fprintf(stderr, "The WDT counter never even incremented!\n\n"); + success = false; + } + else { + printf("Pet it %d times! Maximum counter value was %u.\n\n", + WDT_PET_COUNT, max_count); + } + + printf("Enabling WDT timer with interval: %uus.\n", WDT_INTERVAL); + printf("Expecting %u callbacks over %u seconds.\n", + WDT_COUNT_MAX, WDT_SECONDS); + + /* Enable the WDT in interval counter mode, with a period of 500ms, + an interrupt priority level of 15 (highest), and give it our + timeout callback plus pass it our counter as its userdata pointer. */ + atomic_uint counter = 0; + wdt_enable_timer(0, WDT_INTERVAL, 15, wdt_timeout, &counter); + + /* Begin spinning in a loop until either condition is met: + 1) The counter becomes greater than or equal to the expected value + (meaning our callback has been called the expected number of times + from the Watchdog timer's interval interrupt). + 2) The elapsed time becomes greater than twice the expected number of + seconds, meaning the watchdog interval timer is not behaving as we + expected it to behave (probably running on emulator). + */ + const time_t start_time = time(NULL); + time_t current_time = start_time; + time_t elapsed_time = 0; + while(1) { + /* Measure our current time (using the C standard library, + which internally uses the TMU2 peripheral). */ + current_time = time(NULL); + elapsed_time = current_time - start_time; + + /* Check whether the WDT timer has incremented our counter the + expected number of times and exit if so. */ + if(counter >= WDT_COUNT_MAX) { + break; + } + /* Check whether we should just give up on the WDT. */ + else if(elapsed_time > WDT_SECONDS * 2) { + fprintf(stderr, "Test is taking too long... timing out!\n"); + success = false; + break; + } + } + + printf("%u callbacks in %llu seconds!\n", counter, elapsed_time); + + /* Ensure that the amount of time elapsed based on WDT callbacks agrees + with the amount of time elapsed as reported by TMU2. */ + const unsigned diff_seconds = abs((int)elapsed_time - (int)WDT_SECONDS); + if(diff_seconds > 1) { + printf("Watchdog timing did not match system timing!\n" + "\t[%u sec delta]\n", diff_seconds); + success = false; + } + + /* Report results and return status code. */ + if(success) { + printf("\n\n***** WATCHDOG TIMER TEST SUCCEEDED! *****\n\n"); + return EXIT_SUCCESS; + } + else { + fprintf(stderr, "\n\nXXXXX WATCHDOG TIMER TEST FAILED! XXXXX\n\n"); + return EXIT_FAILURE; + } +} diff --git a/examples/dreamcast/kgl/basic/elements/gl-elements.c b/examples/dreamcast/kgl/basic/elements/gl-elements.c index 9a76148..2a2fd2e 100644 --- a/examples/dreamcast/kgl/basic/elements/gl-elements.c +++ b/examples/dreamcast/kgl/basic/elements/gl-elements.c @@ -78,6 +78,22 @@ void RenderCallback(GLuint texID) { glDisable(GL_KOS_NEARZ_CLIPPING); } +static int check_start(void) { + maple_device_t *cont; + cont_state_t *state; + + cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + + if(cont) { + state = (cont_state_t *)maple_dev_status(cont); + + if(state) + return state->buttons & CONT_START; + } + + return 0; +} + extern uint8 romdisk[]; KOS_INIT_ROMDISK(romdisk); @@ -98,6 +114,9 @@ int main(int argc, char **argv) { GLuint texID = glTextureLoadPVR("/rd/wp001vq.pvr", 0, 0); while(1) { + if(check_start()) + break; + /* Draw the "scene" */ RenderCallback(texID); diff --git a/examples/dreamcast/kgl/basic/zclip_arrays/gl-arrays.c b/examples/dreamcast/kgl/basic/zclip_arrays/gl-arrays.c index 5da5f66..a18e829 100644 --- a/examples/dreamcast/kgl/basic/zclip_arrays/gl-arrays.c +++ b/examples/dreamcast/kgl/basic/zclip_arrays/gl-arrays.c @@ -86,6 +86,22 @@ void RenderCallback(GLuint texID) { glDisable(GL_KOS_NEARZ_CLIPPING); } +static int check_start(void) { + maple_device_t *cont; + cont_state_t *state; + + cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + + if(cont) { + state = (cont_state_t *)maple_dev_status(cont); + + if(state) + return state->buttons & CONT_START; + } + + return 0; +} + extern uint8 romdisk[]; KOS_INIT_ROMDISK(romdisk); @@ -105,6 +121,9 @@ int main(int argc, char **argv) { buildDemoArray(); while(1) { + if(check_start()) + break; + /* Draw the "scene" */ RenderCallback(texID); diff --git a/examples/dreamcast/kgl/demos/blur/radial_blur.c b/examples/dreamcast/kgl/demos/blur/radial_blur.c index 5479974..5b136c3 100644 --- a/examples/dreamcast/kgl/demos/blur/radial_blur.c +++ b/examples/dreamcast/kgl/demos/blur/radial_blur.c @@ -290,10 +290,25 @@ int InputCallback(void) { return 1; } +static int check_start(void) { + maple_device_t *cont; + cont_state_t *state; + + cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + + if(cont) { + state = (cont_state_t *)maple_dev_status(cont); + + if(state) + return state->buttons & CONT_START; + } + + return 0; +} + extern uint8 romdisk[]; KOS_INIT_ROMDISK(romdisk); - int main(int argc, char **argv) { printf("glRadialBlur beginning\n"); @@ -328,6 +343,9 @@ int main(int argc, char **argv) { while(1) { + if(check_start()) + break; + /* Draw the GL "scene" */ if(enable_radial) { /* Bind the Frame Buffer Object to GL, for render-to-texture */ diff --git a/examples/dreamcast/kgl/demos/multitexture-arrays/gl-multitex-arrays.c b/examples/dreamcast/kgl/demos/multitexture-arrays/gl-multitex-arrays.c index ffd18a8..4129812 100644 --- a/examples/dreamcast/kgl/demos/multitexture-arrays/gl-multitex-arrays.c +++ b/examples/dreamcast/kgl/demos/multitexture-arrays/gl-multitex-arrays.c @@ -90,6 +90,22 @@ void RenderCallback(GLuint texID0, GLuint texID1) { glDisableClientState(GL_VERTEX_ARRAY); } +static int check_start(void) { + maple_device_t *cont; + cont_state_t *state; + + cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + + if(cont) { + state = (cont_state_t *)maple_dev_status(cont); + + if(state) + return state->buttons & CONT_START; + } + + return 0; +} + extern uint8 romdisk[]; KOS_INIT_ROMDISK(romdisk); @@ -108,6 +124,9 @@ int main(int argc, char **argv) { GLuint texID1 = glTextureLoadPVR("/rd/FlareWS_256.pvr", 0, 0); while(1) { + if(check_start()) + break; + /* Draw the "scene" */ RenderCallback(texID0, texID1); diff --git a/examples/dreamcast/kgl/demos/multitexture-elements/gl-multitex-elements.c b/examples/dreamcast/kgl/demos/multitexture-elements/gl-multitex-elements.c index c64caa0..89dd481 100644 --- a/examples/dreamcast/kgl/demos/multitexture-elements/gl-multitex-elements.c +++ b/examples/dreamcast/kgl/demos/multitexture-elements/gl-multitex-elements.c @@ -93,6 +93,22 @@ void RenderCallback(GLuint texID0, GLuint texID1) { glDisableClientState(GL_VERTEX_ARRAY); } +static int check_start(void) { + maple_device_t *cont; + cont_state_t *state; + + cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + + if(cont) { + state = (cont_state_t *)maple_dev_status(cont); + + if(state) + return state->buttons & CONT_START; + } + + return 0; +} + extern uint8 romdisk[]; KOS_INIT_ROMDISK(romdisk); @@ -111,6 +127,9 @@ int main(int argc, char **argv) { GLuint texID1 = glTextureLoadPVR("/rd/FlareWS_256.pvr", 0, 0); while(1) { + if(check_start()) + break; + /* Draw the "scene" */ RenderCallback(texID0, texID1); diff --git a/examples/dreamcast/libdream/cdfs/cdfs.c b/examples/dreamcast/libdream/cdfs/cdfs.c index 2277e3a..a482a28 100644 --- a/examples/dreamcast/libdream/cdfs/cdfs.c +++ b/examples/dreamcast/libdream/cdfs/cdfs.c @@ -3,6 +3,7 @@ #include <kos.h> + char buffer[2048]; void cdfs_test(void) { file_t fd; diff --git a/examples/dreamcast/pvr/bumpmap/Makefile b/examples/dreamcast/pvr/bumpmap/Makefile index 7b91855..442f390 100644 ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |