michallenc commented on PR #16642:
URL: https://github.com/apache/nuttx/pull/16642#issuecomment-3061900079

   > > I replaced `ftl_initialize` and `bchdev_register` with 
`register_mtddriver` call, but it seems all data are now written to a 
pseudofile in RAM memory, not to the physical device. I did the same changes as 
you in `boards/arm/samv7/common/src/sam_progmem.c`, so the registration process 
should be fine (also tested on progmem, that has same issues). Maybe we should 
use `register_partition_with_mtd` or `register_mtdpartition` here instead of 
`register_mtddriver`?
   > 
   > @michallenc It's my mistake. Yes, you're absolutely right—there is indeed 
an issue here. From the context, the code is trying to create sub-partition 
devices based on the main MTD device progmem_mtd. I will fix this on my end. By 
the way, do you have this hardware board?
   > 
   > @michallenc Wait, the issue might not be in the registration itself. I 
noticed that `register_partition_with_mtd` ultimately calls `register_mtddriver 
`internally. We don't need `register_partition_with_mtd` here—instead, we 
should directly use `register_mtddriver` because `mtd_partition `is already 
initialized in `boards/arm/samv7/common/src/sam_progmem.c`.
   > 
   > @michallenc Could you give me some more information about this: _all data 
are now written to a pseudofile in RAM memory, not to the physical device_
   
   Sure, I am sorry, I should have specified this better. This is the file for 
initialization of w25q nor flash. It's quite large, the important part is in 
`sam_w25qxxxjv_init`. I did the same as you in 
`boards/arm/samv7/common/src/sam_progmem.c`, replaced FTL/BCH init with one 
call to MTD layer.
   
   ```C
   #include <nuttx/config.h>
   
   #include <stdio.h>
   #include <stdbool.h>
   #include <syslog.h>
   #include <assert.h>
   #include <debug.h>
   #include <errno.h>
   
   #include <nuttx/arch.h>
   #include <nuttx/board.h>
   #include <nuttx/drivers/drivers.h>
   #include <nuttx/mtd/mtd.h>
   #include <nuttx/spi/qspi.h>
   #include <nuttx/net/usrsock.h>
   
   #include <nuttx/fs/ioctl.h>
   #include <nuttx/fs/smart.h>
   #include <sys/ioctl.h>
   #include <sys/stat.h>
   #include <fcntl.h>
   #include <unistd.h>
   
   #include "sam_qspi.h"
   #include "sam_board.h"
   #include "board_progmem.h" /* For struct mtd_partition_s definition */
   
   #define QSPI_PORTNO 0
   
   typedef enum
     {
       MTD_TYPE_BCH,
       MTD_TYPE_SMARTFS,
     } mtd_types;
   
   static struct mtd_partition_s g_mtd_partition_table[] =
   {
     {
       .size    = CONFIG_BOARD_SLOT_SIZE, /* 1966 KiB, MCUboot partition */
       .devpath = "/dev/ota1",
       .type    = MTD_TYPE_BCH,
     },
     {
       .size    = CONFIG_BOARD_SLOT_SIZE, /* 1966 KiB, MCUboot partition */
       .devpath = "/dev/ota2",
       .type    = MTD_TYPE_BCH,
     },
     {
       .size    = 0x8000, /* 32KiB */
       .devpath = "/etc",
       .type    = MTD_TYPE_SMARTFS,
     },
     {
       .size    = 0x800000, /* 8MiB */
       .devpath = "/dev/mtdlog_maintenance",
       .type    = MTD_TYPE_BCH,
     },
     {
       .size    = 0x8000, /* 32 KiB */
       .devpath = "/dev/mtdtest",
       .type    = MTD_TYPE_BCH,
     },
     {
       .size    = 0, /* Calculate the rest of the size */
       .devpath = "/dev/mtdlog_trace",
       .type    = MTD_TYPE_BCH,
     }
   };
   
   static const size_t g_mtd_partition_table_size =
       nitems(g_mtd_partition_table);
   
   #ifdef CONFIG_FS_SMARTFS
   static int issmartfs(FAR const char *pathname)
   {
     struct smart_format_s fmt;
     int fd;
     int ret;
   
     /* Find the inode of the block driver identified by 'source' */
   
     fd = open(pathname, O_RDONLY);
     if (fd < 0)
       {
         return ERROR;
       }
   
     /* Get the format information so we know the block have been formatted */
   
     ret = ioctl(fd, BIOC_GETFORMAT, (unsigned long)&fmt);
     if (ret < 0)
       {
         close(fd);
         return ret;
       }
   
     if (!(fmt.flags & SMART_FMT_ISFORMATTED))
       {
         errno = EFTYPE;
         ret = ERROR;
       }
   
     close(fd);
     return ret;
   }
   
   static int mksmartfs(FAR const char *pathname, uint16_t sectorsize)
   {
     struct smart_format_s fmt;
     struct smart_read_write_s request;
     uint8_t type;
     int fd;
     int ret;
   
     /* Find the inode of the block driver identified by 'pathname' */
   
     fd = open(pathname, O_RDWR);
     if (fd < 0)
       {
         ret = -ENOENT;
         goto errout;
       }
   
     /* Perform a low-level SMART format */
   
     ret = ioctl(fd, BIOC_LLFORMAT, sectorsize << 16);
     if (ret != OK)
       {
         ret = -errno;
         goto errout_with_driver;
       }
   
     /* Get the format information so we know how big the sectors are */
   
     ret = ioctl(fd, BIOC_GETFORMAT, (unsigned long) &fmt);
     if (ret != OK)
       {
         ret = -errno;
         goto errout_with_driver;
       }
   
     /* Now write the filesystem to media. */
   
     ret = ioctl(fd, BIOC_ALLOCSECT, SMARTFS_ROOT_DIR_SECTOR);
     if (ret != SMARTFS_ROOT_DIR_SECTOR)
       {
         ret = -EIO;
         goto errout_with_driver;
       }
   
     /* Mark this block as a directory entry */
   
     type = SMARTFS_SECTOR_TYPE_DIR;
     request.offset = 0;
     request.count = 1;
     request.buffer = &type;
     request.logsector = SMARTFS_ROOT_DIR_SECTOR;
   
     /* Issue a write to the sector, single byte */
   
     ret = ioctl(fd, BIOC_WRITESECT, (unsigned long) &request);
     if (ret != OK)
       {
         ret = -EIO;
         goto errout_with_driver;
       }
   
   errout_with_driver:
   
     /* Close the driver */
   
     close(fd);
   
   errout:
   
     /* Return any reported errors */
   
     if (ret < 0)
       {
         errno = -ret;
         return ERROR;
       }
   
     return OK;
   }
   #endif /* CONFIG_FS_SMARTFS */
   
   static struct mtd_dev_s
   *sam_w25qxxxjv_alloc_mtdpart(struct mtd_dev_s *mtd,
                                struct mtd_geometry_s *geo,
                                struct mtd_partition_s
                                *part)
   {
     ASSERT((part->offset + part->size) <= geo->neraseblocks * geo->erasesize);
     ASSERT((part->offset % geo->erasesize) == 0);
     ASSERT((part->size % geo->erasesize) == 0);
   
     size_t startblock = part->offset / geo->blocksize;
     size_t blocks = part->size / geo->blocksize;
   
     return mtd_partition(mtd, startblock, blocks);
   }
   
   int sam_w25qxxxjv_init(void)
   {
     int ret = OK;
   #ifdef CONFIG_FS_SMARTFS
     char  partref[4];
     char  smartfs_path[30];
   #endif
   
     struct qspi_dev_s *qspi = sam_qspi_initialize(QSPI_PORTNO);
     if (!qspi)
       {
         syslog(LOG_ERR, "ERROR: sam_qspi_initialize failed\n");
         return ERROR;
       }
   
     /* Use the QSPI device instance to initialize the W25QxxJV device.  */
   
     struct mtd_dev_s *mtd = w25qxxxjv_initialize(qspi, true);
     if (!mtd)
       {
         syslog(LOG_ERR, "ERROR: w25qxxxjv_initialize failed\n");
         return ERROR;
       }
   
     /* Get geometry of W25QxxxJV */
   
     struct mtd_geometry_s geometry;
     ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)&geometry);
     if (ret < 0)
       {
         syslog(LOG_ERR, "ERROR: w25qxxxjv ioctl failed: %s\n",
                strerror(errno));
         return ret;
       }
   
     size_t i;
     size_t offset = 0;
     for (i = 0; i < g_mtd_partition_table_size; i++)
       {
         struct mtd_partition_s *part = &g_mtd_partition_table[i];
         part->offset = offset;
         if (part->size == 0)
           {
             part->size = (geometry.neraseblocks * geometry.erasesize) - offset;
           }
   
         part->mtd = sam_w25qxxxjv_alloc_mtdpart(mtd, &geometry, part);
         if (!part->mtd)
           {
             syslog(LOG_ERR, "ERROR: sam_w25qxxxjv_alloc_mtdpart failed\n");
             return ERROR;
           }
   
         /* Use the FTL layer to wrap the MTD driver as a block driver */
   
         if (part->type == MTD_TYPE_BCH)
           {
               ret = register_mtddriver(part->devpath, part->mtd, 0755, NULL);
               if (ret < 0)
                 {
                   syslog(LOG_ERR, "ERROR: failed to register mtd %d", ret);
                   return ret;
                 }
   //          ret = ftl_initialize(W25QXXJV_MTD_MINOR + i, part->mtd);
   //          if (ret < 0)
   //            {
   //              syslog(LOG_ERR, "ERROR: Failed to initialize FTL layer: 
%d\n",
   //                    ret);
   //              return ret;
   //            }
   //
   //          /* Now create a character device on the block device */
   //
   //#if defined(CONFIG_BCH)
   //              char blockdev[18];
   //              snprintf(blockdev, sizeof(blockdev), "/dev/mtdblock%d",
   //                      W25QXXJV_MTD_MINOR + i);
   //              ret = bchdev_register(blockdev, part->devpath, false);
   //              if (ret < 0)
   //                {
   //                  syslog(LOG_ERR, "ERROR: bchdev_register %s failed: %d\n",
   //                        part->devpath, ret);
   //                  return ret;
   //                }
   //#endif /* defined(CONFIG_BCH) */
           }
         else if (part->type == MTD_TYPE_SMARTFS)
           {
   #if defined (CONFIG_FS_SMARTFS)
             sprintf(partref, "p%d", i);
             ret = smart_initialize(0, part->mtd, partref);
             if (ret < 0)
               {
                 syslog(LOG_ERR, "ERROR: smart_initialize %s failed: %d\n",
                       part->devpath, ret);
                 return ret;
               }
   
             sprintf(smartfs_path, "/dev/smart0%s", partref);
             if (issmartfs(smartfs_path) != OK)
               {
                 mksmartfs(smartfs_path, 0);
               }
   
             ret = nx_mount(smartfs_path, part->devpath, "smartfs", 0,
                             NULL);
             if (ret < 0)
               {
                 /* Mount failed. */
   
                 syslog(LOG_ERR, "ERROR: mount %s failed: %d\n", smartfs_path,
                           ret);
                 return ret;
               }
   #endif
           }
         else
           {
             syslog(LOG_ERR, "ERROR: Incorrect device type %d for %s.\n",
                    part->type, part->devpath);
           }
   
         offset += part->size;
       }
   
     return ret;
   }
   ```
   
   Then I have a simple application (see below) that writes to the flash.
   
   ```C
   #include <nuttx/config.h>
   #include <fcntl.h>
   #include <unistd.h>
   #include <stdio.h>
   #include <errno.h>
   
   int main(int argc, FAR char *argv[])
   {
     int ret = 0;
   
     int fd = open("/dev/mtdtest", O_RDWR | O_DIRECT);
     if (fd < 0) {
       printf("failed to open %d", errno);
       return -1;
     }
   
     char buf[4] = {0x33, 0x22, 0x00, 0xab};
     ret = write(fd, buf, sizeof buf);
     if (ret < 0) {
       printf("failed to write: %d\n", errno);
     }
   
     lseek(fd, 32, SEEK_SET);
     ret = write(fd, buf, sizeof buf);
     if (ret < 0) {
       printf("failed to write: %d\n", errno);
     }
   
     buf[0] = 0xff;
     ret = write(fd, buf, sizeof buf);
     if (ret < 0) {
       printf("failed to write: %d\n", errno);
     }
   
     lseek(fd, -4, SEEK_CUR);
     buf[0] &= ~(1 << 7);
     ret = write(fd, &buf[0], 1);
     if (ret < 0) {
       printf("failed to write: %d\n", errno);
     }
   
     close(fd);
     return 0;
   }
   ```
   
   But instead of reading the data back with `hexdump`, I read just `0xff` and 
some memory is consumed during each write. Thus the idea it writes to some 
pseudofile instead of real flash.
   
   ```
   brcg2> free
         total       used       free    maxused    maxfree  nused  nfree name
        323260     174268     148992     180816     144144   1493     17 Umem
   brcg2> confirm_image
   brcg2> hexdump /dev/mtdtest count=48
   /dev/mtdtest at 00000000:
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
   0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
   0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
   brcg2> free
         total       used       free    maxused    maxfree  nused  nfree name
        323260     175076     148184     180816     143880   1504     16 Umem
   brcg2> confirm_image
   brcg2> hexdump /dev/mtdtest count=48
   /dev/mtdtest at 00000000:
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
   0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
   0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
   brcg2> free
         total       used       free    maxused    maxfree  nused  nfree name
        323260     175884     147376     180816     143424   1515     16 Umem
   brcg2> 
   ```
   
   I saw the same behavior on `boards/arm/samv7/common/src/sam_progmem.c` so I 
don't expect this is driver related. Maybe some configuration mistake on my 
part? But I have `CONFIG_BCH` and `CONFIG_MTD` enabled and disabled buffers in 
FTL layer.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to