aboutsummaryrefslogtreecommitdiffstats
path: root/os/various/memtest.cpp
diff options
context:
space:
mode:
authorbarthess <barthess@yandex.ru>2015-06-28 17:18:39 +0300
committerbarthess <barthess@yandex.ru>2015-06-28 17:18:39 +0300
commit1181dc9c2e8df44055bf080731f8abdd6207bc56 (patch)
tree61394b9fca94433dffaffc7d422c19e937dc2b59 /os/various/memtest.cpp
parentfce100680ecae2d19d1c7fb05a769a1968ade733 (diff)
downloadChibiOS-Contrib-1181dc9c2e8df44055bf080731f8abdd6207bc56.tar.gz
ChibiOS-Contrib-1181dc9c2e8df44055bf080731f8abdd6207bc56.tar.bz2
ChibiOS-Contrib-1181dc9c2e8df44055bf080731f8abdd6207bc56.zip
Memtest code moved to 'various' directory
Diffstat (limited to 'os/various/memtest.cpp')
-rw-r--r--os/various/memtest.cpp286
1 files changed, 286 insertions, 0 deletions
diff --git a/os/various/memtest.cpp b/os/various/memtest.cpp
new file mode 100644
index 0000000..49828ec
--- /dev/null
+++ b/os/various/memtest.cpp
@@ -0,0 +1,286 @@
+/*
+ ChibiOS/RT - Copyright (C) 2013-2014 Uladzimir Pylinsky aka barthess
+
+ 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.
+*/
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "memtest.hpp"
+
+/*
+ *
+ */
+template <typename T>
+class Generator {
+public:
+ Generator(void) : pattern(0) {;}
+ virtual T get(void) = 0;
+ virtual testtype get_type(void) = 0;
+ virtual void init(T seed) {
+ pattern = seed;
+ }
+protected:
+ T pattern;
+};
+
+/*
+ *
+ */
+template <typename T>
+class GeneratorWalkingOne : public Generator<T> {
+ T get(void) {
+ T ret = this->pattern;
+
+ this->pattern <<= 1;
+ if (0 == this->pattern)
+ this->pattern = 1;
+
+ return ret;
+ }
+
+ testtype get_type(void) {
+ return MEMTEST_WALKING_ONE;
+ }
+};
+
+/*
+ *
+ */
+template <typename T>
+class GeneratorWalkingZero : public Generator<T> {
+ T get(void) {
+ T ret = ~this->pattern;
+
+ this->pattern <<= 1;
+ if (0 == this->pattern)
+ this->pattern = 1;
+
+ return ret;
+ }
+
+ testtype get_type(void) {
+ return MEMTEST_WALKING_ZERO;
+ }
+};
+
+/*
+ *
+ */
+template <typename T>
+class GeneratorOwnAddress : public Generator<T> {
+ T get(void) {
+ T ret = this->pattern;
+ this->pattern++;
+ return ret;
+ }
+
+ testtype get_type(void) {
+ return MEMTEST_OWN_ADDRESS;
+ }
+};
+
+/*
+ *
+ */
+template <typename T>
+class GeneratorMovingInv : public Generator<T> {
+ T get(void) {
+ T ret = this->pattern;
+ this->pattern = ~this->pattern;
+ return ret;
+ }
+
+ testtype get_type(void) {
+ if ((this->pattern == 0) || ((this->pattern & 0xFF) == 0xFF))
+ return MEMTEST_MOVING_INVERSION_ZERO;
+ else
+ return MEMTEST_MOVING_INVERSION_55AA;
+ }
+};
+
+/*
+ *
+ */
+template <typename T>
+class GeneratorMovingInvRand : public Generator<T> {
+public:
+ GeneratorMovingInvRand(void) : step(0), prev(0){;}
+ void init(T seed) {
+ srand(seed);
+ step = 0;
+ prev = 0;
+ }
+
+ T get(void) {
+ T ret;
+ T mask = -1;
+ if ((step & 1) == 0) {
+ ret = rand() & mask;
+ prev = ret;
+ }
+ else {
+ ret = ~prev & mask;
+ }
+ step++;
+
+ return ret;
+ }
+
+ testtype get_type(void) {
+ return MEMTEST_MOVING_INVERSION_RAND;
+ }
+
+private:
+ size_t step;
+ T prev;
+};
+
+/*
+ *
+ */
+template <typename T>
+static void memtest_sequential(memtest_t *testp, Generator<T> &generator, T seed) {
+ const size_t steps = testp->size / sizeof(T);
+ size_t i;
+ T *mem = static_cast<T *>(testp->start);
+
+ /* fill ram */
+ generator.init(seed);
+ for (i=0; i<steps; i++)
+ mem[i] = generator.get();
+
+ /* read back and compare */
+ generator.init(seed);
+ for (i=0; i<steps; i++) {
+ if (mem[i] != generator.get()) {
+ testp->ecb(testp, generator.get_type(), i*sizeof(T));
+ return;
+ }
+ }
+}
+
+template <typename T>
+static void walking_one(memtest_t *testp) {
+ GeneratorWalkingOne<T> generator;
+ memtest_sequential<T>(testp, generator, 1);
+}
+
+template <typename T>
+static void walking_zero(memtest_t *testp) {
+ GeneratorWalkingZero<T> generator;
+ memtest_sequential<T>(testp, generator, 1);
+}
+
+template <typename T>
+static void own_address(memtest_t *testp) {
+ GeneratorOwnAddress<T> generator;
+ memtest_sequential<T>(testp, generator, 0);
+}
+
+template <typename T>
+static void moving_inversion_zero(memtest_t *testp) {
+ GeneratorMovingInv<T> generator;
+ T mask = -1;
+ memtest_sequential<T>(testp, generator, 0);
+ memtest_sequential<T>(testp, generator, 0xFFFFFFFF & mask);
+}
+
+template <typename T>
+static void moving_inversion_55aa(memtest_t *testp) {
+ GeneratorMovingInv<T> generator;
+ T mask = -1;
+ memtest_sequential<T>(testp, generator, 0x55555555 & mask);
+ memtest_sequential<T>(testp, generator, 0xAAAAAAAA & mask);
+}
+
+template <typename T>
+static void moving_inversion_rand(memtest_t *testp) {
+ GeneratorMovingInvRand<T> generator;
+ T mask = -1;
+ memtest_sequential<T>(testp, generator, testp->rand_seed & mask);
+}
+
+/*
+ *
+ */
+static void memtest_wrapper(memtest_t *testp,
+ void (*p_u8)(memtest_t *testp),
+ void (*p_u16)(memtest_t *testp),
+ void (*p_u32)(memtest_t *testp)) {
+ switch(testp->width) {
+ case MEMTEST_WIDTH_32:
+ p_u8(testp);
+ p_u16(testp);
+ p_u32(testp);
+ break;
+ case MEMTEST_WIDTH_16:
+ p_u8(testp);
+ p_u16(testp);
+ break;
+ case MEMTEST_WIDTH_8:
+ p_u8(testp);
+ break;
+ }
+}
+
+/*
+ *
+ */
+void memtest_run(memtest_t *testp, uint32_t testmask) {
+
+ if (testmask & MEMTEST_WALKING_ONE) {
+ memtest_wrapper(testp,
+ walking_one<uint8_t>,
+ walking_one<uint16_t>,
+ walking_one<uint32_t>);
+ }
+
+ if (testmask & MEMTEST_WALKING_ZERO) {
+ memtest_wrapper(testp,
+ walking_zero<uint8_t>,
+ walking_zero<uint16_t>,
+ walking_zero<uint32_t>);
+ }
+
+ if (testmask & MEMTEST_OWN_ADDRESS) {
+ memtest_wrapper(testp,
+ own_address<uint8_t>,
+ own_address<uint16_t>,
+ own_address<uint32_t>);
+ }
+
+ if (testmask & MEMTEST_MOVING_INVERSION_ZERO) {
+ memtest_wrapper(testp,
+ moving_inversion_zero<uint8_t>,
+ moving_inversion_zero<uint16_t>,
+ moving_inversion_zero<uint32_t>);
+ }
+
+ if (testmask & MEMTEST_MOVING_INVERSION_55AA) {
+ memtest_wrapper(testp,
+ moving_inversion_55aa<uint8_t>,
+ moving_inversion_55aa<uint16_t>,
+ moving_inversion_55aa<uint32_t>);
+ }
+
+ if (testmask & MEMTEST_MOVING_INVERSION_RAND) {
+ memtest_wrapper(testp,
+ moving_inversion_rand<uint8_t>,
+ moving_inversion_rand<uint16_t>,
+ moving_inversion_rand<uint32_t>);
+ }
+}
+