# HG changeset patch # User vae # Date 1329945195 0 # Node ID 97d27161b0f786f32a80e605fb8a48f1b76faadd # Parent a18d3fded36e73b8411643aadc422e58f9075b7d * cdl/flash_sst25xx.cdl * src/sst25xx.c: * tests/flash_sst25xx_test.c: New file Added tests [Bugzilla 1001450] diff --git a/packages/devs/flash/spi/sst25xx/current/ChangeLog b/packages/devs/flash/spi/sst25xx/current/ChangeLog --- 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 + + * cdl/flash_sst25xx.cdl + * src/sst25xx.c: + * tests/flash_sst25xx_test.c: New file + Added tests [Bugzilla 1001450] + 2011-04-13 Christophe Coutand * cdl/sst25xx.cdl: diff --git a/packages/devs/flash/spi/sst25xx/current/cdl/flash_sst25xx.cdl b/packages/devs/flash/spi/sst25xx/current/cdl/flash_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 diff --git a/packages/devs/flash/spi/sst25xx/current/src/sst25xx.c b/packages/devs/flash/spi/sst25xx/current/src/sst25xx.c --- 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 +#include +#include + #include #include #include diff --git a/packages/devs/flash/spi/sst25xx/current/tests/flash_sst25xx_test.c b/packages/devs/flash/spi/sst25xx/current/tests/flash_sst25xx_test.c 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 + +#include +#include // Test macros +#include // Assertion macros +#include // Diagnostic output + +#include // CYGNUM_HAL_STACK_SIZE_TYPICAL +#include +#include + +#include +#include +#include + +// Required data structures. +#include + +#include + +#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(); +} + +//============================================================================= +