changeset 3082:97d27161b0f7

* cdl/flash_sst25xx.cdl * src/sst25xx.c: * tests/flash_sst25xx_test.c: New file Added tests [Bugzilla 1001450]
author vae
date Wed, 22 Feb 2012 21:13:15 +0000
parents a18d3fded36e
children 35ac6793793f
files packages/devs/flash/spi/sst25xx/current/ChangeLog packages/devs/flash/spi/sst25xx/current/cdl/flash_sst25xx.cdl packages/devs/flash/spi/sst25xx/current/src/sst25xx.c packages/devs/flash/spi/sst25xx/current/tests/flash_sst25xx_test.c
diffstat 4 files changed, 461 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/flash/spi/sst25xx/current/ChangeLog
+++ b/packages/devs/flash/spi/sst25xx/current/ChangeLog
@@ -1,3 +1,10 @@
+2012-02-06  Ilija Kocho  <ilijak@siva.com.mk>
+
+    * cdl/flash_sst25xx.cdl
+    * src/sst25xx.c:
+    * tests/flash_sst25xx_test.c: New file
+    Added tests  [Bugzilla 1001450]
+
 2011-04-13  Christophe Coutand  <ecos@hotmail.co.uk>
 
 	* cdl/sst25xx.cdl:
--- a/packages/devs/flash/spi/sst25xx/current/cdl/flash_sst25xx.cdl
+++ b/packages/devs/flash/spi/sst25xx/current/cdl/flash_sst25xx.cdl
@@ -59,13 +59,20 @@ cdl_package CYGPKG_DEVS_FLASH_SPI_SST25X
     implements    CYGHWR_IO_FLASH_INDIRECT_READS
 
     include_dir   cyg/io
-    compile       sst25xx.c
+    compile       -library=libextras.a sst25xx.c
 
     description   "
         Flash memory support for the Silicon Storage Technology SST25xx
         SPI flash devices and compatibles.  This driver implements the
         V2 flash driver API"
 
+    cdl_interface CYGHWR_DEVS_FLASH_SPI_SST25XX_DEVICE {
+        display     "Hardware SST25xx FLASH device drivers"
+        description "
+            This calculated option gives the number of SST25xx flash
+            devices on the current platform."
+    }
+
     cdl_option CYGPKG_DEVS_FLASH_SPI_SST25XX_SUPPORT_JEDECID {
         display       "Device supports JEDEC ID"
         flavor        bool
@@ -121,6 +128,18 @@ cdl_package CYGPKG_DEVS_FLASH_SPI_SST25X
             this block size will automatically be split into a series
             of smaller SPI bus transactions."
     }
+    
+    cdl_component CYGPKG_DEVS_FLASH_SPI_SST25XX_TESTS {
+        display         "SST25xx tests"
+        flavor          data
+        active_if      CYGPKG_KERNEL
+        active_if      CYGPKG_IO_SPI
+        active_if       { CYGHWR_DEVS_FLASH_SPI_SST25XX_DEVICE >= 1 }
+        no_define
+        calculated      { "tests/flash_sst25xx_test.c" }
+        description     "
+            This option specifies the set of tests for sst25 driver."
+    }
 }
 
 # EOF flash_sst25xx.cdl
--- a/packages/devs/flash/spi/sst25xx/current/src/sst25xx.c
+++ b/packages/devs/flash/spi/sst25xx/current/src/sst25xx.c
@@ -51,6 +51,10 @@
 //
 //=============================================================================
 
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_diag.h>
+
 #include <cyg/io/spi.h>
 #include <cyg/io/flash.h>
 #include <cyg/io/flash_dev.h>
new file mode 100644
--- /dev/null
+++ b/packages/devs/flash/spi/sst25xx/current/tests/flash_sst25xx_test.c
@@ -0,0 +1,430 @@
+//=============================================================================
+//
+//      flash_sst25xx_test.c
+//
+//      SPI flash driver tests for SST25XX SPI FLASH
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008, 2009, 2011 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):   ilijak, updated for SST25xx flash
+// Original(s): Chris Holgate, Christian Coutand
+// Date:        2011-04-25
+// Purpose:     SST25xx 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/sst25xx.h>
+
+// Required data structures.
+#include <cyg/io/flash_dev.h>
+
+#include <string.h>
+
+#include CYGHWR_MEMORY_LAYOUT_H
+
+cyg_flash_info_t sst25xx_flash_info;
+//-----------------------------------------------------------------------------
+// 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
+#define BUF_SIZE 128
+
+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("\nPlatform: %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");
+    diag_printf (" Flash device at %p, block_info at %p start = 0x%08x, blocks = %d[0x%x]\n",
+                 &sst25xx_flash_info,
+                 sst25xx_flash_info.block_info, sst25xx_flash_info.start,
+                 sst25xx_flash_info.block_info->blocks,
+                 sst25xx_flash_info.block_info->blocks);
+
+    // Iterate over all flash sectors.
+    for (i = 0; i < sst25xx_flash_info.block_info->blocks; i++) {
+        base_addr =  sst25xx_flash_info.start +
+                            (i * sst25xx_flash_info.block_info->block_size);
+        if(!(i % 64))
+            diag_printf("\n%5d 0x%08x: ", i, base_addr-sst25xx_flash_info.start);
+        diag_printf(".");
+        // Unlock block.
+        status = cyg_flash_unlock (base_addr, 1, &err_addr);
+        if (status != FLASH_ERR_OK) {
+            diag_printf ("Flash erase error : %s\n", cyg_flash_errmsg (status));
+            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 checkerboard.
+        for (j = 0; j < BUF_SIZE;) {
+           wbuf [j++] = 0x55;
+           wbuf [j++] = 0xAA;
+        }
+
+        // Write the checkerboard to the entire sector.
+        for (j = 0; j < sst25xx_flash_info.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 < sst25xx_flash_info.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 < sst25xx_flash_info.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 < sst25xx_flash_info.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 ++;
+            }
+        }
+    }
+    diag_printf("\n");
+    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.
+    diag_printf("Erase all flash sectors\n");
+    for (i = 0; i < sst25xx_flash_info.block_info->blocks; i++) {
+        base_addr =  sst25xx_flash_info.start +
+                           (i * sst25xx_flash_info.block_info->block_size);
+        if(!(i % 64))
+            diag_printf("\n%5d: ", i);
+        diag_printf(".");
+
+        // 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 ++;
+        }
+    }
+    diag_printf("\n");
+
+    // Write counting sequence.
+    diag_printf("Writing counting sequence\n");
+    base_addr =  sst25xx_flash_info.start;
+    for (i = 0; i < (sst25xx_flash_info.end - sst25xx_flash_info.start) / 4;) {
+        if(!(i % (64*1024)))
+            diag_printf("\n%7d: ", i);
+        if(!(i % (32*64)))
+            diag_printf(".");
+        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;
+    }
+    diag_printf("\n");
+
+    // Verify counting sequence.
+    diag_printf("Verifying counting sequence\n");
+    base_addr = sst25xx_flash_info.start;
+    for (i = 0; i < (sst25xx_flash_info.end - sst25xx_flash_info.start) / 4;) {
+        if(!(i % (64*1024)))
+            diag_printf("\n%7d: ", i);
+        if(!(i % (32*64)))
+            diag_printf(".");
+        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;
+    }
+    diag_printf("\n");
+    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 = sst25xx_flash_info.start + sst25xx_flash_info.block_info->block_size;
+    for (i = 1; i <= 256; i++) {
+        if(!(i % 32))
+            diag_printf("\n%5d: ", i);
+        diag_printf(".");
+
+        // 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);
+            diag_printf ("Flash read data corruption %d.\n", i);
+            errors ++;
+        }
+
+        // Use next sector boundary for next test.
+        base_addr += sst25xx_flash_info.block_info->block_size;
+        if (base_addr >= sst25xx_flash_info.end)
+            base_addr = sst25xx_flash_info.start + sst25xx_flash_info.block_info->block_size;
+    }
+    diag_printf("\n\n");
+    return errors;
+}
+
+//-----------------------------------------------------------------------------
+// Run all SST25xx SPI interface loopback tests.
+
+void run_tests
+    (void)
+{
+    cyg_uint32 errors = 0;
+
+    do_version();
+
+    //    diag_printf ("----\nChecking for SST25xx compatible devices at %p\n", &sst25xx_flash_device);
+    diag_printf ("----\nChecking for SST25xx compatible devices.\n");
+    cyg_flash_set_global_printf((cyg_flash_printf *)&diag_printf);
+    cyg_flash_init(NULL);
+
+    cyg_flash_get_info_addr(CYGNUM_DEVS_FLASH_SPI_SST25XX_DEV0_MAP_ADDR, &sst25xx_flash_info);
+
+    // Check that the device is intialised.
+    if (sst25xx_flash_info.start == sst25xx_flash_info.end) {
+        diag_printf ("SST25xx 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 ("SST25xx driver tests ran OK.");
+    else
+        CYG_TEST_FAIL_FINISH ("SST25xx driver test FAILED.");
+}
+
+//-----------------------------------------------------------------------------
+// User startup - tests are run in their own thread.
+
+void cyg_user_start
+    (void)
+{
+    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();
+}
+
+//=============================================================================
+