FATFS converting unsigned int to readable data format - embedded C (stm32 / ARM)

Thread Starter

Engineering_Junkie

Joined Sep 9, 2015
41
Hey everyone,

I have the following function, part of elm-chan's FATFS library:


FRESULT f_write (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
UINT btw, /* Number of bytes to write */
UINT* bw /* Pointer to number of bytes written */
)

Problem is that to get readable data I need to make sure the data I'm passing to const void* buff is a character, otherwise I'll get junk out passing it an int, etc.

So I work with 16 bit unsigned integers and I'll have about 192 of these before I write them to the file. Issue is converting them to char is very processor intensive and going from 16 bit down to 8 bit is a mission. I tried using wchar_t although it seems to work perfectly within the code, but as soon as I write to the file, I get junk again.

Example:

uint16_t aDST_Buffer= 1100;
wchar_t hj;
hj =(wchar_t)aDST_Buffer; //This gives me hj = 1100
res1 = f_write(&SDFile, hj, sizeof(hj), (void *)&wbytes); // This produces a large amount of junk.

Is there anyway around this? Any 16 bit character datatypes or ways to write integers via f_write for readable data?
 

WBahn

Joined Mar 31, 2012
30,058
I don't know anything about this library, but it seems that the purpose of that function is simply to transfer bytes from memory to a file without altering them in any way.

In your call at the end of the post, you are passing it hj, which is the value stored in a variable of type wchar_t. What it is expecting to be passed is the ADDRESS in memory where data is stored.
 

Thread Starter

Engineering_Junkie

Joined Sep 9, 2015
41
I don't know anything about this library, but it seems that the purpose of that function is simply to transfer bytes from memory to a file without altering them in any way.

In your call at the end of the post, you are passing it hj, which is the value stored in a variable of type wchar_t. What it is expecting to be passed is the ADDRESS in memory where data is stored.
Sorry, that was a typo, I fed it the address of the data, although it completely prints out junk. it works perfectly for char data types, but wchar_t completely bugs out

It should show this:

Example:

uint16_t aDST_Buffer= 1100;
wchar_t hj;
hj =(wchar_t)aDST_Buffer; //This gives me hj = 1100
res1 = f_write(&SDFile, &hj, sizeof(hj), (void *)&wbytes); // This produces a large amount of junk.
 
Last edited:

WBahn

Joined Mar 31, 2012
30,058
What is this SDFile variable. It's real hard to debug code when not all the relevant code is presented.

If SDFile is a pointer to a FILE object (which is what it should be), then you want to pass the value stored in SDFile, not the address where it is stored. Although your prototype says that it is looking for a pointer to a FIL object, and I have no idea what that is.
 

xox

Joined Sep 8, 2017
838
Sorry, that was a typo, I fed it the address of the data, although it completely prints out junk. it works perfectly for char data types, but wchar_t completely bugs out

It should show this:

Example:

uint16_t aDST_Buffer= 1100;
wchar_t hj;
hj =(wchar_t)aDST_Buffer; //This gives me hj = 1100
res1 = f_write(&SDFile, &hj, sizeof(hj), (void *)&wbytes); // This produces a large amount of junk.
A FILE* is supposed to be a pointer to file handle, not the address of some FILE object declared in your program.

Also, casting to wchar_t is not well defined. The compiler is free to implement that as utf-8, utf-16, or whatever.
 

WBahn

Joined Mar 31, 2012
30,058
A FILE* is supposed to be a pointer to file handle, not the address of some FILE object declared in your program.

Also, casting to wchar_t is not well defined. The compiler is free to implement that as utf-8, utf-16, or whatever.
I disagree. The FILE *fp is expected to receive the address of the FILE structure for that file. The file handle/descriptor is and integer and is a much lower level access identifier that is O/S specific and is maintained within the FILE structure so that the O/S details can be abstracted away.

I went and looked at this library. They use a FIL structure, probably because it is a custom structure and they didn't want to conflict with the compiler's (that this compiler is compiled on) existing FILE structure and libraries, which their code would need to still use.

Another difference from working with the normal library files is that fopen() does NOT allocate memory for the FIL structure and return a pointer to it. The user is responsible for creating the structure and passing a pointer to fopen(), which then populates it.
 

xox

Joined Sep 8, 2017
838
I disagree. The FILE *fp is expected to receive the address of the FILE structure for that file. The file handle/descriptor is and integer and is a much lower level access identifier that is O/S specific and is maintained within the FILE structure so that the O/S details can be abstracted away.
As far as the C API is concerned, a FILE* is a file handle/descriptor. This library apparently uses another convention.
 

WBahn

Joined Mar 31, 2012
30,058
As far as the C API is concerned, a FILE* is a file handle/descriptor. This library apparently uses another convention.
In the C99 language standard, the word "handle" appears twice and neither has do with files (the uses are generic, such as "to better handle signed zeroes") and the word descriptor doesn't appear at all.

But the term FILE is very explicitly defined as an object type, the object being able to store all of the information needed to control a stream.

Having said that, the standard also very clearly stipulates that the address of a FILE object may, itself, be significant; this means that making a copy of a FILE object and passing the address of the copy may not have the same effect as passing the address of the original. It doesn't spell it out, but my guess is that this is to allow the compiler to hard code certain addresses, perhaps such as stdin, stdout, and stderr, to be constants that the functions check without dereferencing.
 

xox

Joined Sep 8, 2017
838
In the C99 language standard, the word "handle" appears twice and neither has do with files (the uses are generic, such as "to better handle signed zeroes") and the word descriptor doesn't appear at all.

But the term FILE is very explicitly defined as an object type, the object being able to store all of the information needed to control a stream.

Having said that, the standard also very clearly stipulates that the address of a FILE object may, itself, be significant; this means that making a copy of a FILE object and passing the address of the copy may not have the same effect as passing the address of the original. It doesn't spell it out, but my guess is that this is to allow the compiler to hard code certain addresses, perhaps such as stdin, stdout, and stderr, to be constants that the functions check without dereferencing.
Whether the standard explicitly uses that wording is irrelevant, I'm talking about practical usage. The API returns pointers, some descriptors are aliases (stdin, stdout, stderr), and NULL is used to indicate an "invalid handle" value. In other words, it's referred to a file descriptor or handle precisely because it could represent anything; 0xdeadbeef, 123, [pointer on stack of actual structure], etc.
 

WBahn

Joined Mar 31, 2012
30,058
I think we are largely saying the same thing and getting tripped up over a couple different common uses of the term "file handle" or "file descriptor".

But for the TS's problem that is neither here nor there.

The library he is trying to use is pretty clearly spelled out. When you call fopen(), for instance, you have to pass it the address of a FIL object that your program has allocated memory for. The fopen() function then populates the data structure whose address was passed. When you call fwrite(), you need to pass it the address of a FIL object that is opened for writing. The TS isn't showing us enough of his code to know whether this is being done properly or not because we do not know what type of data SDFile is or how it is being allocated and initialized.
 
Top