微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 harvard arch ESP32

如何解决在 harvard arch ESP32

我正在为基于 ESP32 的物联网小工具的文件系统驱动程序编写一些系统代码。我的工具链将始终是 gcc,因为 ESP32 的开发人员框架需要 GCC。架构是一个已知量。便携性不是问题。函数指针与其他函数指针和数据指针的大小相同。

我有一个名为 esp_vfs_t 的(googlable)结构,它稍微简化了,看起来像这样

typedef struct
{
    int flags;      /*!< ESP_VFS_FLAG_CONTEXT_PTR or ESP_VFS_FLAG_DEFAULT */
    union {
        ssize_t (*write_p)(void* p,int fd,const void * data,size_t size);                         /*!< Write with context pointer */
        ssize_t (*write)(int fd,size_t size);                                    /*!< Write without context pointer */
    };
    union {
        off_t (*lseek_p)(void* p,off_t size,int mode);                                     /*!< Seek with context pointer */
        off_t (*lseek)(int fd,int mode);                                                /*!< Seek without context pointer */
    };
    union {
        ssize_t (*read_p)(void* ctx,void * dst,size_t size);                               /*!< Read with context pointer */
        ssize_t (*read)(int fd,size_t size);                                            /*!< Read without context pointer */
    };
    ...
} ...

你可以看到每个函数指针都是一个联合,但我只对将 void* 作为第一个参数的函数感兴趣。

基本上我想通过创建一个可以从中派生的纯抽象类来实现 OO,并且因为我希望此功能的额外开销为零,所以我想将 vtbl 直接复制到这个 esp_vfs_t 结构中,以便每个函数指针都填充我的 vtbl 中对应的函数指针。

我必须做的代码很难看,但不会崩溃。它只是由于我尚未确定的原因没有调用我的函数

我试图断言我的函数指针被复制到了我期望的位置,但是 C++ 不会让我比较需要比较的地址以使其工作。这是因为结构中每个函数的第一个参数是 void*,而我的 vtbl 函数的第一个参数当然是类实例 ptr 本身。

如果我删除代码以尝试执行该断言,以下代码将编译并“成功”运行,但无论出于何种原因我的函数都没有被调用(可能是一个无关的问题)

我期望的是崩溃或我的函数调用。 理想情况下,我现在想要的是获取下面断言要编译的代码

static bool mount(const char* mount_point,vfs_driver* driver) {
    if(nullptr==mount_point || nullptr==driver) {
        m_last_error=ESP_ERR_INVALID_ARG;
        return false;
    }
    esp_vfs_t vfs;
    memset(&vfs,sizeof(vfs));
    vfs.flags = ESP_VFS_FLAG_CONTEXT_PTR;
    // try to assert these values
    void* test1;
    void* test2;
    memcpy(&test1,vfs.fstat,sizeof(void*));
    memcpy(&test2,&esp32::vfs_driver::fstat,sizeof(void*));
    memcpy(&vfs.write_p,driver,sizeof(vfs_driver));
    assert(test1==test2);
    // the above won't compile
    esp_err_t res = esp_vfs_register(mount_point,&vfs,driver);
    if(ESP_OK!=res) {
        m_last_error = res;
        return false;
    }
    return true;
}

这是我创建的抽象基类的第一部分

class vfs_driver {
public:
    virtual ssize_t write(int fd,size_t size)=0;
    virtual off_t lseek(int fd,int mode)=0;
    virtual ssize_t read(int fd,size_t size)=0;
    virtual ssize_t pread(int fd,void *dst,size_t size,off_t offset)=0;
    virtual ssize_t pwrite(int fd,const void *src,off_t offset)=0;
    virtual int open(const char * path,int flags,int mode)=0;
    virtual int close(int fd)=0;
    virtual int fstat(int fd,struct stat * st)=0;
    virtual int fsync(int fd)=0;
...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。