Search code examples
endiannessbyte-shifting

Byte order functions on stm32 microcontroller


Are there any written functions for htonll,ntohll,ntohl,htonl like this one i've found here on forum:

uint32_t ntohl(uint32_t const net) {
    uint8_t data[4] = {};
    memcpy(&data, &net, sizeof(data));

    return ((uint32_t) data[3] << 0)
         | ((uint32_t) data[2] << 8)
         | ((uint32_t) data[1] << 16)
         | ((uint32_t) data[0] << 24);
}

or could you just tell me data shifting scheme for each one and would write it just like this one above?

EDIT:

Are those correct:

uint32_t htonl(uint32_t const net) {
    uint8_t data[4] = {};
    memcpy(&data, &net, sizeof(data));

    return ((uint32_t) data[0] << 0)
         | ((uint32_t) data[1] << 8)
         | ((uint32_t) data[2] << 16)
         | ((uint32_t) data[3] << 24);
}

uint64_t htonll(uint64_t const net) {
    uint8_t data[4] = {};
    memcpy(&data, &net, sizeof(data));

    return ((uint64_t) data[0] << 0)
         | ((uint64_t) data[1] << 8)
         | ((uint64_t) data[2] << 16)
         | ((uint64_t) data[3] << 24);
}

uint64_t ntohll(uint64_t const net) {
    uint8_t data[4] = {};
    memcpy(&data, &net, sizeof(data));

    return ((uint64_t) data[3] << 0)
         | ((uint64_t) data[2] << 8)
         | ((uint64_t) data[1] << 16)
         | ((uint64_t) data[0] << 24);
}

Solution

  • This isn't STM32 specific but can be answered in general for all ARM MCU. Assuming you are using gcc, there are built-in functions like __builtin_bswap32.

    So you can implement it as:

    uint32_t htonl(uint32_t net)
    {
        return __builtin_bswap32(net);
    }
    
    uint16_t htons(uint16_t net)
    {
        return __builtin_bswap16(net);
    }
    
    uint64_t htonll(uint64_t net)
    {
        return __builtin_bswap64(net);
    }
    

    The resulting assembler code is very efficient:

    htonl:
            rev     r0, r0
            bx      lr
    htons:
            rev16   r0, r0
            uxth    r0, r0
            bx      lr
    htonll:
            rev     r3, r0
            rev     r0, r1
            mov     r1, r3
            bx      lr
    

    If you declare the functions as inline, you can even save the function call.

    BTW: In your code, the 64 bit versions are likely incorrect as they only return a 32 bit quantity.