fs/procfs/fs_procfsprogrem: Add /proc/progmem. This is an alternative way to get the information that was previoulsy available in apps/system/free. apps/system/free was removed beause it made illegal calls into the OS violating the portable interface. This new procfs entry provides the same information with no such violation.

This commit is contained in:
Gregory Nutt 2017-11-13 09:08:39 -06:00
parent bfcc8fcbb6
commit f3b37e5da3
10 changed files with 431 additions and 11 deletions

View File

@ -194,6 +194,10 @@ config ARCH_HAVE_POWEROFF
bool
default n
config ARCH_HAVE_PROGMEM
bool
default n
config ARCH_HAVE_RESET
bool
default n

View File

@ -244,9 +244,10 @@ config ARCH_CHIP_STM32
select ARCH_HAVE_MPU
select ARCH_HAVE_I2CRESET
select ARCH_HAVE_HEAPCHECK
select ARCH_HAVE_PROGMEM
select ARCH_HAVE_SPI_BITORDER
select ARCH_HAVE_TICKLESS
select ARCH_HAVE_TIMEKEEPING
select ARCH_HAVE_SPI_BITORDER
select ARM_HAVE_MPU_UNIFIED
select ARMV7M_HAVE_STACKCHECK
---help---
@ -275,13 +276,14 @@ config ARCH_CHIP_STM32F7
config ARCH_CHIP_STM32L4
bool "STMicro STM32 L4"
select ARCH_HAVE_CMNVECTOR
select ARCH_CORTEXM4
select ARCH_HAVE_MPU
select ARCH_HAVE_CMNVECTOR
select ARCH_HAVE_I2CRESET
select ARCH_HAVE_HEAPCHECK
select ARCH_HAVE_TICKLESS
select ARCH_HAVE_MPU
select ARCH_HAVE_PROGMEM
select ARCH_HAVE_SPI_BITORDER
select ARCH_HAVE_TICKLESS
select ARM_HAVE_MPU_UNIFIED
select ARMV7M_CMNVECTOR
select ARMV7M_HAVE_STACKCHECK

View File

@ -135,6 +135,7 @@ config EFM32_RMU
config EFM32_FLASHPROG
bool "Enable Erase/Write flash function (MSC) "
default n
select ARCH_HAVE_PROGMEM
select ARCH_HAVE_RAMFUNCS
config EFM32_RMU_DEBUG

View File

@ -753,6 +753,8 @@ endif # SAMV7_WDT || SAMV7_RSWDT
menuconfig SAMV7_PROGMEM
bool "FLASH program memory"
default n
select ARCH_HAVE_PROGMEM
---help---
Enable support FLASH interfaces as defined in include/nuttx/progmem.h

View File

@ -49,9 +49,7 @@
#include <nuttx/fs/ioctl.h>
#include <nuttx/mtd/mtd.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_ARCH_HAVE_PROGMEM
/****************************************************************************
* Private Types
@ -102,6 +100,7 @@ static int progmem_ioctl(FAR struct mtd_dev_s *dev, int cmd,
/****************************************************************************
* Private Data
****************************************************************************/
/* This structure holds the state of the MTD driver */
static struct progmem_dev_s g_progmem =
@ -411,3 +410,5 @@ FAR struct mtd_dev_s *progmem_initialize(void)
return (FAR struct mtd_dev_s *)priv;
}
#endif /* CONFIG_ARCH_HAVE_PROGMEM */

View File

@ -90,10 +90,10 @@ config FS_PROCFS_EXCLUDE_NET
depends on NET
default n
config FS_PROCFS_EXCLUDE_ROUTE
bool "Exclude routing table"
depends on !FS_PROCFS_EXCLUDE_NET && NET_ROUTE
default n
config FS_PROCFS_EXCLUDE_PROGMEM
bool "Exclude progmem"
depends on ARCH_HAVE_PROGMEM
default y
config FS_PROCFS_EXCLUDE_MTD
bool "Exclude mtd"
@ -105,6 +105,11 @@ config FS_PROCFS_EXCLUDE_PARTITIONS
depends on MTD_PARTITION
default n
config FS_PROCFS_EXCLUDE_ROUTE
bool "Exclude routing table"
depends on !FS_PROCFS_EXCLUDE_NET && NET_ROUTE
default n
config FS_PROCFS_EXCLUDE_SMARTFS
bool "Exclude fs/smartfs"
depends on FS_SMARTFS

View File

@ -40,6 +40,10 @@ ASRCS +=
CSRCS += fs_procfs.c fs_procfsutil.c fs_procfsproc.c fs_procfsuptime.c
CSRCS += fs_procfscpuload.c fs_procfskmm.c
ifeq ($(CONFIG_ARCH_HAVE_PROGMEM),y)
CSRCS += fs_procfsprogmem.c
endif
# Include procfs build support
DEPPATH += --dep-path procfs

View File

@ -79,6 +79,7 @@
extern const struct procfs_operations proc_operations;
extern const struct procfs_operations cpuload_operations;
extern const struct procfs_operations kmm_operations;
extern const struct procfs_operations progmem_operations;
extern const struct procfs_operations module_operations;
extern const struct procfs_operations uptime_operations;
@ -165,6 +166,10 @@ static const struct procfs_entry_s g_procfs_entries[] =
{ "partitions", &part_procfsoperations, PROCFS_FILE_TYPE },
#endif
#if defined(CONFIG_ARCH_HAVE_PROGMEM) && !defined(CONFIG_FS_PROCFS_EXCLUDE_PROGMEM)
{ "progmem", &progmem_operations, PROCFS_FILE_TYPE },
#endif
#if !defined(CONFIG_FS_PROCFS_EXCLUDE_UPTIME)
{ "uptime", &uptime_operations, PROCFS_FILE_TYPE },
#endif

View File

@ -0,0 +1,393 @@
/****************************************************************************
* fs/procfs/fs_procfsprogmem.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/progmem.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#if defined(CONFIG_ARCH_HAVE_PROGMEM) && !defined(CONFIG_FS_PROCFS_EXCLUDE_PROGMEM)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Determines the size of an intermediate buffer that must be large enough
* to handle the longest line generated by this logic.
*/
#define PROGMEM_LINELEN 54
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure describes one open "file" */
struct progmem_file_s
{
struct procfs_file_s base; /* Base open file structure */
unsigned int linesize; /* Number of valid characters in line[] */
char line[PROGMEM_LINELEN]; /* Pre-allocated buffer for formatted lines */
};
struct progmem_info_s
{
int arena; /* Total size of available progmem. */
int ordblks; /* This is the number of free chunks */
int mxordblk; /* Size of the largest free chunk */
int uordblks; /* Total size of memory for allocated chunks */
int fordblks; /* Total size of memory for free chunks.*/
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void progmem_getinfo(FAR struct progmem_info_s *progmem);
/* File system methods */
static int progmem_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int progmem_close(FAR struct file *filep);
static ssize_t progmem_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static int progmem_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int progmem_stat(FAR const char *relpath, FAR struct stat *buf);
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/* See fs_mount.c -- this structure is explicitly externed there.
* We use the old-fashioned kind of initializers so that this will compile
* with any compiler.
*/
const struct procfs_operations progmem_operations =
{
progmem_open, /* open */
progmem_close, /* close */
progmem_read, /* read */
NULL, /* write */
progmem_dup, /* dup */
NULL, /* opendir */
NULL, /* closedir */
NULL, /* readdir */
NULL, /* rewinddir */
progmem_stat /* stat */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: progmem_getinfo
*
* Description:
* The moral equivalent of mallinfo() for prog mem
*
* TODO Max block size only works on uniform prog mem
*
****************************************************************************/
static void progmem_getinfo(FAR struct progmem_info_s *progmem)
{
size_t page = 0;
size_t stpage = 0xffff;
size_t pagesize = 0;
ssize_t status;
progmem->arena = 0;
progmem->fordblks = 0;
progmem->uordblks = 0;
progmem->mxordblk = 0;
for (status = 0, page = 0; status >= 0; page++)
{
status = up_progmem_ispageerased(page);
pagesize = up_progmem_pagesize(page);
progmem->arena += pagesize;
/* Is this beginning of new free space section */
if (status == 0)
{
if (stpage == 0xffff)
{
stpage = page;
}
progmem->fordblks += pagesize;
}
else if (status != 0)
{
progmem->uordblks += pagesize;
if (stpage != 0xffff && up_progmem_isuniform())
{
stpage = page - stpage;
if (stpage > progmem->mxordblk)
{
progmem->mxordblk = stpage;
}
stpage = 0xffff;
}
}
}
progmem->mxordblk *= pagesize;
}
/****************************************************************************
* Name: progmem_open
****************************************************************************/
static int progmem_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
FAR struct progmem_file_s *procfile;
finfo("Open '%s'\n", relpath);
/* PROCFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*
* REVISIT: Write-able proc files could be quite useful.
*/
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
{
ferr("ERROR: Only O_RDONLY supported\n");
return -EACCES;
}
/* "progmem" is the only acceptable value for the relpath */
if (strcmp(relpath, "progmem") != 0)
{
ferr("ERROR: relpath is '%s'\n", relpath);
return -ENOENT;
}
/* Allocate a container to hold the file attributes */
procfile = (FAR struct progmem_file_s *)
kmm_zalloc(sizeof(struct progmem_file_s));
if (procfile == NULL)
{
ferr("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* Save the attributes as the open-specific state in filep->f_priv */
filep->f_priv = (FAR void *)procfile;
return OK;
}
/****************************************************************************
* Name: progmem_close
****************************************************************************/
static int progmem_close(FAR struct file *filep)
{
FAR struct progmem_file_s *procfile;
/* Recover our private data from the struct file instance */
procfile = (FAR struct progmem_file_s *)filep->f_priv;
DEBUGASSERT(procfile);
/* Release the file attributes structure */
kmm_free(procfile);
filep->f_priv = NULL;
return OK;
}
/****************************************************************************
* Name: progmem_read
****************************************************************************/
static ssize_t progmem_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
FAR struct progmem_file_s *procfile;
struct progmem_info_s progmem;
size_t linesize;
size_t copysize;
size_t totalsize;
off_t offset;
finfo("buffer=%p buflen=%d\n", buffer, (int)buflen);
DEBUGASSERT(filep != NULL && buffer != NULL && buflen > 0);
offset = filep->f_pos;
/* Recover our private data from the struct file instance */
procfile = (FAR struct progmem_file_s *)filep->f_priv;
DEBUGASSERT(procfile);
/* The first line is the headers */
linesize = snprintf(procfile->line, PROGMEM_LINELEN,
" total used free largest\n");
copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen,
&offset);
totalsize = copysize;
if (totalsize < buflen)
{
buffer += copysize;
buflen -= copysize;
/* The second line is the memory data */
progmem_getinfo(&progmem);
linesize = snprintf(procfile->line, PROGMEM_LINELEN,
"Prog: %11d%11d%11d%11d\n",
progmem.arena, progmem.uordblks, progmem.fordblks,
progmem.mxordblk);
copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen,
&offset);
totalsize += copysize;
}
/* Update the file offset */
filep->f_pos += totalsize;
return totalsize;
}
/****************************************************************************
* Name: progmem_dup
*
* Description:
* Duplicate open file data in the new file structure.
*
****************************************************************************/
static int progmem_dup(FAR const struct file *oldp, FAR struct file *newp)
{
FAR struct progmem_file_s *oldattr;
FAR struct progmem_file_s *newattr;
finfo("Dup %p->%p\n", oldp, newp);
/* Recover our private data from the old struct file instance */
oldattr = (FAR struct progmem_file_s *)oldp->f_priv;
DEBUGASSERT(oldattr);
/* Allocate a new container to hold the task and attribute selection */
newattr = (FAR struct progmem_file_s *)
kmm_malloc(sizeof(struct progmem_file_s));
if (!newattr)
{
ferr("ERROR: Failed to allocate file attributes\n");
return -ENOMEM;
}
/* The copy the file attributes from the old attributes to the new */
memcpy(newattr, oldattr, sizeof(struct progmem_file_s));
/* Save the new attributes in the new file structure */
newp->f_priv = (FAR void *)newattr;
return OK;
}
/****************************************************************************
* Name: progmem_stat
*
* Description: Return information about a file or directory
*
****************************************************************************/
static int progmem_stat(FAR const char *relpath, FAR struct stat *buf)
{
/* "progmem" is the only acceptable value for the relpath */
if (strcmp(relpath, "progmem") != 0)
{
ferr("ERROR: relpath is '%s'\n", relpath);
return -ENOENT;
}
/* "progmem" is the name for a read-only file */
memset(buf, 0, sizeof(struct stat));
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
#endif /* CONFIG_ARCH_HAVE_PROGMEM && !CONFIG_FS_PROCFS_EXCLUDE_PROGMEM */

View File

@ -45,6 +45,8 @@
#include <stdbool.h>
#ifdef CONFIG_ARCH_HAVE_PROGMEM
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -207,4 +209,5 @@ ssize_t up_progmem_write(size_t addr, FAR const void *buf, size_t count);
}
#endif
#endif /* CONFIG_ARCH_HAVE_PROGMEM */
#endif /* __INCLUDE_NUTTX_PROGMEM_H */