views:

119

answers:

5

I am working on the Firmware for an embedded USB project. The production programmer I would like to use automatically writes the Serial Number into the device flash memory at a specified memory address. The programmer stores the serial number as Hex digits in a specified number of bytes. For example, if I tell it to store the serial number 123456 at address 0x3C00 my memory looks like this:

0x3C00  -  00
0x3C01  -  01
0x3C02  -  E2
0x3C03  -  40
//(123456 in Hex = 1E240)

The problem is, when my host application reads the serial number from the device it is looking for a unicode char array. So my serial number should be ...

{ '1','0',
  '2','0',
  '3','0',
  '4','0',
  '5','0',
  '6','0'}

When the

So in my firmware, which I'm writing in C, is it possible to retrieve the hex serial number from flash, encode it into a unicode char array and store it in a variable in Ram?

+2  A: 

You should be able to use something like this:

wchar_t buf[10];
swprintf(buf, L"%d", your_int_value);

The details may be different depending on your exact implementation of the C runtime library. For example, your swprintf() may expect the number of characters in buf:

swprintf(buf, sizeof(buf)/sizeof(buf[0]), L"%d", your_int_value);
Greg Hewgill
i doubt that it is possible in firmware
Andrey
Since it is a 32 bit number you will have to use %ld rather than %d.
semaj
@Andrey: Firmware is just software with another name. Firmware can have extensive runtime libraries available.
Greg Hewgill
@semaj: `%d` is suitable for a value of type `int`, it doesn't relate to the number of bits in the integer. `%ld` would be suitable for a value of type `long`.
Greg Hewgill
afaik, firmware is software that is ran on very resource limited devices, that have small memory and slow proc. and compilers are special. no one will link unicode libs just to add few more zeros to array.
Andrey
@Andrey: I was presuming that the question required the serial number in Unicode for a particular reason, probably because the *rest* of the program already uses Unicode. Obviously if the rest of the program doesn't need Unicode, then there wouldn't be any reason to convert this serial number to a Unicode representation.
Greg Hewgill
Greg: The question states that the *host* application is expecting a Unicode string (and implies a UCS2 encoding). The implication here is that the embedded device is communicating with a host PC, over something like USB.
caf
@caf: You're quite right, I hadn't noticed that detail. Thanks!
Greg Hewgill
+2  A: 

It seems like you want:

wsprintf(wchar_buffer, L"%d", serial_number)

(assuming that your serial number fits in a 32-bit integer. In any case, wsprintf will print your serial number as a wchar (unicode) string.

JSBangs
`wchar_t` is not necessarily 16 bit UCS2 (it's not even necessarily Unicode at all).
caf
True, but if that's the case then you have bigger problems. You should be able to read your compiler's docs to determine if `wchar_t` has the char size that you need (and if not, how to set the flag so that `wchar_t` does what you want).
JSBangs
+1  A: 

not sure that this code will fit your device, but let's try

char buffer[MAX_SIZE];
char unicodeBuffer[MAX_SIZE];
sprintf(buffer, "%d", i);
int len = strlen(buffer);
int i = 0;
for (int i = 0; i <= (len << 1) - 2; i++)
   unicodeBuffer[i] = i % 2 ? buffer[i] : 0;
unicodeBuffer[i + 1] = 0;
unicodeBuffer[i + 2] = 0;
Andrey
That doesn't work - it's only copying half of the characters from the buffer created by `sprintf`.
caf
+1  A: 

If the serial number fits into 32 bits and the platform is big endian and supports Unicode, 32 bit ints and the standard C libraries then this is pretty straightforward as other answers have shown. If the platform has 32 bit ints and 8 bit chars but is little endian and/or doesn't support Unicode, and if the serial number can vary in length, then the below may be useful, though it's a little workmanlike.

void extract_serial_number(unsigned char* address, unsigned int bytes, char* buffer) {
    unsigned int value = 0;
    char c, *start = buffer;
    while (bytes--) {                      /* read the serial number into an integer */
        value = value << 8;
        value |= *address++;
    }
    while (value > 0) {                    /* convert to 16 bit Unicode (reversed) */
        *buffer++ = '0' + value % 10;
        *buffer++ = '\0';
        value /= 10;
    }
    *buffer++ = '\0';
    *buffer++ = '\0';
    buffer -= 4;
    while (buffer > start) {               /* reverse the string */
        c = *buffer;
        *buffer = *start;
        *start = c;
        buffer -= 2;
        start += 2;
    }
}
El Zorko
+1  A: 

If you have access to sprintf in your embedded environment, then this should work:

#define MAX_SIZE(type) ((CHAR_BIT * sizeof(type) - 1) / 3 + 2)

/* Destination UCS2 buffer size must be at least 2*MAX_SIZE(int) */
void int_to_ucs2(char *dest, int q)
{
    char buffer[MAX_SIZE(q)];
    char *src = buffer;

    sprintf(buffer, "%d", q);

    while (*src)
    {
        *dest++ = *src++;
        *dest++ = 0;
    }

    *dest++ = 0;
    *dest++ = 0;
}
caf