/* 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 #include #include #include "memtest.hpp" /* * */ template 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 class GeneratorWalkingOne : public Generator { 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 class GeneratorWalkingZero : public Generator { 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 class GeneratorOwnAddress : public Generator { T get(void) { T ret = this->pattern; this->pattern++; return ret; } testtype get_type(void) { return MEMTEST_OWN_ADDRESS; } }; /* * */ template class GeneratorMovingInv : public Generator { 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 class GeneratorMovingInvRand : public Generator { 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 static void memtest_sequential(memtest_t *testp, Generator &generator, T seed) { const size_t steps = testp->size / sizeof(T); size_t i; T *mem = static_cast(testp->start); /* fill ram */ generator.init(seed); for (i=0; iecb(testp, generator.get_type(), i*sizeof(T)); return; } } } template static void walking_one(memtest_t *testp) { GeneratorWalkingOne generator; memtest_sequential(testp, generator, 1); } template static void walking_zero(memtest_t *testp) { GeneratorWalkingZero generator; memtest_sequential(testp, generator, 1); } template static void own_address(memtest_t *testp) { GeneratorOwnAddress generator; memtest_sequential(testp, generator, 0); } template static void moving_inversion_zero(memtest_t *testp) { GeneratorMovingInv generator; T mask = -1; memtest_sequential(testp, generator, 0); memtest_sequential(testp, generator, 0xFFFFFFFF & mask); } template static void moving_inversion_55aa(memtest_t *testp) { GeneratorMovingInv generator; T mask = -1; memtest_sequential(testp, generator, 0x55555555 & mask); memtest_sequential(testp, generator, 0xAAAAAAAA & mask); } template static void moving_inversion_rand(memtest_t *testp) { GeneratorMovingInvRand generator; T mask = -1; memtest_sequential(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, walking_one, walking_one); } if (testmask & MEMTEST_WALKING_ZERO) { memtest_wrapper(testp, walking_zero, walking_zero, walking_zero); } if (testmask & MEMTEST_OWN_ADDRESS) { memtest_wrapper(testp, own_address, own_address, own_address); } if (testmask & MEMTEST_MOVING_INVERSION_ZERO) { memtest_wrapper(testp, moving_inversion_zero, moving_inversion_zero, moving_inversion_zero); } if (testmask & MEMTEST_MOVING_INVERSION_55AA) { memtest_wrapper(testp, moving_inversion_55aa, moving_inversion_55aa, moving_inversion_55aa); } if (testmask & MEMTEST_MOVING_INVERSION_RAND) { memtest_wrapper(testp, moving_inversion_rand, moving_inversion_rand, moving_inversion_rand); } }