diff options
Diffstat (limited to 'apps/system/ramtest/ramtest.c')
-rw-r--r-- | apps/system/ramtest/ramtest.c | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/apps/system/ramtest/ramtest.c b/apps/system/ramtest/ramtest.c new file mode 100644 index 000000000..120b1732c --- /dev/null +++ b/apps/system/ramtest/ramtest.c @@ -0,0 +1,483 @@ +/**************************************************************************** + * apps/system/ramtest/ramtest.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/progmem.h> + +#include <sys/types.h> + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sched.h> +#include <syslog.h> +#include <errno.h> + +#include <nuttx/usb/usbdev_trace.h> + +#ifdef CONFIG_SYSTEM_RAMTEST + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RAMTEST_PREFIX "RAMTest: " + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ramtest_s +{ + uint8_t width; + uintptr_t start; + size_t size; + uint32_t mask; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void show_usage(FAR const char *progname, int exitcode) +{ + printf("\nUsage: %s [-w|h|b] <hex-address> <decimal-size>\n", progname); + printf("\nWhere:\n"); + printf(" <hex-address> starting address of the test."); + printf(" <decimal-size> number of memory locations."); + printf(" -w Sets the width of a memory location to 32-bits."); + printf(" -h Sets the width of a memory location to 16-bits (default)."); + printf(" -b Sets the width of a memory location to 8-bits."); + exit(exitcode); +} + +static void parse_commandline(int argc, char **argv, FAR struct ramtest_s *info) +{ + FAR char *ptr; + int option; + + while ((option = getopt(argc, argv, "whb")) != ERROR) + { + if (option == 'w') + { + info->width = 32; + info->mask = 0xffffffff; + } + else if (option == 'h') + { + info->width = 16; + info->mask = 0x0000ffff; + } + else if (option == 'b') + { + info->width = 8; + info->mask = 0x000000ff; + } + else + { + printf(RAMTEST_PREFIX "Unrecognized option: '%c'\n", option); + show_usage(argv[0], EXIT_FAILURE); + } + } + + /* There should be two parameters remaining on the command line */ + + if (optind >= argc) + { + printf(RAMTEST_PREFIX "Missing required arguments\n"); + show_usage(argv[0], EXIT_FAILURE); + } + + info->start = (uintptr_t)strtoul(argv[optind], &ptr, 16); + if (*ptr != '\0'); + { + printf(RAMTEST_PREFIX "Invalid <hex-address>\n"); + show_usage(argv[0], EXIT_FAILURE); + } + + optind++; + + if (optind >= argc) + { + printf(RAMTEST_PREFIX "Missing <decimal-size>\n"); + show_usage(argv[0], EXIT_FAILURE); + } + + info->size = (size_t)strtoul(argv[optind], &ptr, 10); + if (*ptr != '\0'); + { + printf(RAMTEST_PREFIX "Invalid <decimal-size>\n"); + show_usage(argv[0], EXIT_FAILURE); + } + + if (optind != argc) + { + printf(RAMTEST_PREFIX "Too many arguments\n"); + show_usage(argv[0], EXIT_FAILURE); + } +} + +static void write_memory(FAR struct ramtest_s *info, uint32_t value) +{ + size_t i; + + if (info->width == 32) + { + uint32_t *ptr = (uint32_t*)info->start; + for (i = 0; i < info->size; i++) + { + *ptr++ = value; + } + } + else if (info->width == 16) + { + uint16_t *ptr = (uint16_t*)info->start; + for (i = 0; i < info->size; i++) + { + *ptr++ = (uint16_t)value; + } + } + else /* if (info->width == 8) */ + { + uint8_t *ptr = (uint8_t*)info->start; + for (i = 0; i < info->size; i++) + { + *ptr++ = (uint8_t)value; + } + } +} + +static void verify_memory(FAR struct ramtest_s *info, uint32_t value) +{ + size_t i; + + if (info->width == 32) + { + uint32_t *ptr = (uint32_t*)info->start; + for (i = 0; i < info->size; i++) + { + if (*ptr != value) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %08x Expected %08x\n", + ptr, *ptr, value); + } + + ptr++; + } + } + else if (info->width == 16) + { + uint16_t value16 = (uint16_t)(value & 0x0000ffff); + uint16_t *ptr = (uint16_t*)info->start; + for (i = 0; i < info->size; i++) + { + if (*ptr != value16) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %04x Expected %04x\n", + ptr, *ptr, value16); + } + + ptr++; + } + } + else /* if (info->width == 8) */ + { + uint8_t value8 = (uint8_t)(value & 0x000000ff); + uint8_t *ptr = (uint8_t*)info->start; + for (i = 0; i < info->size; i++) + { + if (*ptr != value8) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %02x Expected %02x\n", + ptr, *ptr, value8); + } + + ptr++; + } + } +} + +static void marching_ones(FAR struct ramtest_s *info) +{ + uint32_t pattern = 0x00000001; + + while (pattern != 0) + { + write_memory(info, pattern); + verify_memory(info, pattern); + pattern <<= 1; + pattern &= info->mask; + } +} + +static void marching_zeros(FAR struct ramtest_s *info) +{ + uint32_t pattern = 0xfffffffe; + + while (pattern != 0xffffffff) + { + write_memory(info, pattern); + verify_memory(info, pattern); + pattern <<= 1; + pattern |= 1; + pattern |= ~info->mask; + } +} + +static void write_memory2(FAR struct ramtest_s *info, uint32_t value_1, uint32_t value_2) +{ + size_t even_size = info->size & ~1; + size_t i; + + if (info->width == 32) + { + uint32_t *ptr = (uint32_t*)info->start; + for (i = 0; i < even_size; i += 2) + { + *ptr++ = value_1; + *ptr++ = value_2; + } + } + else if (info->width == 16) + { + uint16_t *ptr = (uint16_t*)info->start; + for (i = 0; i < even_size; i += 2) + { + *ptr++ = (uint16_t)value_1; + *ptr++ = (uint16_t)value_2; + } + } + else /* if (info->width == 8) */ + { + uint8_t *ptr = (uint8_t*)info->start; + for (i = 0; i < even_size; i += 2) + { + *ptr++ = (uint8_t)value_1; + *ptr++ = (uint8_t)value_2; + } + } +} + +static void verify_memory2(FAR struct ramtest_s *info, uint32_t value_1, uint32_t value_2) +{ + size_t even_size = info->size & ~1; + size_t i; + + if (info->width == 32) + { + uint32_t *ptr = (uint32_t*)info->start; + for (i = 0; i < even_size; i += 2) + { + if (ptr[0] != value_1 || ptr[1] != value_2) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %08x and %08x\n", + ptr, ptr[0], ptr[1]); + printf(RAMTEST_PREFIX " Expected: %08x and %08x\n", + value_1, value_2); + } + + ptr += 2; + } + } + else if (info->width == 16) + { + uint16_t value16_1 = (uint16_t)(value_1 & 0x0000ffff); + uint16_t value16_2 = (uint16_t)(value_2 & 0x0000ffff); + uint16_t *ptr = (uint16_t*)info->start; + for (i = 0; i < even_size; i += 2) + { + if (ptr[0] != value16_1 || ptr[1] != value16_2) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %04x and %04x\n", + ptr, ptr[0], ptr[1]); + printf(RAMTEST_PREFIX " Expected: %04x and %04x\n", + value16_1, value16_2); + } + + ptr += 2; + } + } + else /* if (info->width == 8) */ + { + uint8_t value8_1 = (uint8_t)(value_1 & 0x000000ff); + uint8_t value8_2 = (uint8_t)(value_2 & 0x000000ff); + uint8_t *ptr = (uint8_t*)info->start; + for (i = 0; i < even_size; i += 2) + { + if (ptr[0] != value8_1 || ptr[1] != value8_2) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %02x and %02x\n", + ptr, ptr[0], ptr[1]); + printf(RAMTEST_PREFIX " Expected: %02x and %02x\n", + value8_1, value8_2); + } + + ptr += 2; + } + } +} + +static void pattern_test(FAR struct ramtest_s *info, uint32_t pattern1, uint32_t pattern2) +{ + write_memory2(info, pattern1, pattern2); + verify_memory2(info, pattern1, pattern2); +} + +static void write_addrinaddr(FAR struct ramtest_s *info) +{ + size_t i; + + if (info->width == 32) + { + uint32_t *ptr = (uint32_t*)info->start; + for (i = 0; i < info->size; i++) + { + uint32_t value32 = (uint32_t)((uintptr_t)ptr); + *ptr++ = value32; + } + } + else if (info->width == 16) + { + uint16_t *ptr = (uint16_t*)info->start; + for (i = 0; i < info->size; i++) + { + uint16_t value16 = (uint16_t)((uintptr_t)ptr & 0x0000ffff); + *ptr++ = value16; + } + } + else /* if (info->width == 8) */ + { + uint8_t *ptr = (uint8_t*)info->start; + for (i = 0; i < info->size; i++) + { + uint8_t value8 = (uint8_t)((uintptr_t)ptr & 0x000000ff); + *ptr++ = value8; + } + } +} + +static void verify_addrinaddr(FAR struct ramtest_s *info) +{ + size_t i; + + if (info->width == 32) + { + uint32_t *ptr = (uint32_t*)info->start; + for (i = 0; i < info->size; i++) + { + uint32_t value32 = (uint32_t)((uintptr_t)ptr); + if (*ptr != value32) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %08x Expected %08x\n", + ptr, *ptr, value32); + } + + ptr++; + } + } + else if (info->width == 16) + { + uint16_t *ptr = (uint16_t*)info->start; + for (i = 0; i < info->size; i++) + { + uint16_t value16 = (uint16_t)((uintptr_t)ptr & 0x0000ffff); + if (*ptr != value16) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %04x Expected %04x\n", + ptr, *ptr, value16); + } + + ptr++; + } + } + else /* if (info->width == 8) */ + { + uint8_t *ptr = (uint8_t*)info->start; + for (i = 0; i < info->size; i++) + { + uint16_t value8 = (uint8_t)((uintptr_t)ptr & 0x000000ff); + if (*ptr != value8) + { + printf(RAMTEST_PREFIX "ERROR: Address %p Found: %02x Expected %02x\n", + ptr, *ptr, value8); + } + + ptr++; + } + } +} + +static void addr_in_addr(FAR struct ramtest_s *info) +{ + write_addrinaddr(info); + verify_addrinaddr(info); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int ramtest_main(int argc, char **argv) +{ + struct ramtest_s info; + + /* Setup defaults and parse the command line */ + + info.width = 16; + info.mask = 0x0000ffff; + parse_commandline(argc, argv, &info); + + /* Perform the memory tests */ + + marching_ones(&info); + marching_zeros(&info); + pattern_test(&info, 0x55555555, 0xaaaaaaaa); + pattern_test(&info, 0x66666666, 0x99999999); + pattern_test(&info, 0x33333333, 0xcccccccc); + addr_in_addr(&info); + return 0; +} + +#endif /* CONFIG_SYSTEM_RAMTEST */ |