Mercurial > nand-ecoscentric
changeset 3194:a9b6ea6f3c09
Added Atmel AT25DFxxx driver test application. [Bugzilla 1001449]
| author | vae |
|---|---|
| date | Mon, 12 Mar 2012 20:49:57 +0000 |
| parents | bbae8ea8a773 |
| children | 103d5fa67c22 |
| files | packages/devs/flash/spi/at25dfxxx/current/ChangeLog packages/devs/flash/spi/at25dfxxx/current/cdl/flash_at25dfxxx.cdl packages/devs/flash/spi/at25dfxxx/current/tests/at25dfxxx_test.c |
| diffstat | 3 files changed, 425 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/devs/flash/spi/at25dfxxx/current/ChangeLog +++ b/packages/devs/flash/spi/at25dfxxx/current/ChangeLog @@ -1,3 +1,10 @@ + +2012-01-05 Christophe Coutand <ecos@hotmail.co.uk> + * cdl/at25dfxxx.cdl: + * tests/at25dfxxx_test.c: + Added Atmel AT25DFxxx driver test application. + [Bugzilla 1001449] + 2011-04-13 Christophe Coutand <ecos@hotmail.co.uk> * cdl/at25dfxxx.cdl:
--- a/packages/devs/flash/spi/at25dfxxx/current/cdl/flash_at25dfxxx.cdl +++ b/packages/devs/flash/spi/at25dfxxx/current/cdl/flash_at25dfxxx.cdl @@ -65,6 +65,13 @@ cdl_package CYGPKG_DEVS_FLASH_SPI_AT25DF Flash memory support for Atmel AT95DFxxx SPI flash devices and compatibles. This driver implements the V2 flash driver API." + cdl_interface CYGHWR_DEVS_FLASH_SPI_AT25DFXXX_DEVICE { + display "Hardware AT25DFxxx FLASH device drivers" + description " + This calculated option gives the number of AT25DFxxx flash + devices on the current platform." + } + cdl_option CYGPKG_DEVS_FLASH_SPI_AT25DFXXX_BLOCK_SIZE { display "Flash block size in bytes" legal_values { 4096 32768 65536 } @@ -108,6 +115,19 @@ cdl_package CYGPKG_DEVS_FLASH_SPI_AT25DF this block size will automatically be split into a series of smaller SPI bus transactions." } + + cdl_option CYGPKG_DEVS_FLASH_SPI_AT25DFXXX_TESTS { + display "SPI flash driver tests for Atmel AT95DFxxx flash" + active_if CYGPKG_KERNEL + active_if CYGPKG_IO_SPI + requires { CYGHWR_DEVS_FLASH_SPI_AT25DFXXX_DEVICE >= 1 } + flavor data + no_define + calculated { "tests/at25dfxxx_test.c" } + description " + This option specifies the set of tests for the Atmel AT95DFxxx + SPI flash." + } } # EOF flash_at25dfxxx.cdl
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/spi/at25dfxxx/current/tests/at25dfxxx_test.c @@ -0,0 +1,398 @@ +//============================================================================= +// +// at25dfxxx_test.c +// +// SPI flash driver tests for Atmel AT95DFxxx 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): ccoutand, updated for Atmel AT95DFxxx flash +// Original(s): Chris Holgate +// Date: 2011-04-25 +// Purpose: Atmel AT95DFxxx 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/at25dfxxx.h> + +// Required data structures. +#include <cyg/io/flash_dev.h> + +#include <string.h> + +#include CYGHWR_MEMORY_LAYOUT_H + +static cyg_flash_info_t at25dfxxx_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 + +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"); + + // Iterate over all flash sectors. + for (i = 0; i < at25dfxxx_flash_info.block_info->blocks; i++) { + base_addr = at25dfxxx_flash_info.start + + (i * at25dfxxx_flash_info.block_info->block_size); + + // 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 < at25dfxxx_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 < at25dfxxx_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 < at25dfxxx_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 < at25dfxxx_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 ++; + } + } + } + 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 < at25dfxxx_flash_info.block_info->blocks; i++) { + base_addr = at25dfxxx_flash_info.start + + (i * at25dfxxx_flash_info.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 = at25dfxxx_flash_info.start; + for (i = 0; i < (at25dfxxx_flash_info.end - at25dfxxx_flash_info.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 = at25dfxxx_flash_info.start; + for (i = 0; i < (at25dfxxx_flash_info.end - at25dfxxx_flash_info.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 = at25dfxxx_flash_info.start + at25dfxxx_flash_info.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 += at25dfxxx_flash_info.block_info->block_size; + if (base_addr >= at25dfxxx_flash_info.end) + base_addr = at25dfxxx_flash_info.start + at25dfxxx_flash_info.block_info->block_size; + } + return errors; +} + +//----------------------------------------------------------------------------- +// Run all M25Pxx SPI interface loopback tests. + +void run_tests + (void) +{ + cyg_uint32 errors = 0; + + do_version(); + + diag_printf ("----\nChecking for AT25DFxxx 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_AT25XXX_DEV0_MAP_ADDR, + &at25dfxxx_flash_info); + + // Check that the device is intialised. + if (at25dfxxx_flash_info.start == at25dfxxx_flash_info.end) { + diag_printf ("AT25DFxxx 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 ("AT25DFxxx driver tests ran OK."); + else + CYG_TEST_FAIL_FINISH ("AT25DFxxx 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(); +} + +//=============================================================================
