简体   繁体   中英

How can I retrieve data through a serial terminal without corrupting its fundamental value in GNU ARM embedded?

I'm wondering if anyone can help me spot the problem here...

In my C++ embedded program for an STM32L, I'm trying to retrieve a binary data file stored on an SD card over a serial connection via a CLI (or terminal, or whatever will work). So far, I can read the data file just fine using the FatFs f_read function. It's contents are being stored in the f_read buffer, which I can verify in debug mode.

However, the problem is that the RTOS I'm using requires outgoing data to be in the const char* form, so I'm forced to somehow get the elements into that type. So far I've been doing this by casting, however, depending on which type I use as a an f_read buffer, this either causes nothing to be printed or changes the its fundamental hex value when it's transferred over the serial connection to the CLI on my CPU.

Here's the operative part of my code. In this instance I'm storing the buffer data as uint16_t, but I've tried many other types (char, BYTE, char*), none of which manage to get the data to the other side without being corrupted.

FRESULT res;
FIL fsrc;
uint16_t buffer[512];
uint16_t bw = 0;

res = f_open(&fsrc, "zurn.dat", FA_READ | FA_OPEN_ALWAYS);  

res = f_read(&fsrc, buffer, sizeof buffer, &bw);                                      

//just printing the first few elements to see if it works
for(int i=0; i<10; i++){
     CLI_printMessage(ZString((const char*)buffer[i])); 
}

f_close(&fsrc);                                               

I must emphasize that its the fundamental hex values that I'm trying to transfer. A user has already kindly showed me how to get the ASCII representation of the hex values to go through (which I may have to resort to in the end), however, it'd be more useful for me if there's a way to get maintain the hex values themselves rather.

To further clarify, as an example: the first few characters of the data file look like this in ASCII: Èì‰Jà©í, and this in Hex: ecc8 8903 e04a a9ad. This is what I need on the other side, rather than this in ASCII: ecc8 8903 e04a a9ad, which is this in hex: 6563 6338 2038 3930 3320 6530 3461 2061 3961 64.

Some further thoughts: I realize the problem is likely with the casting. For starters, it gives me the warning "cast to pointer from integer of different size [-Wint-to-pointer-cast]". I understand this is because in C++ pointers default to 16 bits, hence the uint16_t type for my buffer.

I've also tried copying the data stored in the buffer to another variable, and casting that. In most circumstances, this shows the proper hex values at the debug level, but with lots of ASCII junk attached to it, of which I have no explanation for. I've also tried reducing my buffer array size to a mere 8 elements, still no difference.

The answer may also be specific to my RTOS, which has many special types made for it that I don't fully understand, though its mostly based on FreeRTOS. If you haven't noticed I'm not a very experienced programmer...

Also, I'm using the Eclipse IDE and the GNU Arm Build Tools.

Casting will not solve the issue and perhaps you have illustrated why casting is bad.


You need a function like something like this,

/* four 'nibbles' (nibble = 4 bits = one hex) is 16 bits. */
void int16ToString(char *buf[4], uint16_t val)
{
   static const char *lookup = "0123456789ABCDEF";
   buf[3] = lookup[val & 0xf]; /* write backwards or you need a copy of val */
   val = val >> 4;
   buf[2] = lookup[val & 0xf];
   val = val >> 4;
   buf[1] = lookup[val & 0xf];
   val = val >> 4;
   buf[0] = lookup[val & 0xf];
}

There are various functions in the C library, etc which do similar things. Obviously the routine needs a buffer of 4 bytes and it is not null terminated by the routine. It is just to demonstrate what needs to happen. sprintf , snprint , etc will be useful to look at as well as itoa , etc.


Why do you need a function like that? Because there are two sides to the conversation and they can (and probably do interpret things differently ). Generally you can transfer the lower ascii characters without effect. For example 'XON' is a flow control character that can be embedded in a data stream.

If you are to transmit the binary data via the CLI you need to 'clean it' and then you need code on the other side of the CLI uart to undo that. You can just send hex and then convert back to binary. There are more efficient ways to do this such as zmodem and base64 if the data is large or the link (CLI uart) is not reliable. A simple itoa() with ahexdump conversion on another host will transfer the binary which is suitable for a debugging transfer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM