Reputation: 53
I have a problem with an embedded system and one library.
I am currently working with a device called Ambiq [3] which use a Cortex M-4 and I want to use the FANN (Fast artificial neural network) library [2] on it. I am able to compile and link everything, but the problem is that the FANN library requires 2 files to read when starting.
Now, I have an embedded system, so I don't have any file system and neither a operating system. I'm quite sure that I can, in some way, write the content of that file inside the flash memory but I don't really know how can I link the first file address to the C file functions such as the "fopen" which require a file name as input. I only need some connection between the file name and the physical address of the file and I am done if it exits (or a C function that accept something different from a file name).
One thing that I already tried is to hard-code the content of the file into a C-array using xxd -i [filename] [1] but I don't know how should I link the fopen that the FANN library use. I've also started some cleaver parser but it seems to be really time consuming.
Please let me know if you can suggest me something. Thank you in advance. Best regards. Jaskirat
Additional information: - Software used for compiling: Eclipse with makefile. - Compiler: eabi-none-gcc toolbox - I am compiling directly the FANN library source code with the Ambiq microcontroller application that should run on the Cortex M4.
References: [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/
Upvotes: 5
Views: 2065
Reputation: 93446
Assuming that you have the source to the FANN library, the simplest solution would be to modify it to access your data arrays directly rather than using a file-system model.
However if you really must implement a file-system access model to static data, then, you will need to either implement the functions, or where provided implement the library re-targetting stubs. f you are using newlib for example, the higher level stdio file functions are enabled by implementing the lower-level syscalls. The minimal stub for open()
for example does nothing and looks like:
int open(const char *name, int flags, int mode) {
return -1;
}
The read functions use the handle returned by open
to access a control structure that you define as necessary. So let us assume that you have generated from the file data static data arrays thus:
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} } ;
Then open()
becomes something like:
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 ;
}
}
}
The read()
implementation:
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 ;
}
and close()
:
int close(int file)
{
files[file].index = -1 ;
return -1;
}
You may also need to implement lseek()
if FANN uses random access to the files. This is simply a mater of manipulating files[file].index
.
That should give you a minimal read-only "hard-coded" file-system. Note that I have omitted checking that handles are valid and perhaps other robustness and safety code for clarity. You may or may not feel it necessary given the read-only nature of the implementation. Also the code is intended as an outline and is untested - regard it as pseudo-code.
If you are not using newlib, no doubt there will be similar retargetting stubs for the library or you could simply override or implement the higher level functions fopen()
etc. in a similar manner.
The file model may be memory hungry because it copies chunks of ROM memory into RAM when you could otherwise access the ROM directly by modifying the FANN library itself.
Upvotes: 1
Reputation: 44288
Looking at the FANN source code, there's one function that you need to rewrite, and replace the fscanf with sscanf and pass in the pointer to the training data....
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;
}
Upvotes: 2