diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index eb195233d38..ed3a8ae7e50 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -104,6 +104,11 @@ config XTENSA_IMEM_REGION_SIZE range 0x2000 0x28000 default 0x28000 +config XTENSA_IMEM_PROCFS + bool "Internal memory PROCFS support" + default n + depends on XTENSA_USE_SEPERATE_IMEM && !DISABLE_MOUNTPOINT && FS_PROCFS && FS_PROCFS_REGISTER + source arch/xtensa/src/lx6/Kconfig if ARCH_CHIP_ESP32 source arch/xtensa/src/esp32/Kconfig diff --git a/arch/xtensa/include/arch.h b/arch/xtensa/include/arch.h index 1db25d4dda9..919f4dad5e6 100644 --- a/arch/xtensa/include/arch.h +++ b/arch/xtensa/include/arch.h @@ -92,11 +92,15 @@ extern "C" #endif #ifdef CONFIG_XTENSA_USE_SEPERATE_IMEM + +struct mallinfo; /* Forward reference, see malloc.h */ + void up_imm_initialize(void); FAR void *up_imm_malloc(size_t size); void up_imm_free(FAR void *mem); FAR void *up_imm_memalign(size_t alignment, size_t size); bool up_imm_heapmember(FAR void *mem); +int up_imm_mallinfo(FAR struct mallinfo *info); #endif #undef EXTERN diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 0a9f3f73458..cbb8c5141ee 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -149,6 +149,10 @@ CHIP_CSRCS += esp32_tim_lowerhalf.c endif endif +ifeq ($(CONFIG_XTENSA_IMEM_PROCFS),y) +CHIP_CSRCS += esp32_procfs_imm.c +endif + ifeq ($(CONFIG_ARCH_USE_MODULE_TEXT),y) CHIP_CSRCS += esp32_modtext.c CMN_ASRCS += xtensa_loadstore.S diff --git a/arch/xtensa/src/esp32/esp32_imm.c b/arch/xtensa/src/esp32/esp32_imm.c index d7487b16e9c..8760179a97a 100644 --- a/arch/xtensa/src/esp32/esp32_imm.c +++ b/arch/xtensa/src/esp32/esp32_imm.c @@ -26,6 +26,8 @@ #include #include +#include + #include "xtensa.h" #if CONFIG_XTENSA_USE_SEPERATE_IMEM @@ -116,4 +118,19 @@ bool up_imm_heapmember(FAR void *mem) { return mm_heapmember(&g_iheap, mem); } + +/**************************************************************************** + * Name: up_imm_mallinfo + * + * Description: + * mallinfo returns a copy of updated current heap information for the + * user heap. + * + ****************************************************************************/ + +int up_imm_mallinfo(FAR struct mallinfo *info) +{ + return mm_mallinfo(&g_iheap, info); +} + #endif /* CONFIG_XTENSA_USE_SEPERATE_IMEM */ diff --git a/arch/xtensa/src/esp32/esp32_procfs_imm.c b/arch/xtensa/src/esp32/esp32_procfs_imm.c new file mode 100644 index 00000000000..65e6183fdb6 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_procfs_imm.c @@ -0,0 +1,319 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_procfs_imm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) && \ + defined(CONFIG_FS_PROCFS_REGISTER) && defined(CONFIG_XTENSA_IMEM_PROCFS) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMM_LINELEN 64 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This enumeration identifies all of the thread attributes that can be + * accessed via the procfs file system. + */ + +/* This structure describes one open "file" */ + +struct imm_file_s +{ + struct procfs_file_s base; /* Base open file structure */ + unsigned int linesize; /* Number of valid characters in line[] */ + char line[IMM_LINELEN]; /* Pre-allocated buffer for formatted lines */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* File system methods */ + +static int imm_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int imm_close(FAR struct file *filep); +static ssize_t imm_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static int imm_dup(FAR const struct file *oldp, + FAR struct file *newp); +static int imm_stat(FAR const char *relpath, FAR struct stat *buf); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* See include/nutts/fs/procfs.h */ + +static const struct procfs_operations imm_procfsoperations = +{ + imm_open, /* open */ + imm_close, /* close */ + imm_read, /* read */ + NULL, /* write */ + imm_dup, /* dup */ + NULL, /* opendir */ + NULL, /* closedir */ + NULL, /* readdir */ + NULL, /* rewinddir */ + imm_stat /* stat */ +}; + +static const struct procfs_entry_s g_procfs_imm = +{ + "imm", + &imm_procfsoperations +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imm_open + ****************************************************************************/ + +static int imm_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct imm_file_s *priv; + + 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; + } + + /* "imm" is the only acceptable value for the relpath */ + + if (strcmp(relpath, "imm") != 0) + { + ferr("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + /* Allocate a container to hold the task and attribute selection */ + + priv = (FAR struct imm_file_s *)kmm_zalloc(sizeof(struct imm_file_s)); + if (!priv) + { + ferr("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* Save the index as the open-specific state in filep->f_priv */ + + filep->f_priv = (FAR void *)priv; + return OK; +} + +/**************************************************************************** + * Name: imm_close + ****************************************************************************/ + +static int imm_close(FAR struct file *filep) +{ + FAR struct imm_file_s *priv; + + /* Recover our private data from the struct file instance */ + + priv = (FAR struct imm_file_s *)filep->f_priv; + DEBUGASSERT(priv); + + /* Release the file attributes structure */ + + kmm_free(priv); + filep->f_priv = NULL; + return OK; +} + +/**************************************************************************** + * Name: imm_read + ****************************************************************************/ + +static ssize_t imm_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct imm_file_s *priv; + size_t linesize; + size_t copysize; + size_t remaining; + size_t totalsize; + struct mallinfo mem; + off_t offset = filep->f_pos; + + finfo("buffer=%p buflen=%d\n", buffer, (int)buflen); + + /* Recover our private data from the struct file instance */ + + priv = (FAR struct imm_file_s *)filep->f_priv; + DEBUGASSERT(priv); + + up_imm_mallinfo(&mem); + + remaining = buflen; + totalsize = 0; + + linesize = snprintf(priv->line, + IMM_LINELEN, + " total used free largest\n"); + copysize = procfs_memcpy(priv->line, linesize, buffer, remaining, &offset); + totalsize += copysize; + buffer += copysize; + remaining -= copysize; + + if (totalsize >= buflen) + { + return totalsize; + } + + linesize = snprintf(priv->line, + IMM_LINELEN, + "Mem: %11d%11d%11d%11d\n", + mem.arena, + mem.uordblks, + mem.fordblks, + mem.mxordblk); + copysize = procfs_memcpy(priv->line, linesize, buffer, remaining, &offset); + totalsize += copysize; + + /* Update the file offset */ + + if (totalsize > 0) + { + filep->f_pos += totalsize; + } + + return totalsize; +} + +/**************************************************************************** + * Name: imm_dup + ****************************************************************************/ + +static int imm_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct imm_file_s *oldpriv; + FAR struct imm_file_s *newpriv; + + finfo("Dup %p->%p\n", oldp, newp); + + /* Recover our private data from the old struct file instance */ + + oldpriv = (FAR struct imm_file_s *)oldp->f_priv; + DEBUGASSERT(oldpriv); + + /* Allocate a new container to hold the task and attribute selection */ + + newpriv = (FAR struct imm_file_s *)kmm_zalloc(sizeof(struct imm_file_s)); + if (!newpriv) + { + ferr("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* The copy the file attributes from the old attributes to the new */ + + memcpy(newpriv, oldpriv, sizeof(struct imm_file_s)); + + /* Save the new attributes in the new file structure */ + + newp->f_priv = (FAR void *)newpriv; + return OK; +} + +/**************************************************************************** + * Name: imm_stat + ****************************************************************************/ + +static int imm_stat(const char *relpath, struct stat *buf) +{ + if (strcmp(relpath, "imm") != 0) + { + ferr("ERROR: relpath is '%s'\n", relpath); + return -ENOENT; + } + + buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR; + buf->st_size = 0; + buf->st_blksize = 0; + buf->st_blocks = 0; + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imm_procfs_register + * + * Description: + * Register the internal heap procfs file system entry + * + ****************************************************************************/ + +int imm_procfs_register(void) +{ + return procfs_register(&g_procfs_imm); +} + +#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS && + * CONFIG_FS_PROCFS_REGISTER && CONFIG_XTENSA_IMEM_PROCFS */ diff --git a/arch/xtensa/src/esp32/esp32_procfs_imm.h b/arch/xtensa/src/esp32/esp32_procfs_imm.h new file mode 100644 index 00000000000..84e843d47ab --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_procfs_imm.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_procfs_imm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_IMM_H +#define __ARCH_XTENSA_SRC_ESP32_IMM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imm_procfs_register + * + * Description: + * Register the internal heap procfs file system entry + * + ****************************************************************************/ + +#ifdef CONFIG_XTENSA_IMEM_PROCFS +int imm_procfs_register(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_IMM_H */ + diff --git a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c index fd505f964e5..7fb25770eb9 100644 --- a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c @@ -56,6 +56,7 @@ #include #include +#include "esp32_procfs_imm.h" #include "esp32-core.h" #include "esp32_wlan.h" @@ -135,6 +136,21 @@ int esp32_bringup(void) { int ret; +#ifdef CONFIG_XTENSA_IMEM_PROCFS + /* Register the internal memory procfs entry. + * This must be done before the procfs is mounted. + */ + + ret = imm_procfs_register(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to register internal memory to PROCFS: %d\n", + ret); + } + +#endif + #ifdef CONFIG_FS_PROCFS /* Mount the procfs file system */ @@ -145,6 +161,7 @@ int esp32_bringup(void) } #endif + #ifdef CONFIG_MMCSD ret = esp32_mmcsd_initialize(0); if (ret < 0)