FSMC_SRAM testhal. Added memtest and membench.
This commit is contained in:
parent
a1822c490d
commit
33f1b2541e
|
@ -87,8 +87,7 @@ include $(CHIBIOS)/community/os/hal/ports/STM32/STM32F4xx/platform.mk
|
||||||
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
|
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
|
||||||
include $(CHIBIOS)/os/rt/rt.mk
|
include $(CHIBIOS)/os/rt/rt.mk
|
||||||
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_stm32f4xx.mk
|
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_stm32f4xx.mk
|
||||||
include $(CHIBIOS)/test/rt/test.mk
|
include $(CHIBIOS)/os/various/cpp_wrappers/chcpp.mk
|
||||||
|
|
||||||
|
|
||||||
# Define linker script file here
|
# Define linker script file here
|
||||||
LDSCRIPT= $(PORTLD)/STM32F407xG.ld
|
LDSCRIPT= $(PORTLD)/STM32F407xG.ld
|
||||||
|
@ -97,15 +96,17 @@ LDSCRIPT= $(PORTLD)/STM32F407xG.ld
|
||||||
# setting.
|
# setting.
|
||||||
CSRC = $(PORTSRC) \
|
CSRC = $(PORTSRC) \
|
||||||
$(KERNSRC) \
|
$(KERNSRC) \
|
||||||
$(TESTSRC) \
|
|
||||||
$(HALSRC) \
|
$(HALSRC) \
|
||||||
|
$(OSALSRC) \
|
||||||
$(PLATFORMSRC) \
|
$(PLATFORMSRC) \
|
||||||
$(BOARDSRC) \
|
$(BOARDSRC) \
|
||||||
main.c
|
main.c \
|
||||||
|
membench.c
|
||||||
|
|
||||||
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
||||||
# setting.
|
# setting.
|
||||||
CPPSRC =
|
CPPSRC = $(CHCPPSRC) \
|
||||||
|
memtest.cpp
|
||||||
|
|
||||||
# C sources to be compiled in ARM mode regardless of the global setting.
|
# C sources to be compiled in ARM mode regardless of the global setting.
|
||||||
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
|
||||||
|
@ -132,9 +133,9 @@ ASMSRC = $(PORTASM)
|
||||||
|
|
||||||
INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
|
INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
|
||||||
$(HALINC) $(OSALINC) $(PLATFORMINC) $(BOARDINC) \
|
$(HALINC) $(OSALINC) $(PLATFORMINC) $(BOARDINC) \
|
||||||
|
$(CHIBIOS)/os/various/cpp_wrappers \
|
||||||
$(CHIBIOS)/os/various
|
$(CHIBIOS)/os/various
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Project, sources and paths
|
# Project, sources and paths
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
|
@ -14,24 +14,20 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
TODO:
|
|
||||||
write memtest function using ideas from http://www.memtest86.com/technical.htm
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
|
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
#include "fsmc_sram.h"
|
#include "fsmc_sram.h"
|
||||||
|
#include "membench.h"
|
||||||
|
#include "memtest.hpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
#define USE_INFINITE_MEMTEST FALSE
|
#define SRAM_START ((void *)FSMC_Bank1_4_MAP)
|
||||||
|
#define SRAM_SIZE (512 * 1024)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
|
@ -45,27 +41,58 @@ write memtest function using ideas from http://www.memtest86.com/technical.htm
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void mem_error_cb(memtest_t *memp, testtype_t e, size_t address);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* GLOBAL VARIABLES
|
* GLOBAL VARIABLES
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
static uint32_t sram_check_buf[16 * 1024];
|
|
||||||
static uint32_t *sram_start = (uint32_t *)FSMC_Bank1_4_MAP;
|
|
||||||
static const size_t sram_size = 524288;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SRAM driver configuration structure.
|
* SRAM driver configuration structure.
|
||||||
*/
|
*/
|
||||||
static const SRAMConfig sram_cfg = {
|
static const SRAMConfig sram_cfg = {
|
||||||
.btr = 2 << 8
|
2 << 8
|
||||||
};
|
};
|
||||||
|
|
||||||
/* benchmarking results in MiB/S */
|
/*
|
||||||
volatile double memset_speed_ext;
|
*
|
||||||
volatile double memset_speed_int;
|
*/
|
||||||
volatile double memcpy_speed_ext2int;
|
static memtest_t memtest_struct = {
|
||||||
volatile double memcpy_speed_int2ext;
|
SRAM_START,
|
||||||
|
SRAM_SIZE,
|
||||||
|
MEMTEST_WIDTH_16,
|
||||||
|
mem_error_cb,
|
||||||
|
42
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static membench_t membench_ext = {
|
||||||
|
SRAM_START,
|
||||||
|
SRAM_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static uint8_t int_buf[64*1024];
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static membench_t membench_int = {
|
||||||
|
int_buf,
|
||||||
|
sizeof(int_buf),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static membench_result_t membench_result_ext2int;
|
||||||
|
static membench_result_t membench_result_int2ext;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
|
@ -74,58 +101,53 @@ volatile double memcpy_speed_int2ext;
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void sram_benchmark(void){
|
|
||||||
|
|
||||||
size_t i=0;
|
static inline void red_led_on(void) {palSetPad(GPIOI, GPIOI_LED_R);}
|
||||||
time_measurement_t mem_tmu;
|
static inline void red_led_off(void) {palClearPad(GPIOI, GPIOI_LED_R);}
|
||||||
|
static inline void green_led_on(void) {palSetPad(GPIOI, GPIOI_LED_G);}
|
||||||
|
static inline void green_led_off(void) {palClearPad(GPIOI, GPIOI_LED_G);}
|
||||||
|
static inline void green_led_toggle(void) {palTogglePad(GPIOI, GPIOI_LED_G);}
|
||||||
|
|
||||||
/* memset speed ext */
|
static void mem_error_cb(memtest_t *memp, testtype_t e, size_t address) {
|
||||||
chTMObjectInit(&mem_tmu);
|
(void)memp;
|
||||||
chTMStartMeasurementX(&mem_tmu);
|
(void)e;
|
||||||
memset(sram_start, 0x55, sram_size);
|
(void)address;
|
||||||
memset(sram_start, 0x00, sram_size);
|
|
||||||
chTMStopMeasurementX(&mem_tmu);
|
|
||||||
memset_speed_ext = 1 / (mem_tmu.cumulative / (double)STM32_SYSCLK);
|
|
||||||
|
|
||||||
/* memset speed int */
|
green_led_off();
|
||||||
chTMObjectInit(&mem_tmu);
|
red_led_on();
|
||||||
chTMStartMeasurementX(&mem_tmu);
|
osalSysHalt("Memory broken");
|
||||||
for (i=0; i<16; i++)
|
|
||||||
memset(sram_check_buf, i, sizeof(sram_check_buf));
|
|
||||||
chTMStopMeasurementX(&mem_tmu);
|
|
||||||
memset_speed_int = 1 / (mem_tmu.cumulative / (double)STM32_SYSCLK);
|
|
||||||
|
|
||||||
/* memcpy ext2int */
|
|
||||||
chTMObjectInit(&mem_tmu);
|
|
||||||
chTMStartMeasurementX(&mem_tmu);
|
|
||||||
for (i=0; i<16; i++)
|
|
||||||
memcpy(sram_check_buf, sram_start+ i * sizeof(sram_check_buf), sizeof(sram_check_buf));
|
|
||||||
chTMStopMeasurementX(&mem_tmu);
|
|
||||||
memcpy_speed_ext2int = 1 / (mem_tmu.cumulative / (double)STM32_SYSCLK);
|
|
||||||
|
|
||||||
/* memcpy int2ext */
|
|
||||||
chTMObjectInit(&mem_tmu);
|
|
||||||
memset(sram_check_buf, 0xAA, sizeof(sram_check_buf));
|
|
||||||
chTMStartMeasurementX(&mem_tmu);
|
|
||||||
for (i=0; i<16; i++)
|
|
||||||
memcpy(sram_start + i * sizeof(sram_check_buf), sram_check_buf, sizeof(sram_check_buf));
|
|
||||||
chTMStopMeasurementX(&mem_tmu);
|
|
||||||
memcpy_speed_int2ext = 1 / (mem_tmu.cumulative / (double)STM32_SYSCLK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if USE_INFINITE_MEMTEST
|
static void memtest(void) {
|
||||||
static void memstest(void){
|
|
||||||
|
red_led_off();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
;
|
memtest_struct.width = MEMTEST_WIDTH_16;
|
||||||
|
memtest_struct.rand_seed = chSysGetRealtimeCounterX();
|
||||||
|
memtest_run(&memtest_struct, MEMTEST_RUN_ALL);
|
||||||
|
|
||||||
|
memtest_struct.width = MEMTEST_WIDTH_8;
|
||||||
|
memtest_struct.rand_seed = chSysGetRealtimeCounterX();
|
||||||
|
memtest_run(&memtest_struct, MEMTEST_RUN_ALL);
|
||||||
|
|
||||||
|
green_led_toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
green_led_on();
|
||||||
|
green_led_off();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void membench(void) {
|
||||||
|
membench_run(&membench_ext, &membench_int, &membench_result_int2ext);
|
||||||
|
membench_run(&membench_int, &membench_ext, &membench_result_ext2int);
|
||||||
}
|
}
|
||||||
#endif /* USE_INFINITE_MEMTEST */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
|
@ -150,11 +172,9 @@ int main(void) {
|
||||||
|
|
||||||
fsmcSramInit();
|
fsmcSramInit();
|
||||||
fsmcSramStart(&SRAMD4, &sram_cfg);
|
fsmcSramStart(&SRAMD4, &sram_cfg);
|
||||||
sram_benchmark();
|
|
||||||
|
|
||||||
#if USE_INFINITE_MEMTEST
|
membench();
|
||||||
memtest();
|
memtest();
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Normal main() thread activity, in this demo it does nothing.
|
* Normal main() thread activity, in this demo it does nothing.
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
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 <string.h>
|
||||||
|
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#include "membench.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************************
|
||||||
|
* DEFINES
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************************
|
||||||
|
* EXTERNS
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************************
|
||||||
|
* PROTOTYPES
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************************
|
||||||
|
* GLOBAL VARIABLES
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
volatile int warning_suppressor;
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************************
|
||||||
|
******************************************************************************
|
||||||
|
* LOCAL FUNCTIONS
|
||||||
|
******************************************************************************
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Calculates memory access time in MiB.
|
||||||
|
*/
|
||||||
|
double speed(const time_measurement_t *tmu, size_t len) {
|
||||||
|
double size; // MiB
|
||||||
|
double time; // sec
|
||||||
|
|
||||||
|
size = len;
|
||||||
|
size /= 1024 * 1024;
|
||||||
|
|
||||||
|
time = tmu->last;
|
||||||
|
time /= STM32_SYSCLK;
|
||||||
|
|
||||||
|
return size / time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
******************************************************************************
|
||||||
|
* EXPORTED FUNCTIONS
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void membench_run(membench_t *dest, const membench_t *src,
|
||||||
|
membench_result_t *result) {
|
||||||
|
time_measurement_t mem_tmu;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (src->size < dest->size)
|
||||||
|
len = src->size;
|
||||||
|
else
|
||||||
|
len = dest->size;
|
||||||
|
|
||||||
|
/* memset */
|
||||||
|
chTMObjectInit(&mem_tmu);
|
||||||
|
chTMStartMeasurementX(&mem_tmu);
|
||||||
|
memset(dest->start, 0x55, dest->size);
|
||||||
|
chTMStopMeasurementX(&mem_tmu);
|
||||||
|
result->memset_spd = speed(&mem_tmu, dest->size);
|
||||||
|
|
||||||
|
/* memcpy */
|
||||||
|
chTMObjectInit(&mem_tmu);
|
||||||
|
chTMStartMeasurementX(&mem_tmu);
|
||||||
|
memcpy(dest->start, src->start, len);
|
||||||
|
chTMStopMeasurementX(&mem_tmu);
|
||||||
|
result->memcpy_spd = speed(&mem_tmu, len);
|
||||||
|
|
||||||
|
/* memcmp */
|
||||||
|
chTMObjectInit(&mem_tmu);
|
||||||
|
chTMStartMeasurementX(&mem_tmu);
|
||||||
|
warning_suppressor = memcmp(dest->start, src->start, len);
|
||||||
|
chTMStopMeasurementX(&mem_tmu);
|
||||||
|
result->memcmp_spd = speed(&mem_tmu, len);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef MEMBENCH_H_
|
||||||
|
#define MEMBENCH_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
void *start;
|
||||||
|
size_t size;
|
||||||
|
} membench_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
double memset_spd;
|
||||||
|
double memcpy_spd;
|
||||||
|
double memcmp_spd;
|
||||||
|
} membench_result_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void membench_run(membench_t *dest, const membench_t *src, membench_result_t *ret);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MEMBENCH_H_ */
|
|
@ -0,0 +1,226 @@
|
||||||
|
#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 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class GeneratorOwnAddress : public Generator<T> {
|
||||||
|
T get(void) {
|
||||||
|
T ret = this->pattern;
|
||||||
|
this->pattern++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class GeneratorMovingInv : public Generator<T> {
|
||||||
|
T get(void) {
|
||||||
|
T ret = this->pattern;
|
||||||
|
this->pattern = ~this->pattern;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class GeneratorMovingInvRand : public Generator<T> {
|
||||||
|
public:
|
||||||
|
GeneratorMovingInvRand(void) : step(0), prev(0){;}
|
||||||
|
void init(size_t seed) {
|
||||||
|
srand(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
T get(void) {
|
||||||
|
T ret;
|
||||||
|
if ((step & 1) == 0) {
|
||||||
|
ret = rand();
|
||||||
|
prev = ret;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = ~prev;
|
||||||
|
}
|
||||||
|
step++;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t step;
|
||||||
|
T prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static void memtest_sequential(memtest_t *memp, Generator<T> &generator, T seed) {
|
||||||
|
const size_t steps = memp->size / sizeof(T);
|
||||||
|
size_t i;
|
||||||
|
T *mem = static_cast<T *>(memp->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()) {
|
||||||
|
memp->ecb(memp, MEMTEST_WALKING_ONE, i*sizeof(T));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void walking_one(memtest_t *memp) {
|
||||||
|
GeneratorWalkingOne<T> generator;
|
||||||
|
memtest_sequential<T>(memp, generator, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void walking_zero(memtest_t *memp) {
|
||||||
|
GeneratorWalkingZero<T> generator;
|
||||||
|
memtest_sequential<T>(memp, generator, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void own_address(memtest_t *memp) {
|
||||||
|
GeneratorOwnAddress<T> generator;
|
||||||
|
memtest_sequential<T>(memp, generator, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void moving_inversion(memtest_t *memp) {
|
||||||
|
GeneratorMovingInv<T> generator;
|
||||||
|
memtest_sequential<T>(memp, generator, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void moving_inversion_rand(memtest_t *memp) {
|
||||||
|
GeneratorMovingInvRand<T> generator;
|
||||||
|
memtest_sequential<T>(memp, generator, memp->rand_seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void memtest_wrapper(memtest_t *memp,
|
||||||
|
void (*p_u8)(memtest_t *memp),
|
||||||
|
void (*p_u16)(memtest_t *memp),
|
||||||
|
void (*p_u32)(memtest_t *memp)) {
|
||||||
|
switch(memp->width){
|
||||||
|
case MEMTEST_WIDTH_32:
|
||||||
|
p_u32(memp);
|
||||||
|
p_u16(memp);
|
||||||
|
p_u8(memp);
|
||||||
|
break;
|
||||||
|
case MEMTEST_WIDTH_16:
|
||||||
|
p_u16(memp);
|
||||||
|
p_u8(memp);
|
||||||
|
break;
|
||||||
|
case MEMTEST_WIDTH_8:
|
||||||
|
p_u8(memp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void memtest_run(memtest_t *memp, uint32_t testmask) {
|
||||||
|
|
||||||
|
if ((testmask & MEMTEST_WALKING_ONE) == MEMTEST_WALKING_ONE) {
|
||||||
|
memtest_wrapper(memp,
|
||||||
|
walking_one<uint32_t>,
|
||||||
|
walking_one<uint16_t>,
|
||||||
|
walking_one<uint8_t>);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((testmask & MEMTEST_WALKING_ZERO) == MEMTEST_WALKING_ZERO) {
|
||||||
|
memtest_wrapper(memp,
|
||||||
|
walking_zero<uint32_t>,
|
||||||
|
walking_zero<uint16_t>,
|
||||||
|
walking_zero<uint8_t>);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((testmask & MEMTEST_OWN_ADDRESS) == MEMTEST_OWN_ADDRESS) {
|
||||||
|
memtest_wrapper(memp,
|
||||||
|
own_address<uint32_t>,
|
||||||
|
own_address<uint16_t>,
|
||||||
|
own_address<uint8_t>);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((testmask & MEMTEST_MOVING_INVERSION) == MEMTEST_MOVING_INVERSION) {
|
||||||
|
memtest_wrapper(memp,
|
||||||
|
moving_inversion<uint32_t>,
|
||||||
|
moving_inversion<uint16_t>,
|
||||||
|
moving_inversion<uint8_t>);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((testmask & MEMTEST_MOVING_INVERSION_RAND) == MEMTEST_MOVING_INVERSION_RAND) {
|
||||||
|
memtest_wrapper(memp,
|
||||||
|
moving_inversion_rand<uint32_t>,
|
||||||
|
moving_inversion_rand<uint16_t>,
|
||||||
|
moving_inversion_rand<uint8_t>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef MEMTEST_HPP_
|
||||||
|
#define MEMTEST_HPP_
|
||||||
|
|
||||||
|
#define MEMTEST_WALKING_ONE (1 << 0)
|
||||||
|
#define MEMTEST_WALKING_ZERO (1 << 1)
|
||||||
|
#define MEMTEST_OWN_ADDRESS (1 << 2)
|
||||||
|
#define MEMTEST_MOVING_INVERSION (1 << 3)
|
||||||
|
#define MEMTEST_MOVING_INVERSION_RAND (1 << 4)
|
||||||
|
|
||||||
|
#define MEMTEST_RUN_ALL (MEMTEST_WALKING_ONE | \
|
||||||
|
MEMTEST_WALKING_ZERO | \
|
||||||
|
MEMTEST_OWN_ADDRESS | \
|
||||||
|
MEMTEST_MOVING_INVERSION | \
|
||||||
|
MEMTEST_MOVING_INVERSION_RAND)
|
||||||
|
|
||||||
|
typedef struct memtest_t memtest_t;
|
||||||
|
typedef uint32_t testtype_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Error call back.
|
||||||
|
*/
|
||||||
|
typedef void (*memtestecb_t)(memtest_t *memp, testtype_t e, size_t address);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
MEMTEST_WIDTH_8,
|
||||||
|
MEMTEST_WIDTH_16,
|
||||||
|
MEMTEST_WIDTH_32
|
||||||
|
} memtest_bus_width_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct memtest_t {
|
||||||
|
void *start;
|
||||||
|
size_t size;
|
||||||
|
memtest_bus_width_t width;
|
||||||
|
memtestecb_t ecb;
|
||||||
|
unsigned int rand_seed;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void memtest_run(memtest_t *memp, uint32_t testmask);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MEMTEST_HPP_ */
|
Loading…
Reference in New Issue