aboutsummaryrefslogtreecommitdiffstats
path: root/testhal/common
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-04-11 14:37:16 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-04-11 14:37:16 +0000
commit5a4986fa34ba272a9fce83fb33eef99470c55fd4 (patch)
tree4ebce6169629258f1a61775398cb0436189551c6 /testhal/common
parente66d39847114737997496308853b649564f9beb3 (diff)
downloadChibiOS-5a4986fa34ba272a9fce83fb33eef99470c55fd4.tar.gz
ChibiOS-5a4986fa34ba272a9fce83fb33eef99470c55fd4.tar.bz2
ChibiOS-5a4986fa34ba272a9fce83fb33eef99470c55fd4.zip
Unified IRQ Storm code.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7882 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'testhal/common')
-rw-r--r--testhal/common/irq_storm.c278
-rw-r--r--testhal/common/irq_storm.h166
2 files changed, 444 insertions, 0 deletions
diff --git a/testhal/common/irq_storm.c b/testhal/common/irq_storm.c
new file mode 100644
index 000000000..8d07e3f19
--- /dev/null
+++ b/testhal/common/irq_storm.c
@@ -0,0 +1,278 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file irq_storm.c
+ * @brief IRQ Storm stress test code.
+ *
+ * @addtogroup IRQ_STORM
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "chprintf.h"
+#include "irq_storm.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+#define MSG_SEND_LEFT (msg_t)0
+#define MSG_SEND_RIGHT (msg_t)1
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+static const irq_storm_config_t *config;
+
+static bool saturated;
+
+/*
+ * Mailboxes and buffers.
+ */
+static mailbox_t mb[IRQ_STORM_CFG_NUM_THREADS];
+static msg_t b[IRQ_STORM_CFG_NUM_THREADS][IRQ_STORM_CFG_MAILBOX_SIZE];
+
+/*
+ * Threads working areas.
+ */
+static THD_WORKING_AREA(irq_storm_thread_wa[IRQ_STORM_CFG_NUM_THREADS],
+ IRQ_STORM_CFG_STACK_SIZE);
+
+/*
+ * Pointers to threads.
+ */
+static thread_t *threads[IRQ_STORM_CFG_NUM_THREADS];
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/*
+ * Test worker threads.
+ */
+static THD_FUNCTION(irq_storm_thread, arg) {
+ static volatile unsigned x = 0;
+ static unsigned cnt = 0;
+ unsigned me = (unsigned)arg;
+ unsigned target;
+ unsigned r;
+ msg_t msg;
+
+ chRegSetThreadName("irq_storm");
+
+ /* Thread loop, until terminated.*/
+ while (chThdShouldTerminateX() == false) {
+
+ /* Waiting for a message.*/
+ chMBFetch(&mb[me], &msg, TIME_INFINITE);
+
+#if IRQ_STORM_CFG_RANDOMIZE != FALSE
+ /* Pseudo-random delay.*/
+ {
+ chSysLock();
+ r = rand() & 15;
+ chSysUnlock();
+ while (r--)
+ x++;
+ }
+#else /* IRQ_STORM_CFG_RANDOMIZE == FALSE */
+ /* Fixed delay.*/
+ {
+ r = me >> 4;
+ while (r--)
+ x++;
+ }
+#endif /* IRQ_STORM_CFG_RANDOMIZE == FALSE */
+
+ /* Deciding in which direction to re-send the message.*/
+ if (msg == MSG_SEND_LEFT)
+ target = me - 1;
+ else
+ target = me + 1;
+
+ if (target < IRQ_STORM_CFG_NUM_THREADS) {
+ /* If this thread is not at the end of a chain re-sending the message,
+ note this check works because the variable target is unsigned.*/
+ msg = chMBPost(&mb[target], msg, TIME_IMMEDIATE);
+ if (msg != MSG_OK)
+ saturated = TRUE;
+ }
+ else {
+ /* Provides a visual feedback about the system.*/
+ if (++cnt >= 500) {
+ cnt = 0;
+ palTogglePad(config->port, config->pad);
+ }
+ }
+ }
+}
+
+/**
+ * @brief GPT1 callback.
+ */
+void irq_storm_gpt1_cb(GPTDriver *gptp) {
+ msg_t msg;
+
+ (void)gptp;
+ chSysLockFromISR();
+ msg = chMBPostI(&mb[0], MSG_SEND_RIGHT);
+ if (msg != MSG_OK)
+ saturated = true;
+ chSysUnlockFromISR();
+}
+
+/**
+ * @brief GPT2 callback.
+ */
+void irq_storm_gpt2_cb(GPTDriver *gptp) {
+ msg_t msg;
+
+ (void)gptp;
+ chSysLockFromISR();
+ msg = chMBPostI(&mb[IRQ_STORM_CFG_NUM_THREADS - 1], MSG_SEND_LEFT);
+ if (msg != MSG_OK)
+ saturated = true;
+ chSysUnlockFromISR();
+}
+
+/**
+ * @brief IRQ storm execution.
+ *
+ * @param[in] cfg pointer to the test configuration structure
+ *
+ * @api
+ */
+void irq_storm_execute(const irq_storm_config_t *cfg) {
+ unsigned i;
+ gptcnt_t interval, threshold, worst;
+
+ /* Global configuration pointer.*/
+ config = cfg;
+
+ /* Starting timers using the stored configurations.*/
+ gptStart(cfg->gpt1p, cfg->gptcfg1p);
+ gptStart(cfg->gpt2p, cfg->gptcfg2p);
+
+ /*
+ * Initializes the mailboxes and creates the worker threads.
+ */
+ for (i = 0; i < IRQ_STORM_CFG_NUM_THREADS; i++) {
+ chMBObjectInit(&mb[i], b[i], IRQ_STORM_CFG_MAILBOX_SIZE);
+ threads[i] = chThdCreateStatic(irq_storm_thread_wa[i],
+ sizeof irq_storm_thread_wa[i],
+ IRQ_STORM_CFG_THREADS_PRIORITY,
+ irq_storm_thread,
+ (void *)i);
+ }
+
+ /* Printing environment information.*/
+ chprintf(cfg->out, "");
+ chprintf(cfg->out, "\r\n*** ChibiOS/RT IRQ-STORM long duration test\r\n***\r\n");
+ chprintf(cfg->out, "*** Kernel: %s\r\n", CH_KERNEL_VERSION);
+ chprintf(cfg->out, "*** Compiled: %s\r\n", __DATE__ " - " __TIME__);
+#ifdef PORT_COMPILER_NAME
+ chprintf(cfg->out, "*** Compiler: %s\r\n", PORT_COMPILER_NAME);
+#endif
+ chprintf(cfg->out, "*** Architecture: %s\r\n", PORT_ARCHITECTURE_NAME);
+#ifdef PORT_CORE_VARIANT_NAME
+ chprintf(cfg->out, "*** Core Variant: %s\r\n", PORT_CORE_VARIANT_NAME);
+#endif
+ chprintf(cfg->out, "*** System Clock: %d\r\n", cfg->sysclk);
+#ifdef PORT_INFO
+ chprintf(cfg->out, "*** Port Info: %s\r\n", PORT_INFO);
+#endif
+#ifdef PLATFORM_NAME
+ chprintf(cfg->out, "*** Platform: %s\r\n", PLATFORM_NAME);
+#endif
+#ifdef BOARD_NAME
+ chprintf(cfg->out, "*** Test Board: %s\r\n", BOARD_NAME);
+#endif
+ chprintf(cfg->out, "***\r\n");
+ chprintf(cfg->out, "*** Iterations: %d\r\n", IRQ_STORM_CFG_ITERATIONS);
+ chprintf(cfg->out, "*** Randomize: %d\r\n", IRQ_STORM_CFG_RANDOMIZE);
+ chprintf(cfg->out, "*** Threads: %d\r\n", IRQ_STORM_CFG_NUM_THREADS);
+ chprintf(cfg->out, "*** Mailbox size: %d\r\n\r\n", IRQ_STORM_CFG_MAILBOX_SIZE);
+
+ /* Test loop.*/
+ worst = 0;
+ for (i = 1; i <= IRQ_STORM_CFG_ITERATIONS; i++){
+
+ chprintf(cfg->out, "Iteration %d\r\n", i);
+ saturated = false;
+ threshold = 0;
+
+ /* Timer intervals starting at 2mS then decreased by 10% after each
+ cycle.*/
+ for (interval = 2000; interval >= 2; interval -= (interval + 9) / 10) {
+
+ /* Timers programmed slightly out of phase each other.*/
+ gptStartContinuous(cfg->gpt1p, interval - 1); /* Slightly out of phase.*/
+ gptStartContinuous(cfg->gpt2p, interval + 1); /* Slightly out of phase.*/
+
+ /* Storming for one second.*/
+ chThdSleepMilliseconds(1000);
+
+ /* Timers stopped.*/
+ gptStopTimer(cfg->gpt1p);
+ gptStopTimer(cfg->gpt2p);
+
+ /* Did the storm saturate the threads chain?*/
+ if (!saturated)
+ chprintf(cfg->out, ".");
+ else {
+ chprintf(cfg->out, "#");
+ if (threshold == 0)
+ threshold = interval;
+ break;
+ }
+ }
+ /* Gives threads a chance to empty the mailboxes before next cycle.*/
+ chThdSleepMilliseconds(20);
+ chprintf(cfg->out, "\r\nSaturated at %d uS\r\n\r\n", threshold);
+ if (threshold > worst)
+ worst = threshold;
+ }
+ gptStopTimer(&GPTD4);
+ gptStopTimer(&GPTD3);
+
+ chprintf(cfg->out, "Worst case at %d uS\r\n", worst);
+ chprintf(cfg->out, "\r\nTest Complete\r\n");
+
+ /* Terminating threads and cleaning up.*/
+ for (i = 0; i < IRQ_STORM_CFG_NUM_THREADS; i++) {
+ chThdTerminate(threads[i]);
+ chThdWait(threads[i]);
+ threads[i] = NULL;
+ }
+}
+
+/** @} */
diff --git a/testhal/common/irq_storm.h b/testhal/common/irq_storm.h
new file mode 100644
index 000000000..f465fd366
--- /dev/null
+++ b/testhal/common/irq_storm.h
@@ -0,0 +1,166 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file irq_storm.h
+ * @brief IRQ Storm stress test header.
+ *
+ * @addtogroup IRQ_STORM
+ * @{
+ */
+
+#ifndef _IRQ_STORM_H_
+#define _IRQ_STORM_H_
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+#ifndef RANDOMIZE
+#define RANDOMIZE FALSE
+#endif
+
+#ifndef ITERATIONS
+#define ITERATIONS 100
+#endif
+
+#ifndef NUM_THREADS
+#define NUM_THREADS 4
+#endif
+
+#ifndef MAILBOX_SIZE
+#define MAILBOX_SIZE 4
+#endif
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Timings randomization.
+ */
+#if !defined(IRQ_STORM_CFG_RANDOMIZE) || defined(__DOXYGEN__)
+#define IRQ_STORM_CFG_RANDOMIZE FALSE
+#endif
+
+/**
+ * @brief Number of test iterations.
+ */
+#if !defined(IRQ_STORM_CFG_ITERATIONS) || defined(__DOXYGEN__)
+#define IRQ_STORM_CFG_ITERATIONS 100
+#endif
+
+/**
+ * @brief Number of storm threads.
+ */
+#if !defined(IRQ_STORM_CFG_NUM_THREADS) || defined(__DOXYGEN__)
+#define IRQ_STORM_CFG_NUM_THREADS 4
+#endif
+
+/**
+ * @brief Priority of storm threads.
+ */
+#if !defined(IRQ_STORM_CFG_THREADS_PRIORITY) || defined(__DOXYGEN__)
+#define IRQ_STORM_CFG_THREADS_PRIORITY (tprio_t)(NORMALPRIO-20)
+#endif
+
+/**
+ * @brief Mailboxes size.
+ */
+#if !defined(IRQ_STORM_CFG_MAILBOX_SIZE) || defined(__DOXYGEN__)
+#define IRQ_STORM_CFG_MAILBOX_SIZE 4
+#endif
+
+/**
+ * @brief Stack size for worker threads.
+ */
+#if !defined(IRQ_STORM_CFG_STACK_SIZE) || defined(__DOXYGEN__)
+#define IRQ_STORM_CFG_STACK_SIZE 128
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+typedef struct {
+ /**
+ * @brief Stream for output.
+ */
+ BaseSequentialStream *out;
+ /**
+ * @brief LED port.
+ */
+ ioportid_t port;
+ /**
+ * @brief LED bit.
+ */
+ unsigned pad;
+ /**
+ * @brief GPT driver 1.
+ */
+ GPTDriver *gpt1p;
+ /**
+ * @brief GPT driver 2.
+ */
+ GPTDriver *gpt2p;
+ /**
+ * @brief GPT1 configuration 1.
+ */
+ const GPTConfig *gptcfg1p;
+ /**
+ * @brief GPT1 configuration 2.
+ */
+ const GPTConfig *gptcfg2p;
+ /**
+ * @brief System clock.
+ */
+ uint32_t sysclk;
+} irq_storm_config_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void irq_storm_gpt1_cb(GPTDriver *gptp);
+ void irq_storm_gpt2_cb(GPTDriver *gptp);
+ void irq_storm_execute(const irq_storm_config_t *cfg);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* _IRQ_STORM_H_ */
+
+/** @} */