嵌入式世界中的C文件函数

时间:2015-12-15 20:23:55

标签: c file embedded microcontroller

我遇到嵌入式系统和一个库的问题。

我目前正在使用一种名为Ambiq [3]的设备,该设备使用Cortex M-4,我想在其上使用FANN(快速人工神经网络)库[2]。 我能够编译和链接所有内容,但问题是FANN库在启动时需要读取2个文件。

现在,我有一个嵌入式系统,所以我没有任何文件系统,也没有操作系统。 我非常确定我可以在某种程度上将该文件的内容写入闪存,但我真的不知道如何将第一个文件地址链接到C文件函数,例如"的fopen"需要文件名作为输入。我只需要文件名和文件的物理地址之间的一些连接,如果它退出(或接受与文件名不同的C函数),我就完成了。

我已经尝试过的一件事是使用xxd -i [filename] [1]将文件内容硬编码到C数组中,但我不知道应该如何链接fopen FANN库使用。我也启动了一些切割器解析器,但它似乎非常耗时。

如果你能给我一些建议,请告诉我。 先感谢您。 最好的祝福。 Jaskirat

其他信息: - 用于编译的软件:带有makefile的Eclipse。 - 编译器:eabi-none-gcc工具箱 - 我正在使用应该在Cortex M4上运行的Ambiq微控制器应用程序直接编译FANN库源代码。

参考文献: [1] Read a file into a string at compile-time [2] FANN LIBRARY UFFICIAL SITE http://leenissen.dk/fann/wp/ [3] AMBIQ MICRO:http://ambiqmicro.com/

2 个答案:

答案 0 :(得分:2)

查看FANN源代码,您需要重写一个函数,并用sscanf替换fscanf并将指针传递给训练数据....

struct fann_train_data *fann_read_train_from_fd(FILE * file, const char *filename)
{
    unsigned int num_input, num_output, num_data, i, j;
    unsigned int line = 1;
    struct fann_train_data *data;

    if(fscanf(file, "%u %u %u\n", &num_data, &num_input, &num_output) != 3)
    {
        fann_error(NULL, FANN_E_CANT_READ_TD, filename, line);
        return NULL;
    }
    line++;

    data = fann_create_train(num_data, num_input, num_output);
    if(data == NULL)
    {
        return NULL;
    }

    for(i = 0; i != num_data; i++)
    {
        for(j = 0; j != num_input; j++)
        {
            if(fscanf(file, FANNSCANF " ", &data->input[i][j]) != 1)
            {
                fann_error(NULL, FANN_E_CANT_READ_TD, filename, line);
                fann_destroy_train(data);
                return NULL;
            }
        }
        line++;

        for(j = 0; j != num_output; j++)
        {
            if(fscanf(file, FANNSCANF " ", &data->output[i][j]) != 1)
            {
                fann_error(NULL, FANN_E_CANT_READ_TD, filename, line);
                fann_destroy_train(data);
                return NULL;
            }
        }
        line++;
    }
    return data;
}

答案 1 :(得分:0)

假设您拥有FANN库的源代码,最简单的解决方案是修改它以直接访问数据数组,而不是使用文件系统模型。

但是,如果您确实必须将文件系统访问模型实现为静态数据,则需要实现这些功能,或者在提供实现库重新定位存根的情况下。例如,如果您正在使用newlib,则通过实现较低级别的系统调用来启用更高级别的stdio文件功能。例如open()的最小存根没有任何作用,看起来像:

int open(const char *name, int flags, int mode) {
  return -1;
}

读取函数使用open返回的句柄来访问您根据需要定义的控件结构。因此,让我们假设您已经从文件数据生成静态数据数组:

static const char file1[] = { '\x00`, `\x01`, ... } ;
static const char file2[] = { '\x00`, `\x01`, ... } ;
static struct
{
    const char* file ;
    int size ;
    int index ;
} files[] = { {file1, sizeof(file1), -1}, {file2, sizeof(file2), -1} } ;

然后open()就变成了:

int open(const char *name, int flags, int mode) 
{ 
    static const char* file_to_handle[] = { "file1", "file2", 0 } ;  // change names to match the FANN library names.

    int handle = -1 ;
    for( int h = 0; file_to_handle[h] != 0 && handle == -1; h++ )
    {
        if( strcmp( file_to_handle[h], name ) == 0 && files[h].index == -1 )
        {
            handle = h ;
            files[h].index = 0 ;
        }
    }
}

read()实施:

int read(int file, char *ptr, int len) 
{
    int i = -1 ;
    if( files[file].index > 0 )
    {
        i = 0 ;
        while( files[file].index < files[file].size && i < len)
        {
            ptr[i] = files[file].index ;
            i++ ;
            files[file].index++ ;
        }
    }    
    return i ;
}

close()

int close(int file) 
{
    files[file].index = -1 ;
    return -1;
}

如果FANN使用随机访问文件,您可能还需要实施lseek()。这只是操纵files[file].index的主要内容。

这应该给你一个最小的只读“硬编码”文件系统。请注意,为了清楚起见,我省略了检查句柄是否有效以及其他可靠性和安全性代码。鉴于实现的只读性质,您可能会或可能不会觉得有必要。此外,代码也是一个大纲,未经测试 - 将其视为伪代码。

如果你没有使用newlib,毫无疑问会有类似的重新定位存根,你可以简单地以类似的方式覆盖或实现更高级别的函数fopen()等。

文件模型可能是内存耗尽,因为它可以通过修改FANN库本身直接访问ROM来将ROM内存复制到RAM中。