嵌入式世界中的 C 文件函数
C file functions in embedded world
我有一个嵌入式系统和一个库的问题。
我目前正在使用名为 Ambiq [3] 的设备,该设备使用 Cortex M-4,我想在其上使用 FANN(快速人工神经网络)库 [2]。
我能够编译 link 一切,但问题是 FANN 库在启动时需要读取 2 个文件。
现在,我有一个嵌入式系统,所以我没有任何文件系统,也没有操作系统。
我很确定我可以通过某种方式将该文件的内容写入闪存,但我真的不知道如何 link C 文件功能的第一个文件地址,例如"fopen" 需要文件名作为输入。我只需要文件名和文件物理地址之间的某种联系,如果它退出(或接受不同于文件名的 C 函数),我就完成了。
我已经尝试过的一件事是使用 xxd -i [filename] [1] 将文件的内容硬编码到 C 数组中,但我不知道我应该怎么做 link FANN 库使用的 fopen。我也开始了一些切肉刀解析器,但它似乎真的很耗时。
如果你能给我一些建议,请告诉我。
先感谢您。
最好的祝福。
贾斯基拉特
附加信息:
- 编译软件:Eclipse with makefile。
- 编译器:eabi-none-gcc 工具箱
- 我正在使用应该在 Cortex M4 上 运行 的 Ambiq 微控制器应用程序直接编译 FANN 库源代码。
参考资料:
[1] Read a file into a string at compile-time
[2] 范恩图书馆官方网站 http://leenissen.dk/fann/wp/
[3] AMBIQ 微型:http://ambiqmicro.com/
假设您拥有 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
.
的问题
那应该给你一个最小的只读 "hard-coded" 文件系统。请注意,为清楚起见,我省略了检查句柄是否有效以及其他稳健性和安全性代码。鉴于实现的只读性质,您可能会或可能不会觉得有必要。此外,该代码旨在作为大纲并且未经测试 - 将其视为伪代码。
如果您不使用 newlib,毫无疑问,该库会有类似的重定向存根,或者您可以以类似的方式简单地覆盖或实现更高级别的功能 fopen()
等。
文件模型可能会占用大量内存,因为它会将 ROM 内存块复制到 RAM 中,否则您可以通过修改 FANN 库本身直接访问 ROM。
查看FANN源码,有一个函数需要重写,把fscanf换成sscanf,传入训练数据指针....
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;
}
我有一个嵌入式系统和一个库的问题。
我目前正在使用名为 Ambiq [3] 的设备,该设备使用 Cortex M-4,我想在其上使用 FANN(快速人工神经网络)库 [2]。 我能够编译 link 一切,但问题是 FANN 库在启动时需要读取 2 个文件。
现在,我有一个嵌入式系统,所以我没有任何文件系统,也没有操作系统。 我很确定我可以通过某种方式将该文件的内容写入闪存,但我真的不知道如何 link C 文件功能的第一个文件地址,例如"fopen" 需要文件名作为输入。我只需要文件名和文件物理地址之间的某种联系,如果它退出(或接受不同于文件名的 C 函数),我就完成了。
我已经尝试过的一件事是使用 xxd -i [filename] [1] 将文件的内容硬编码到 C 数组中,但我不知道我应该怎么做 link FANN 库使用的 fopen。我也开始了一些切肉刀解析器,但它似乎真的很耗时。
如果你能给我一些建议,请告诉我。 先感谢您。 最好的祝福。 贾斯基拉特
附加信息: - 编译软件:Eclipse with makefile。 - 编译器:eabi-none-gcc 工具箱 - 我正在使用应该在 Cortex M4 上 运行 的 Ambiq 微控制器应用程序直接编译 FANN 库源代码。
参考资料: [1] Read a file into a string at compile-time [2] 范恩图书馆官方网站 http://leenissen.dk/fann/wp/ [3] AMBIQ 微型:http://ambiqmicro.com/
假设您拥有 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
.
那应该给你一个最小的只读 "hard-coded" 文件系统。请注意,为清楚起见,我省略了检查句柄是否有效以及其他稳健性和安全性代码。鉴于实现的只读性质,您可能会或可能不会觉得有必要。此外,该代码旨在作为大纲并且未经测试 - 将其视为伪代码。
如果您不使用 newlib,毫无疑问,该库会有类似的重定向存根,或者您可以以类似的方式简单地覆盖或实现更高级别的功能 fopen()
等。
文件模型可能会占用大量内存,因为它会将 ROM 内存块复制到 RAM 中,否则您可以通过修改 FANN 库本身直接访问 ROM。
查看FANN源码,有一个函数需要重写,把fscanf换成sscanf,传入训练数据指针....
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;
}