static inline void lpc31_initsrc(void) { FAR struct spi_dev_s *spi; #ifdef CONFIG_DEBUG uint32_t capacity; int ret; #endif /* Are we already initialized? */ if (!g_pgsrc.initialized) { /* No... the initialize now */ pgllvdbg("Initializing\n"); /* First get an instance of the SPI device interface */ spi = up_spiinitialize(CONFIG_EA3131_PAGING_SPIPORT); DEBUGASSERT(spi != NULL); /* Then bind the SPI interface to the MTD driver */ #ifdef CONFIG_PAGING_M25PX g_pgsrc.mtd = m25p_initialize(spi); #else g_pgsrc.mtd = at45db_initialize(spi); #endif DEBUGASSERT(g_pgsrc.mtd != NULL); /* Verify that we can use the device */ #ifdef CONFIG_DEBUG /* Get the device geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ ret = MTD_IOCTL(g_pgsrc.mtd, MTDIOC_GEOMETRY, (unsigned long)&g_pgsrc.geo); DEBUGASSERT(ret >= 0); capacity = g_pgsrc.geo.erasesize*g_pgsrc.geo.neraseblocks; pgllvdbg("capacity: %d\n", capacity); DEBUGASSERT(capacity >= (CONFIG_EA3131_PAGING_BINOFFSET + PG_TEXT_VSIZE)); #endif /* We are now initialized */ g_pgsrc.initialized = true; } }
static int ftl_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) { struct ftl_struct_s *dev ; int ret; finfo("Entry\n"); DEBUGASSERT(inode && inode->i_private); /* Only one block driver ioctl command is supported by this driver (and * that command is just passed on to the MTD driver in a slightly * different form). */ if (cmd == BIOC_XIPBASE) { /* The argument accompanying the BIOC_XIPBASE should be non-NULL. If * DEBUG is enabled, we will catch it here instead of in the MTD * driver. */ #ifdef CONFIG_DEBUG_FEATURES if (arg == 0) { ferr("ERROR: BIOC_XIPBASE argument is NULL\n"); return -EINVAL; } #endif /* Just change the BIOC_XIPBASE command to the MTDIOC_XIPBASE command. */ cmd = MTDIOC_XIPBASE; } /* No other block driver ioctl commmands are not recognized by this * driver. Other possible MTD driver ioctl commands are passed through * to the MTD driver (unchanged). */ dev = (struct ftl_struct_s *)inode->i_private; ret = MTD_IOCTL(dev->mtd, cmd, arg); if (ret < 0) { ferr("ERROR: MTD ioctl(%04x) failed: %d\n", cmd, ret); } return ret; }
int mtdconfig_register(FAR struct mtd_dev_s *mtd) { int ret = OK; struct mtdconfig_struct_s *dev; struct mtd_geometry_s geo; /* Device geometry */ dev = (struct mtdconfig_struct_s *)kmm_malloc(sizeof(struct mtdconfig_struct_s)); if (dev) { /* Initialize the mtdconfig device structure */ dev->mtd = mtd; sem_init(&dev->exclsem, 0, 1); /* Get the device geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo)); if (ret < 0) { fdbg("MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret); kmm_free(dev); goto errout; } dev->blocksize = geo.blocksize; dev->neraseblocks = geo.neraseblocks; dev->erasesize = geo.erasesize; dev->nblocks = geo.neraseblocks * geo.erasesize / geo.blocksize; (void)register_driver("/dev/config", &mtdconfig_fops, 0666, dev); } errout: return ret; }
int smart_main(int argc, char *argv[]) { FAR struct mtd_dev_s *mtd; unsigned int i; int ret; /* Seed the random number generated */ srand(0x93846); /* Create and initialize a RAM MTD device instance */ #ifdef CONFIG_EXAMPLES_SMART_ARCHINIT mtd = smart_archinitialize(); #else mtd = rammtd_initialize(g_simflash, EXAMPLES_SMART_BUFSIZE); #endif if (!mtd) { message("ERROR: Failed to create RAM MTD instance\n"); msgflush(); exit(1); } /* Initialize to provide SMART on an MTD interface */ MTD_IOCTL(mtd, MTDIOC_BULKERASE, 0); ret = smart_initialize(1, mtd); if (ret < 0) { message("ERROR: SMART initialization failed: %d\n", -ret); msgflush(); exit(2); } /* Creaet a SMARTFS filesystem */ ret = mksmartfs("/dev/smart1"); /* Mount the file system */ ret = mount("/dev/smart1", CONFIG_EXAMPLES_SMART_MOUNTPT, "smartfs", 0, NULL); if (ret < 0) { message("ERROR: Failed to mount the SMART volume: %d\n", errno); msgflush(); exit(3); } /* Set up memory monitoring */ #ifdef CONFIG_CAN_PASS_STRUCTS g_mmbefore = mallinfo(); g_mmprevious = g_mmbefore; #else (void)mallinfo(&g_mmbefore); memcpy(&g_mmprevious, &g_mmbefore, sizeof(struct mallinfo)); #endif /* Loop a few times ... file the file system with some random, files, * delete some files randomly, fill the file system with more random file, * delete, etc. This beats the FLASH very hard! */ #if CONFIG_EXAMPLES_SMART_NLOOPS == 0 for (i = 0; ; i++) #else for (i = 1; i <= CONFIG_EXAMPLES_SMART_NLOOPS; i++) #endif { /* Write a files to the SMART file system until either (1) all of the * open file structures are utilized or until (2) SMART reports an error * (hopefully that the file system is full) */ message("\n=== FILLING %d =============================\n", i); ret = smart_fillfs(); message("Filled file system\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); /* Directory listing */ smart_directory(); /* Verify all files written to FLASH */ ret = smart_verifyfs(); if (ret < 0) { message("ERROR: Failed to verify files\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); } else { #if CONFIG_EXAMPLES_SMART_VERBOSE != 0 message("Verified!\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); #endif } /* Delete some files */ message("\n=== DELETING %d ============================\n", i); ret = smart_delfiles(); if (ret < 0) { message("ERROR: Failed to delete files\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); } else { message("Deleted some files\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); } /* Directory listing */ smart_directory(); /* Verify all files written to FLASH */ ret = smart_verifyfs(); if (ret < 0) { message("ERROR: Failed to verify files\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); } else { #if CONFIG_EXAMPLES_SMART_VERBOSE != 0 message("Verified!\n"); message(" Number of files: %d\n", g_nfiles); message(" Number deleted: %d\n", g_ndeleted); #endif } /* Show memory usage */ smart_loopmemusage(); msgflush(); } /* Delete all files then show memory usage again */ smart_delallfiles(); smart_endmemusage(); msgflush(); return 0; }
int nxffs_dump(FAR struct mtd_dev_s *mtd, bool verbose) { #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) struct nxffs_blkinfo_s blkinfo; int ret; /* Get the volume geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ memset(&blkinfo, 0, sizeof(struct nxffs_blkinfo_s)); ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&blkinfo.geo)); if (ret < 0) { fdbg("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret); goto errout; } /* Save the verbose output indication */ blkinfo.verbose = verbose; /* Allocate a buffer to hold one block */ blkinfo.buffer = (FAR uint8_t *)kmalloc(blkinfo.geo.blocksize); if (!blkinfo.buffer) { fdbg("ERROR: Failed to allocate block cache\n"); ret = -ENOMEM; goto errout; } /* Now read every block on the device */ fdbg("NXFFS Dump:\n"); fdbg(g_hdrformat); blkinfo.nblocks = blkinfo.geo.erasesize * blkinfo.geo.neraseblocks / blkinfo.geo.blocksize; for (blkinfo.block = 0, blkinfo.offset = 0; blkinfo.block < blkinfo.nblocks; blkinfo.block++, blkinfo.offset += blkinfo.geo.blocksize) { /* Read the next block */ ret = MTD_BREAD(mtd, blkinfo.block, 1, blkinfo.buffer); if (ret < 0) { fdbg("ERROR: Failed to read block %d\n", blkinfo.block); goto errout_with_block; } /* Analyze the block */ nxffs_analyze(&blkinfo); } fdbg("%d blocks analyzed\n", blkinfo.nblocks); errout_with_block: kfree(blkinfo.buffer); errout: return ret; #else return -ENOSYS; #endif }
int nxffs_initialize(FAR struct mtd_dev_s *mtd) { FAR struct nxffs_volume_s *volume; struct nxffs_blkstats_s stats; off_t threshold; int ret; /* If CONFIG_NXFFS_PREALLOCATED is defined, then this is the single, pre- * allocated NXFFS volume instance. */ #ifdef CONFIG_NXFFS_PREALLOCATED volume = &g_volume; memset(volume, 0, sizeof(struct nxffs_volume_s)); #else /* Allocate a NXFFS volume structure */ volume = (FAR struct nxffs_volume_s *)kzalloc(sizeof(struct nxffs_volume_s)); if (!volume) { ret = -ENOMEM; goto errout; } #endif /* Initialize the NXFFS volume structure */ volume->mtd = mtd; volume->cblock = (off_t)-1; sem_init(&volume->exclsem, 0, 1); sem_init(&volume->wrsem, 0, 1); /* Get the volume geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&volume->geo)); if (ret < 0) { fdbg("MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret); goto errout_with_volume; } /* Allocate one I/O block buffer to general files system access */ volume->cache = (FAR uint8_t *)kmalloc(volume->geo.blocksize); if (!volume->cache) { fdbg("Failed to allocate an erase block buffer\n"); ret = -ENOMEM; goto errout_with_volume; } /* Pre-allocate one, full, in-memory erase block. This is needed for filesystem * packing (but is useful in other places as well). This buffer is not needed * often, but is best to have pre-allocated and in-place. */ volume->pack = (FAR uint8_t *)kmalloc(volume->geo.erasesize); if (!volume->pack) { fdbg("Failed to allocate an I/O block buffer\n"); ret = -ENOMEM; goto errout_with_cache; } /* Get the number of R/W blocks per erase block and the total number o * R/W blocks */ volume->blkper = volume->geo.erasesize / volume->geo.blocksize; volume->nblocks = volume->geo.neraseblocks * volume->blkper; DEBUGASSERT((off_t)volume->blkper * volume->geo.blocksize == volume->geo.erasesize); /* Check if there is a valid NXFFS file system on the flash */ ret = nxffs_blockstats(volume, &stats); if (ret < 0) { fdbg("Failed to collect block statistics: %d\n", -ret); goto errout_with_buffer; } /* If the proportion of good blocks is low or the proportion of unformatted * blocks is high, then reformat the FLASH. */ threshold = stats.nblocks / 5; if (stats.ngood < threshold || stats.nunformat > threshold) { /* Reformat the volume */ ret = nxffs_reformat(volume); if (ret < 0) { fdbg("Failed to reformat the volume: %d\n", -ret); goto errout_with_buffer; } /* Get statistics on the re-formatted volume */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS) ret = nxffs_blockstats(volume, &stats); if (ret < 0) { fdbg("Failed to collect block statistics: %d\n", -ret); goto errout_with_buffer; } #endif } /* Get the file system limits */ ret = nxffs_limits(volume); if (ret == OK) { return OK; } fdbg("Failed to calculate file system limits: %d\n", -ret); errout_with_buffer: kfree(volume->pack); errout_with_cache: kfree(volume->cache); errout_with_volume: #ifndef CONFIG_NXFFS_PREALLOCATED kfree(volume); #endif return ret; }
int board_app_initialize(uintptr_t arg) { #ifdef HAVE_RTC_DRIVER FAR struct rtc_lowerhalf_s *rtclower; #endif #if defined(HAVE_N25QXXX) FAR struct mtd_dev_s *mtd_temp; #endif #if defined(HAVE_N25QXXX_CHARDEV) char blockdev[18]; char chardev[12]; #endif int ret; (void)ret; #ifdef HAVE_PROC /* mount the proc filesystem */ syslog(LOG_INFO, "Mounting procfs to /proc\n"); ret = mount(NULL, CONFIG_NSH_PROC_MOUNTPOINT, "procfs", 0, NULL); if (ret < 0) { syslog(LOG_ERR, "ERROR: Failed to mount the PROC filesystem: %d (%d)\n", ret, errno); return ret; } #endif #ifdef HAVE_RTC_DRIVER /* Instantiate the STM32 lower-half RTC driver */ rtclower = stm32l4_rtc_lowerhalf(); if (!rtclower) { serr("ERROR: Failed to instantiate the RTC lower-half driver\n"); return -ENOMEM; } else { /* Bind the lower half driver and register the combined RTC driver * as /dev/rtc0 */ ret = rtc_initialize(0, rtclower); if (ret < 0) { serr("ERROR: Failed to bind/register the RTC driver: %d\n", ret); return ret; } } #endif #ifdef HAVE_N25QXXX /* Create an instance of the STM32L4 QSPI device driver */ g_qspi = stm32l4_qspi_initialize(0); if (!g_qspi) { _err("ERROR: stm32l4_qspi_initialize failed\n"); return ret; } else { /* Use the QSPI device instance to initialize the * N25QXXX device. */ mtd_temp = n25qxxx_initialize(g_qspi, true); if (!mtd_temp) { _err("ERROR: n25qxxx_initialize failed\n"); return ret; } g_mtd_fs = mtd_temp; #ifdef CONFIG_MTD_PARTITION { FAR struct mtd_geometry_s geo; off_t nblocks; /* Setup a partition of 256KiB for our file system. */ ret = MTD_IOCTL(g_mtd_fs, MTDIOC_GEOMETRY, (unsigned long)(uintptr_t)&geo); if (ret < 0) { _err("ERROR: MTDIOC_GEOMETRY failed\n"); return ret; } nblocks = (256*1024) / geo.blocksize; mtd_temp = mtd_partition(g_mtd_fs, 0, nblocks); if (!mtd_temp) { _err("ERROR: mtd_partition failed\n"); return ret; } g_mtd_fs = mtd_temp; } #endif #ifdef HAVE_N25QXXX_SMARTFS /* Configure the device with no partition support */ ret = smart_initialize(N25QXXX_SMART_MINOR, g_mtd_fs, NULL); if (ret != OK) { _err("ERROR: Failed to initialize SmartFS: %d\n", ret); } #elif defined(HAVE_N25QXXX_NXFFS) /* Initialize to provide NXFFS on the N25QXXX MTD interface */ ret = nxffs_initialize(g_mtd_fs); if (ret < 0) { _err("ERROR: NXFFS initialization failed: %d\n", ret); } /* Mount the file system at /mnt/nxffs */ ret = mount(NULL, "/mnt/nxffs", "nxffs", 0, NULL); if (ret < 0) { _err("ERROR: Failed to mount the NXFFS volume: %d\n", errno); return ret; } #else /* if defined(HAVE_N25QXXX_CHARDEV) */ /* Use the FTL layer to wrap the MTD driver as a block driver */ ret = ftl_initialize(N25QXXX_MTD_MINOR, g_mtd_fs); if (ret < 0) { _err("ERROR: Failed to initialize the FTL layer: %d\n", ret); return ret; } /* Use the minor number to create device paths */ snprintf(blockdev, 18, "/dev/mtdblock%d", N25QXXX_MTD_MINOR); snprintf(chardev, 12, "/dev/mtd%d", N25QXXX_MTD_MINOR); /* Now create a character device on the block device */ /* NOTE: for this to work, you will need to make sure that * CONFIG_FS_WRITABLE is set in the config. It's not a user- * visible setting, but you can make it set by selecting an * arbitrary writable file system (you don't have to actually * use it, just select it so that the block device created via * ftl_initialize() will be writable). */ ret = bchdev_register(blockdev, chardev, false); if (ret < 0) { _err("ERROR: bchdev_register %s failed: %d\n", chardev, ret); return ret; } #endif } #endif #ifdef HAVE_USBHOST /* Initialize USB host operation. stm32l4_usbhost_initialize() starts a thread * will monitor for USB connection and disconnection events. */ ret = stm32l4_usbhost_initialize(); if (ret != OK) { udbg("ERROR: Failed to initialize USB host: %d\n", ret); return ret; } #endif #ifdef HAVE_USBMONITOR /* Start the USB Monitor */ ret = usbmonitor_start(0, NULL); if (ret != OK) { udbg("ERROR: Failed to start USB monitor: %d\n", ret); return ret; } #endif return OK; }
static int mtdconfig_setconfig(FAR struct mtdconfig_struct_s *dev, FAR struct config_data_s *pdata) { uint8_t sig[CONFIGDATA_BLOCK_HDR_SIZE]; /* Format signature bytes ("CD") */ char retrycount = 0; int ret = -ENOSYS; off_t offset, bytes_left_in_block, bytes; uint16_t block; struct mtdconfig_header_s hdr; uint8_t ram_consolidate; /* Allocate a temp block buffer */ dev->buffer = (FAR uint8_t *) kmm_malloc(dev->blocksize); /* Read and vaidate the signature bytes */ retry: offset = mtdconfig_findfirstentry(dev, &hdr); if (offset == 0) { /* Config Data partition not formatted. */ if (retrycount) { ret = -ENOSYS; goto errout; } /* Try to format the config partition */ ret = MTD_IOCTL(dev->mtd, MTDIOC_BULKERASE, 0); if (ret < 0) { goto errout; } /* Write a format signature */ sig[0] = 'C'; sig[1] = 'D'; sig[2] = CONFIGDATA_FORMAT_VERSION; mtdconfig_writebytes(dev, 0, sig, sizeof(sig)); /* Now go try to read the signature again (as verification) */ retrycount++; goto retry; } /* Okay, the Config Data partition is formatted. Check if the * config item being written is already in the database. If it * is, we must mark it as obsolete before creating a new entry. */ offset = mtdconfig_findentry(dev, offset, pdata, &hdr); /* Test if the header was found. */ if (offset > 0 && pdata->id == hdr.id && pdata->instance == hdr.instance) { /* Mark this entry as released */ hdr.flags = (uint8_t)~MTD_ERASED_FLAGS; mtdconfig_writebytes(dev, offset, &hdr.flags, sizeof(hdr.flags)); } /* Test if the new length is zero. If it is, then we are * deleting the entry. */ if (pdata->len == 0) { ret = OK; goto errout; } /* Now find a new entry for this config data */ retrycount = 0; retry_find: offset = mtdconfig_findfirstentry(dev, &hdr); if (offset > 0 && hdr.id == MTD_ERASED_ID) { block = offset / dev->erasesize; bytes_left_in_block = (block + 1) * dev->erasesize - offset; if (bytes_left_in_block < sizeof(hdr) + pdata->len) { /* Simulate an active block to search for the next one * in the code below. */ hdr.id = 1; } } if (hdr.id != MTD_ERASED_ID) { /* Read the next entry */ offset = mtdconfig_findnextentry(dev, offset, &hdr, pdata->len); if (offset == 0) { /* No free entries left on device! */ #ifdef CONFIG_MTD_CONFIG_RAM_CONSOLIDATE ram_consolidate = 1; #else ram_consolidate = dev->neraseblocks == 1; #endif if (ram_consolidate) { /* If we only have 1 erase block, then we must do a RAM * assisted consolidation of released entries. */ if (retrycount) { /* Out of space! */ ret = -ENOMEM; goto errout; } mtdconfig_ramconsolidate(dev); retrycount++; goto retry_find; } #ifndef CONFIG_MTD_CONFIG_RAM_CONSOLIDATE else { if (retrycount) { /* Out of space! */ ret = -ENOMEM; goto errout; } mtdconfig_consolidate(dev); retrycount++; goto retry_find; } #endif } } /* Test if a new entry was found */ if (offset > 0) { /* Save the data at this entry */ hdr.id = pdata->id; hdr.instance = pdata->instance; hdr.len = pdata->len; hdr.flags = MTD_ERASED_FLAGS; //printf("SAV HDR: ID=%04X,%02X Len=%4d Off=%5d\n", // hdr.id, hdr.instance, hdr.len, offset); mtdconfig_writebytes(dev, offset, (uint8_t *)&hdr, sizeof(hdr)); bytes = mtdconfig_writebytes(dev, offset + sizeof(hdr), pdata->configdata, pdata->len); if (bytes != pdata->len) { /* Error writing data! */ hdr.flags = MTD_ERASED_FLAGS; mtdconfig_writebytes(dev, offset, (uint8_t *)&hdr, sizeof(hdr.flags)); ret = -EIO; goto errout; } ret = OK; } errout: /* Free the buffer */ kmm_free(dev->buffer); return ret; }
int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd) { struct ftl_struct_s *dev; char devname[16]; int ret = -ENOMEM; /* Sanity check */ #ifdef CONFIG_DEBUG_FEATURES if (minor < 0 || minor > 255 || !mtd) { return -EINVAL; } #endif /* Allocate a FTL device structure */ dev = (struct ftl_struct_s *)kmm_malloc(sizeof(struct ftl_struct_s)); if (dev) { /* Initialize the FTL device structure */ dev->mtd = mtd; /* Get the device geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->geo)); if (ret < 0) { ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", ret); kmm_free(dev); return ret; } /* Allocate one, in-memory erase block buffer */ #ifdef CONFIG_FS_WRITABLE dev->eblock = (FAR uint8_t *)kmm_malloc(dev->geo.erasesize); if (!dev->eblock) { ferr("ERROR: Failed to allocate an erase block buffer\n"); kmm_free(dev); return -ENOMEM; } #endif /* Get the number of R/W blocks per erase block */ dev->blkper = dev->geo.erasesize / dev->geo.blocksize; DEBUGASSERT(dev->blkper * dev->geo.blocksize == dev->geo.erasesize); /* Configure read-ahead/write buffering */ #ifdef FTL_HAVE_RWBUFFER dev->rwb.blocksize = dev->geo.blocksize; dev->rwb.nblocks = dev->geo.neraseblocks * dev->blkper; dev->rwb.dev = (FAR void *)dev; #if defined(CONFIG_FS_WRITABLE) && defined(CONFIG_FTL_WRITEBUFFER) dev->rwb.wrmaxblocks = dev->blkper; dev->rwb.wrflush = ftl_flush; #endif #ifdef CONFIG_FTL_READAHEAD dev->rwb.rhmaxblocks = dev->blkper; dev->rwb.rhreload = ftl_reload; #endif ret = rwb_initialize(&dev->rwb); if (ret < 0) { ferr("ERROR: rwb_initialize failed: %d\n", ret); kmm_free(dev); return ret; } #endif /* Create a MTD block device name */ snprintf(devname, 16, "/dev/mtdblock%d", minor); /* Inode private data is a reference to the FTL device structure */ ret = register_blockdriver(devname, &g_bops, 0, dev); if (ret < 0) { ferr("ERROR: register_blockdriver failed: %d\n", -ret); kmm_free(dev); } } return ret; }
int configdata_main(int argc, char *argv[]) { unsigned int i; int ret; FAR struct mtd_dev_s *mtd; /* Seed the random number generated */ srand(0x93846); /* Create and initialize a RAM MTD device instance */ #ifdef CONFIG_EXAMPLES_CONFIGDATA_ARCHINIT mtd = configdata_archinitialize(); #else #if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 message("Creating %d byte RAM drive\n", EXAMPLES_CONFIGDATA_BUFSIZE); #endif mtd = rammtd_initialize(g_simflash, EXAMPLES_CONFIGDATA_BUFSIZE); #endif if (!mtd) { message("ERROR: Failed to create RAM MTD instance\n"); msgflush(); exit(1); } /* Initialize to provide CONFIGDATA on an MTD interface */ #if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 message("Registering /dev/config device\n"); #endif MTD_IOCTL(mtd, MTDIOC_BULKERASE, 0); ret = mtdconfig_register(mtd); if (ret < 0) { message("ERROR: /dev/config registration failed: %d\n", -ret); msgflush(); exit(2); } /* Zero out our entry array */ memset(g_entries, 0, sizeof(g_entries)); /* Open the /dev/config device */ g_fd = open("/dev/config", O_RDOK); if (g_fd == -1) { message("ERROR: Failed to open /dev/config %d\n", -errno); msgflush(); exit(2); } /* Initialize the before memory values */ #ifdef CONFIG_CAN_PASS_STRUCTS g_mmbefore = mallinfo(); #else (void)mallinfo(&g_mmbefore); #endif /* Loop seveal times ... create some config data items, delete them * randomly, verify them randomly, add new config items. */ g_ntests = g_nverified = 0; g_ntotaldelete = g_ntotalalloc = 0; #if CONFIG_EXAMPLES_CONFIGDATA_NLOOPS == 0 for (i = 0; ; i++) #else for (i = 1; i <= CONFIG_EXAMPLES_CONFIGDATA_NLOOPS; i++) #endif { /* Write config data to the /dev/config device until either (1) all of the * open file structures are utilized or until (2) CONFIGDATA reports an error * (hopefully that the /dev/config device is full) */ #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT message("\n=== FILLING %d =============================\n", i); #endif ret = configdata_fillconfig(); #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT message("Filled /dev/config\n"); message(" Number of entries: %d\n", g_nentries); #endif /* Verify all files entries to FLASH */ ret = configdata_verifyconfig(); if (ret < 0) { message("ERROR: Failed to verify partition\n"); message(" Number of entries: %d\n", g_nentries); } else { #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT #if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 message("Verified!\n"); message(" Number of entries: %d\n", g_nentries); #endif #endif } /* Delete some entries */ #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT message("\n=== DELETING %d ============================\n", i); #endif ret = configdata_delentries(); if (ret < 0) { message("ERROR: Failed to delete enries\n"); message(" Number of entries: %d\n", g_nentries); message(" Number deleted: %d\n", g_ndeleted); } else { #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT message("Deleted some enries\n"); message(" Number of entries: %d\n", g_nentries); message(" Number deleted: %d\n", g_ndeleted); #endif } /* Verify all files written to FLASH */ ret = configdata_verifyconfig(); if (ret < 0) { message("ERROR: Failed to verify partition\n"); message(" Number of entries: %d\n", g_nentries); message(" Number deleted: %d\n", g_ndeleted); } else { #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT #if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 message("Verified!\n"); message(" Number of entries: %d\n", g_nentries); message(" Number deleted: %d\n", g_ndeleted); #endif #endif } /* Clear deleted entries */ configdata_cleardeleted(); /* Show memory usage */ #ifndef CONFIG_EXAMPLES_CONFIGDATA_SILENT configdata_loopmemusage(); msgflush(); #else if ((i % EXAMPLES_CONFIGDATA_REPORT) == 0) { message("%d\n", i); msgflush(); } #endif } /* Delete all files then show memory usage again */ //configdata_delallfiles(); configdata_endmemusage(); msgflush(); return 0; }
int nxffs_dump(FAR struct mtd_dev_s *mtd, bool verbose) { #if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_FS) struct nxffs_blkinfo_s blkinfo; int ret; /* Get the volume geometry. (casting to uintptr_t first eliminates * complaints on some architectures where the sizeof long is different * from the size of a pointer). */ memset(&blkinfo, 0, sizeof(struct nxffs_blkinfo_s)); ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&blkinfo.geo)); if (ret < 0) { ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret); return ret; } /* Save the verbose output indication */ blkinfo.verbose = verbose; /* Allocate a buffer to hold one block */ blkinfo.buffer = (FAR uint8_t *)kmm_malloc(blkinfo.geo.blocksize); if (!blkinfo.buffer) { ferr("ERROR: Failed to allocate block cache\n"); return -ENOMEM; } /* Now read every block on the device */ syslog(LOG_NOTICE, "NXFFS Dump:\n"); syslog(LOG_NOTICE, g_hdrformat); blkinfo.nblocks = blkinfo.geo.erasesize * blkinfo.geo.neraseblocks / blkinfo.geo.blocksize; for (blkinfo.block = 0, blkinfo.offset = 0; blkinfo.block < blkinfo.nblocks; blkinfo.block++, blkinfo.offset += blkinfo.geo.blocksize) { /* Read the next block */ ret = MTD_BREAD(mtd, blkinfo.block, 1, blkinfo.buffer); if (ret < 0) { #ifndef CONFIG_NXFFS_NAND /* Read errors are fatal */ ferr("ERROR: Failed to read block %d\n", blkinfo.block); kmm_free(blkinfo.buffer); return ret; #else /* A read error is probably fatal on all media but NAND. * On NAND, the read error probably just signifies a block * with an uncorrectable ECC failure. So, to handle NAND, * just report the read error and continue. */ syslog(LOG_NOTICE, g_format, blkinfo.block, 0, "BLOCK", "RD FAIL", blkinfo.geo.blocksize); #endif } else { /* Analyze the block that we just read */ nxffs_analyze(&blkinfo); } } syslog(LOG_NOTICE, "%d blocks analyzed\n", blkinfo.nblocks); kmm_free(blkinfo.buffer); return OK; #else return -ENOSYS; #endif }