summaryrefslogtreecommitdiff
path: root/ecos/packages/devs/flash/spi/m25pxx/current/test/m25pxx_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecos/packages/devs/flash/spi/m25pxx/current/test/m25pxx_test.c')
-rw-r--r--ecos/packages/devs/flash/spi/m25pxx/current/test/m25pxx_test.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/ecos/packages/devs/flash/spi/m25pxx/current/test/m25pxx_test.c b/ecos/packages/devs/flash/spi/m25pxx/current/test/m25pxx_test.c
new file mode 100644
index 0000000..587155e
--- /dev/null
+++ b/ecos/packages/devs/flash/spi/m25pxx/current/test/m25pxx_test.c
@@ -0,0 +1,396 @@
+//=============================================================================
+//
+// m25pxx_test.c
+//
+// SPI flash driver tests for Numonyx M25Pxx devices and compatibles.
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later
+// version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Chris Holgate
+// Date: 2008-12-22
+// Purpose: Numonyx M25Pxx SPI flash driver stress tests.
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/system.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h> // Test macros
+#include <cyg/infra/cyg_ass.h> // Assertion macros
+#include <cyg/infra/diag.h> // Diagnostic output
+
+#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
+#include <cyg/hal/hal_if.h>
+#include <cyg/kernel/kapi.h>
+
+#include <cyg/io/spi.h>
+#include <cyg/io/flash.h>
+#include <cyg/io/m25pxx.h>
+
+#include <string.h>
+
+#include CYGHWR_MEMORY_LAYOUT_H
+
+//-----------------------------------------------------------------------------
+// Set up the SPI intertface on the ST STM3210E eval board for the STM32. The
+// M25PXX device is connected to SPI bus 1. To configure the board for this
+// test, jumper JP3 must be open and SPI1 should be set up in configtool so
+// that chip select 1 corresponds to GPIO number 18 (PB2) and 50MHz I/O is
+// enabled. If the data area is in external RAM, SPI1 must be configured with
+// bounce buffers of at least 256 bytes and the M25PXX read data block size
+// should be set to the same size as the bounce buffers.
+
+#ifdef CYGPKG_HAL_CORTEXM_STM32_STM3210E_EVAL
+#include <cyg/io/spi_stm32.h>
+
+CYG_DEVS_SPI_CORTEXM_STM32_DEVICE (
+ m25pxx_spi_device, 1, 0, false, 0, 0, 25000000, 1, 1, 1
+);
+
+#endif
+
+//-----------------------------------------------------------------------------
+// Instantiate the M25Pxx device driver.
+
+CYG_DEVS_FLASH_SPI_M25PXX_DRIVER (
+ m25pxx_flash_device, 0, &m25pxx_spi_device
+);
+
+//-----------------------------------------------------------------------------
+// Thread data structures.
+
+static cyg_uint32 stack [CYGNUM_HAL_STACK_SIZE_TYPICAL / 4];
+static cyg_thread thread_data;
+static cyg_handle_t thread_handle;
+
+//-----------------------------------------------------------------------------
+// Data transfer buffers.
+
+#define BUF_SIZE 1024
+
+static cyg_uint8 wbuf [BUF_SIZE];
+static cyg_uint8 rbuf [BUF_SIZE];
+
+//-----------------------------------------------------------------------------
+// Print out version information.
+
+void do_version (void)
+{
+ char *version = CYGACC_CALL_IF_MONITOR_VERSION();
+ if (version != NULL) diag_printf("%s", version);
+#ifdef HAL_PLATFORM_CPU
+ diag_printf("Platform: %s (%s) %s\n", HAL_PLATFORM_BOARD, HAL_PLATFORM_CPU, HAL_PLATFORM_EXTRA);
+#endif
+ diag_printf("RAM: %p-%p, ", (void*)(CYGMEM_REGION_ram), (void*)(CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - 1));
+ diag_printf("(HEAP: %p-%p)\n", (void*)(CYGMEM_SECTION_heap1), (void*)(CYGMEM_SECTION_heap1 + CYGMEM_SECTION_heap1_SIZE - 1));
+}
+
+//-----------------------------------------------------------------------------
+// Run checkerboard and inverse checkerboard writes over each sector in turn.
+
+cyg_uint32 run_test_1
+ (void)
+{
+ int status;
+ cyg_uint32 i, j;
+ cyg_uint32 errors = 0;
+ cyg_flashaddr_t base_addr, err_addr;
+
+ diag_printf ("Test 1 - write and verify checkerboard and inverse checkerboard.\n");
+
+ // Iterate over all flash sectors.
+ for (i = 0; i < m25pxx_flash_device.block_info->blocks; i++) {
+ base_addr = m25pxx_flash_device.start + (i * m25pxx_flash_device.block_info->block_size);
+
+ // Erase block.
+ status = cyg_flash_erase (base_addr, 1, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash erase error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+
+ // Set up buffer with checkerboard.
+ for (j = 0; j < BUF_SIZE;) {
+ wbuf [j++] = 0x55;
+ wbuf [j++] = 0xAA;
+ }
+
+ // Write the checkerboard to the entire sector.
+ for (j = 0; j < m25pxx_flash_device.block_info->block_size; j += BUF_SIZE) {
+ status = cyg_flash_program (base_addr + j, wbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash write error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ }
+
+ // Read back the checkerboard and verify.
+ for (j = 0; j < m25pxx_flash_device.block_info->block_size; j += BUF_SIZE) {
+ status = cyg_flash_read (base_addr + j, rbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash read error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ else if (memcmp (rbuf, wbuf, BUF_SIZE) != 0) {
+ diag_printf ("Flash read data corruption (0x%08X - 0x%08X).\n", base_addr + j, base_addr + j + BUF_SIZE - 1);
+ errors ++;
+ }
+ }
+
+ // Erase block.
+ status = cyg_flash_erase (base_addr, 1, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash erase error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+
+ // Set up buffer with inverse checkerboard.
+ for (j = 0; j < BUF_SIZE;) {
+ wbuf [j++] = 0xAA;
+ wbuf [j++] = 0x55;
+ }
+
+ // Write the checkerboard to the entire sector.
+ for (j = 0; j < m25pxx_flash_device.block_info->block_size; j += BUF_SIZE) {
+ status = cyg_flash_program (base_addr + j, wbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash write error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ }
+
+ // Read back the checkerboard and verify.
+ for (j = 0; j < m25pxx_flash_device.block_info->block_size; j += BUF_SIZE) {
+ status = cyg_flash_read (base_addr + j, rbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash read error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ else if (memcmp (rbuf, wbuf, BUF_SIZE) != 0) {
+ diag_printf ("Flash read data corruption (0x%08X - 0x%08X).\n", base_addr + j, base_addr + j + BUF_SIZE - 1);
+ errors ++;
+ }
+ }
+ }
+ return errors;
+}
+
+//-----------------------------------------------------------------------------
+// Write and verify counting sequence over all device.
+
+cyg_uint32 run_test_2
+ (void)
+{
+ int status;
+ cyg_uint32 i, j;
+ cyg_uint32 errors = 0;
+ cyg_flashaddr_t base_addr, err_addr;
+
+ diag_printf ("Test 2 - write and verify counting sequence.\n");
+
+ // Erase all flash sectors.
+ for (i = 0; i < m25pxx_flash_device.block_info->blocks; i++) {
+ base_addr = m25pxx_flash_device.start + (i * m25pxx_flash_device.block_info->block_size);
+
+ // Erase block.
+ status = cyg_flash_erase (base_addr, 1, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash erase error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ }
+
+ // Write counting sequence.
+ base_addr = m25pxx_flash_device.start;
+ for (i = 0; i < (m25pxx_flash_device.end - m25pxx_flash_device.start) / 4;) {
+ for (j = 0; j < BUF_SIZE;) {
+ wbuf [j++] = (cyg_uint8) ((i >> 0) & 0xFF);
+ wbuf [j++] = (cyg_uint8) ((i >> 8) & 0xFF);
+ wbuf [j++] = (cyg_uint8) ((i >> 16) & 0xFF);
+ wbuf [j++] = (cyg_uint8) ((i >> 24) & 0xFF);
+ i++;
+ }
+ status = cyg_flash_program (base_addr, wbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash write error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ base_addr += BUF_SIZE;
+ }
+
+ // Verify counting sequence.
+ base_addr = m25pxx_flash_device.start;
+ for (i = 0; i < (m25pxx_flash_device.end - m25pxx_flash_device.start) / 4;) {
+ for (j = 0; j < BUF_SIZE;) {
+ wbuf [j++] = (cyg_uint8) ((i >> 0) & 0xFF);
+ wbuf [j++] = (cyg_uint8) ((i >> 8) & 0xFF);
+ wbuf [j++] = (cyg_uint8) ((i >> 16) & 0xFF);
+ wbuf [j++] = (cyg_uint8) ((i >> 24) & 0xFF);
+ i++;
+ }
+ status = cyg_flash_read (base_addr, rbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash read error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ else if (memcmp (rbuf, wbuf, BUF_SIZE) != 0) {
+ diag_printf ("Flash read data corruption (0x%08X - 0x%08X).\n", base_addr, base_addr + BUF_SIZE - 1);
+ errors ++;
+ }
+ base_addr += BUF_SIZE;
+ }
+ return errors;
+}
+
+//-----------------------------------------------------------------------------
+// Perform non-aligned buffer read/write tests, spanning sector boundaries.
+
+cyg_uint32 run_test_3
+ (void)
+{
+ int status;
+ cyg_uint32 i, count;
+ cyg_uint32 errors = 0;
+ cyg_flashaddr_t base_addr, err_addr;
+
+ diag_printf ("Test 3 - test non-aligned writes and reads.\n");
+
+ // Fill the write buffer with a basic counting sequence.
+ count = 0;
+ for (i = 0; i < BUF_SIZE;) {
+ wbuf [i++] = (cyg_uint8) ((count >> 0) & 0xFF);
+ wbuf [i++] = (cyg_uint8) ((count >> 8) & 0xFF);
+ count++;
+ }
+
+ // Assuming 256 byte pages gives 256 possible alignments.
+ base_addr = m25pxx_flash_device.start + m25pxx_flash_device.block_info->block_size;
+ for (i = 1; i <= 256; i++) {
+
+ // Erase sectors either side of sector boundary.
+ status = cyg_flash_erase (base_addr - 1, 1, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash erase error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ status = cyg_flash_erase (base_addr, 1, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash erase error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+
+ // Write data spanning sector boundary.
+ status = cyg_flash_program (base_addr - i, wbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash write error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+
+ // Verify data spanning sector boundary.
+ status = cyg_flash_read (base_addr - i, rbuf, BUF_SIZE, &err_addr);
+ if (status != FLASH_ERR_OK) {
+ diag_printf ("Flash read error : %s\n", cyg_flash_errmsg (status));
+ errors ++;
+ }
+ else if (memcmp (rbuf, wbuf, BUF_SIZE) != 0) {
+ diag_printf ("Flash read data corruption (0x%08X - 0x%08X).\n", base_addr - i, base_addr - i + BUF_SIZE - 1);
+ errors ++;
+ }
+
+ // Use next sector boundary for next test.
+ base_addr += m25pxx_flash_device.block_info->block_size;
+ if (base_addr >= m25pxx_flash_device.end)
+ base_addr = m25pxx_flash_device.start + m25pxx_flash_device.block_info->block_size;
+ }
+ return errors;
+}
+
+//-----------------------------------------------------------------------------
+// Run all M25Pxx SPI interface loopback tests.
+
+void run_tests
+ (void)
+{
+ cyg_uint32 errors = 0;
+
+ // Check that the device is intialised.
+ if (m25pxx_flash_device.start == m25pxx_flash_device.end) {
+ diag_printf ("M25Pxx device not initialised.\n");
+ errors ++;
+ goto out;
+ }
+
+ // Run the tests.
+ errors += run_test_1 ();
+ errors += run_test_2 ();
+ errors += run_test_3 ();
+
+out:
+ diag_printf ("----\nTests complete - detected %d errors in total.\n", errors);
+ if (errors == 0)
+ CYG_TEST_PASS_FINISH ("M25Pxx driver tests ran OK.");
+ else
+ CYG_TEST_FAIL_FINISH ("M25Pxx driver test FAILED.");
+}
+
+//-----------------------------------------------------------------------------
+// User startup - tests are run in their own thread.
+
+void cyg_user_start
+ (void)
+{
+ do_version();
+ diag_printf ("----\nChecking for M25Pxx compatible devices.\n");
+ cyg_flash_set_global_printf((cyg_flash_printf *)&diag_printf);
+ cyg_flash_init(NULL);
+ CYG_TEST_INIT();
+ cyg_thread_create(
+ 10, // Arbitrary priority
+ (cyg_thread_entry_t*) run_tests, // Thread entry point
+ 0, //
+ "test_thread", // Thread name
+ (cyg_uint8*) stack, // Stack
+ CYGNUM_HAL_STACK_SIZE_TYPICAL, // Stack size
+ &thread_handle, // Thread handle
+ &thread_data // Thread data structure
+ );
+ cyg_thread_resume(thread_handle);
+ cyg_scheduler_start();
+}
+
+//=============================================================================