diff --git a/bsps/arm/xilinx-zynq/dev/spi/zynq-qspi-flashdev.c b/bsps/arm/xilinx-zynq/dev/spi/zynq-qspi-flashdev.c index 439ffa03cd..7fe42452b6 100644 --- a/bsps/arm/xilinx-zynq/dev/spi/zynq-qspi-flashdev.c +++ b/bsps/arm/xilinx-zynq/dev/spi/zynq-qspi-flashdev.c @@ -149,6 +149,12 @@ static int zqspi_sector_count( return 0; } +static void zqspi_priv_destroy(rtems_flashdev* flash) +{ + free(flash->region_table->regions); + free(flash->region_table); +} + rtems_flashdev* zqspi_flashdev_init(zqspiflash *bmdriver) { zqspi_flash_region_table *xtable = @@ -180,6 +186,7 @@ rtems_flashdev* zqspi_flashdev_init(zqspiflash *bmdriver) } flash->driver = bmdriver; + flash->priv_destroy = &zqspi_priv_destroy; flash->read = &zqspi_read_wrapper; flash->write = &zqspi_write_wrapper; flash->erase = &zqspi_erase_wrapper; @@ -195,10 +202,3 @@ rtems_flashdev* zqspi_flashdev_init(zqspiflash *bmdriver) return flash; } - -void zqspi_flashdev_destroy(rtems_flashdev* flash) -{ - free(flash->region_table->regions); - free(flash->region_table); - rtems_flashdev_destroy_and_free(flash); -} diff --git a/bsps/arm/xilinx-zynq/include/dev/spi/zynq-qspi-flashdev.h b/bsps/arm/xilinx-zynq/include/dev/spi/zynq-qspi-flashdev.h index 78d8f0ac22..b67de802d2 100644 --- a/bsps/arm/xilinx-zynq/include/dev/spi/zynq-qspi-flashdev.h +++ b/bsps/arm/xilinx-zynq/include/dev/spi/zynq-qspi-flashdev.h @@ -34,10 +34,11 @@ #define ZQSPI_FLASH_MAX_REGIONS ((size_t)32) /* - * @brief Initializes a flash device using zynq qspi flash - * driver. The flash device is not registered in this call. - * If an rtems_flashdev is created using zqspi_flash_init it must be - * destroyed using xqspi_flash_destroy. + * @brief Initializes a flash device using zynq qspi flash driver. + * + * The flash device is not registered in this call. If an rtems_flashdev is + * created using zqspi_flash_init and is not registered, it must be destroyed + * using rtems_flashdev_destroy. * * @param[in] zqspiflash A initialised zqspiflash device to wrap. * @@ -46,16 +47,6 @@ */ rtems_flashdev* zqspi_flashdev_init(zqspiflash *bmdriver); -/* - * @brief Destroys a rtems_flashdev initialised with zqspi_flash_init. - * If an rtems_flashdev is created using zqspi_flash_init it must be - * destroyed using zqspi_flash_destroy. The zqspiflash originally passed in - * is untouched. - * - * @param[in] flash The flashdev to destroy -*/ -void zqspi_flashdev_destroy(rtems_flashdev* flash); - /* * @brief Struct allocating memory space for flash regions. Used by * rtems_flashdev to store region allocations. diff --git a/bsps/include/dev/spi/xqspi_flash.h b/bsps/include/dev/spi/xqspi_flash.h index dbd1f913d3..92010eae7c 100644 --- a/bsps/include/dev/spi/xqspi_flash.h +++ b/bsps/include/dev/spi/xqspi_flash.h @@ -38,10 +38,10 @@ extern "C" { #define XQSPI_FLASH_MAX_REGIONS ((size_t)32) /* - * @brief Initializes a flash device using Xilinx's xqspi flash - * driver. The flash device is not registered in this call. - * If an rtems_flashdev is created using xqspi_flash_init it must be - * destroyed using xqspi_flash_destroy. + * @brief Initializes a flash device using Xilinx's xqspi flash driver. + * + * The flash device is not registered in this call. The returned object must be + * destroyed with rtems_flashdev_destroy_and_free if it has not been registered. * * @param[in] xQspiDev A configured XQspiPsu device to initialise. * @@ -50,16 +50,6 @@ extern "C" { */ rtems_flashdev* xqspi_flash_init(XQspiPsu *xQspiDev); -/* - * @brief Destroys a rtems_flashdev initialised with xqspi_flash_init. - * If an rtems_flashdev is created using xqspi_flash_init it must be - * destroyed using xqspi_flash_destroy. The XQspiPsu originally passed in - * is untouched. - * - * @param[in] flash The flashdev to destroy -*/ -void xqspi_flash_destroy(rtems_flashdev* flash); - /* * @brief Struct allocating memory space for flash regions. Used by * rtems_flashdev to store region allocations. diff --git a/bsps/shared/dev/spi/xqspi_flash.c b/bsps/shared/dev/spi/xqspi_flash.c index 299cfd37f9..e757e4f9bb 100644 --- a/bsps/shared/dev/spi/xqspi_flash.c +++ b/bsps/shared/dev/spi/xqspi_flash.c @@ -121,6 +121,12 @@ static int xqspi_erase_wrapper( return QspiPsu_NOR_Erase(flash_driver, (uint32_t)offset, (uint32_t)count); } +static void xqspi_flash_priv_destroy(rtems_flashdev* flash) +{ + free(flash->region_table->regions); + free(flash->region_table); +} + rtems_flashdev* xqspi_flash_init(XQspiPsu *xQspiDev) { xqspi_flash_region_table *xtable = @@ -152,6 +158,7 @@ rtems_flashdev* xqspi_flash_init(XQspiPsu *xQspiDev) } flash->driver = xQspiDev; + flash->priv_destroy = &xqspi_flash_priv_destroy; flash->read = &xqspi_read_wrapper; flash->write = &xqspi_write_wrapper; flash->erase = &xqspi_erase_wrapper; @@ -165,10 +172,3 @@ rtems_flashdev* xqspi_flash_init(XQspiPsu *xQspiDev) return flash; } - -void xqspi_flash_destroy(rtems_flashdev* flash) -{ - free(flash->region_table->regions); - free(flash->region_table); - rtems_flashdev_destroy_and_free(flash); -} diff --git a/cpukit/dev/flash/flashdev.c b/cpukit/dev/flash/flashdev.c index 482468cb67..852af49bb9 100644 --- a/cpukit/dev/flash/flashdev.c +++ b/cpukit/dev/flash/flashdev.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -503,6 +504,13 @@ int rtems_flashdev_register( return rv; } +int rtems_flashdev_unregister( + const char *flash_path +) +{ + return unlink(flash_path); +} + static int rtems_flashdev_do_init( rtems_flashdev *flash, void ( *destroy )( rtems_flashdev *flash ) @@ -517,25 +525,38 @@ static int rtems_flashdev_do_init( void rtems_flashdev_destroy( rtems_flashdev *flash ) { - rtems_recursive_mutex_destroy( &flash->mutex ); + ( *flash->destroy )( flash ); } void rtems_flashdev_destroy_and_free( rtems_flashdev *flash ) +{ + rtems_flashdev_destroy( flash ); +} + +static void flashdev_destroy_internal( rtems_flashdev *flash ) +{ + if (flash->priv_destroy != NULL) { + ( *flash->priv_destroy )( flash ); + } + + rtems_recursive_mutex_destroy( &flash->mutex ); +} + +static void flashdev_destroy_and_free_internal( rtems_flashdev *flash ) { if ( flash == NULL ) { return; } - rtems_recursive_mutex_destroy( &( flash->mutex ) ); + flashdev_destroy_internal( flash ); free( flash ); flash = NULL; - return; } int rtems_flashdev_init( rtems_flashdev *flash ) { memset( flash, 0, sizeof( *flash ) ); - return rtems_flashdev_do_init( flash, rtems_flashdev_destroy ); + return rtems_flashdev_do_init( flash, flashdev_destroy_internal ); } rtems_flashdev *rtems_flashdev_alloc_and_init( size_t size ) @@ -547,7 +568,7 @@ rtems_flashdev *rtems_flashdev_alloc_and_init( size_t size ) if ( flash != NULL ) { int rv; - rv = rtems_flashdev_do_init( flash, rtems_flashdev_destroy_and_free ); + rv = rtems_flashdev_do_init( flash, flashdev_destroy_and_free_internal ); if ( rv != 0 ) { rtems_recursive_mutex_destroy( &flash->mutex ); free( flash ); diff --git a/cpukit/include/dev/flash/flashdev.h b/cpukit/include/dev/flash/flashdev.h index 62bc5cf443..207b794c68 100644 --- a/cpukit/include/dev/flash/flashdev.h +++ b/cpukit/include/dev/flash/flashdev.h @@ -443,6 +443,16 @@ struct rtems_flashdev { rtems_flashdev *flashdev ); + /** + * @brief Callback to destroy private data not owned directly by the flashdev + * framework. + * + * @param[in] flash Pointer to flash device. + */ + void ( *priv_destroy )( + rtems_flashdev *flashdev + ); + /** * @brief Pointer to device driver. */ @@ -495,7 +505,8 @@ int rtems_flashdev_init( /** * @brief Register the flash device. * - * This function always claims ownership of the flash device. + * This function always claims ownership of the flash device passed to it. Once + * registered, the flash device can only be destroyed by unregistering it. * * After initialization and before registration read, write, erase, jedec_id * and flash_type functions need to be set in the flashdev. @@ -511,9 +522,24 @@ int rtems_flashdev_register( const char *flash_path ); +/** + * @brief Unregister the flash device. + * + * @param[in] flash The flash device. + * + * @retval 0 Successful operation. + * @retval non-zero Failed operation. + */ +int rtems_flashdev_unregister( + const char *flash_path +); + /** * @brief Destroys the flash device. * + * This function must only be used on rtems_flashdev instances that have not + * been registered. + * * @param[in] flash The flash device. */ void rtems_flashdev_destroy( @@ -523,6 +549,9 @@ void rtems_flashdev_destroy( /** * @brief Destroys the flash device and frees its memory. * + * This function must only be used on rtems_flashdev instances that have not + * been registered. + * * @param[in] flash The flash device. */ void rtems_flashdev_destroy_and_free( diff --git a/testsuites/libtests/flashdev01/init.c b/testsuites/libtests/flashdev01/init.c index 54b6290e01..8b348778ce 100644 --- a/testsuites/libtests/flashdev01/init.c +++ b/testsuites/libtests/flashdev01/init.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #define TEST_NAME_LENGTH 10 @@ -64,6 +65,32 @@ static void run_test(void) { int sector_count; int type; size_t wb_size; + rtems_resource_snapshot snapshot; + + /* Check resource usage on creation and deletion */ + rtems_resource_snapshot_take(&snapshot); + + flash = test_flashdev_init(); + rtems_test_assert(flash != NULL); + + rtems_flashdev_destroy(flash); + flash = NULL; + + rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); + + /* Check resource usage on registration */ + rtems_resource_snapshot_take(&snapshot); + + flash = test_flashdev_init(); + rtems_test_assert(flash != NULL); + + status = rtems_flashdev_register(flash, "dev/flashdev0"); + rtems_test_assert(!status); + + status = rtems_flashdev_unregister("dev/flashdev0"); + rtems_test_assert(!status); + + rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); /* Initalize the flash device driver and flashdev */ flash = test_flashdev_init(); @@ -78,6 +105,12 @@ static void run_test(void) { rtems_test_assert(file != NULL); fd = fileno(file); + /* Initial read to establish cached buffers */ + read_data = fgets(buff, TEST_DATA_SIZE, file); + rtems_test_assert(read_data != NULL); + + rtems_resource_snapshot_take(&snapshot); + /* Read data from flash */ read_data = fgets(buff, TEST_DATA_SIZE, file); rtems_test_assert(read_data != NULL); @@ -176,6 +209,14 @@ static void run_test(void) { fseek(file, 0x400, SEEK_SET); fgets(buff, 11, file); rtems_test_assert(strncmp(buff, "HELLO WORLD", 11)); + + rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); + + status = fclose(file); + rtems_test_assert(!status); + + status = rtems_flashdev_unregister("dev/flashdev0"); + rtems_test_assert(!status); } static void Init(rtems_task_argument arg) diff --git a/testsuites/libtests/flashdev01/test_flashdev.c b/testsuites/libtests/flashdev01/test_flashdev.c index 2fc0b3e83a..993cb9ae99 100644 --- a/testsuites/libtests/flashdev01/test_flashdev.c +++ b/testsuites/libtests/flashdev01/test_flashdev.c @@ -264,6 +264,14 @@ int test_flashdev_erase( return 0; } +static void test_flashdev_priv_destroy(rtems_flashdev *flash) +{ + test_flashdev* flash_driver = flash->driver; + free(flash_driver->data); + free(flash->driver); + free(flash->region_table); +} + /* Initialize Flashdev and underlying driver. */ rtems_flashdev* test_flashdev_init(void) { @@ -295,6 +303,7 @@ rtems_flashdev* test_flashdev_init(void) ftable->bit_allocator = flash_driver->bit_allocator; flash->driver = flash_driver; + flash->priv_destroy = &test_flashdev_priv_destroy; flash->read = &test_flashdev_read; flash->write = &test_flashdev_write; flash->erase = &test_flashdev_erase;