This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/CC1310: Printing MAC address via UART does not work

Part Number: CC1310

Tool/software: Code Composer Studio

Hello everybody,

I am working with the sensor/actuator example and I am trying to print the 8 bytes of the MAC address of the sensor sending data to the collector.

Doing this:

 LCD_WRITE_STRING_VALUE("Sensor 0x", (uint16_t)* pMsg->extAddr, 16, 6); Prints the first 2 bytes.

LCD_WRITE_STRING_VALUE("Sensor 0x", (uint16_t)* (pMsg+1)->extAddr, 16, 6); Prints the second 2 bytes and so on...

But I want to send it in one line. So I tried this:

    char extAddress_array[20];
    for(int i=0; i < 7; i++)
    {
        sprintf(&extAddress_array[2*i],"%02X", *(pMsg+i)->extAddress);
    }
    extAddress_array[19] = '\0';
    
    System_printf((xdc_CString) extAddress_array);
    System_printf("\r\n");

The code works if I put in chars into the "extAddress_array" manually, but using sprintf seems not to do the trick, because running this code just causes the collector to stop printing anything via UART.

Can someone of you find the mistake? Or give me another elegant solution to print the extAddress of the sensor by the collector via UART?

kind regards

Stefan

  • You forgot the (uint16_t) cast.

    Of course, sprintf() is going to print *3* characters, don't forget the trailing nul.
  • I am sorry, but your answer is cryptic to me.

    Did you mean these changes?

    char extAddress_array[20];
        for(int i=0; i < 7; i++)
        {
            sprintf(&extAddress_array[2*i],"%2X", (uint16_t)* (pMsg+i)->extAddress);
        }
        extAddress_array[19] = '\0';
        System_printf((xdc_CString) extAddress_array);
        System_printf("\r\n");

    Well, it still doesnt print anything.

    And why the uint16_t cast? I thought this was only necessary to fit the LCD_WRITE_STRING_VALUE function.

    If you could be a little bit more precise I would appreciate it.

    kind regards

    Stefan

  • LCD_WRITE_STRING_VALUE("Sensor 0x", (uint16_t)* (pMsg+1)->extAddr, 16, 6); Prints the second 2 bytes and so on...
    It does not print second byte of a sensor's MAC address.
    First, try to do it without the sprintf() calls.
  • Unfortunately, I am too lazy to look up the type of extAddress, so I can't really help you.

    I can tell you you are abusing pointers in your call to sprintf().

    You are saying to print 2 characters in a multibyte number. Then you point into the middle of the object, and tell sprintf() to print 2 characters of a multibyte object.

    Lets say the number is 0x12345678. You point to the 1 and tell sprintf() to print 2 characters of this number. Which 2 characters does it print? I don't know. Then you point to the 3 and say print 2 characters of 0x345678XX, where XX is whatever junk is adjacent to your extAddress. What does it print? I have no idea, and could possibly crash the machine.

    Without knowing the type of extAddress, I cannot make any more suggestions.

    That is why they have the (uint16_t) cast in your first code, tell the compiler to treat what you are pointing to as 12 instead of 12345678.

  • Hi Tomasz,

    Can you not just hard code the formatting? You know the extended address will always be 8 bytes, which means the resulting string will always be 17 chars (2 chars per byte, 8 bytes equals 16 chars + NULL terminator totals 17 chars). Now, I don't understand what kind of type pMsg->extAddress points to, and if (pMsg + 1)->extAddress points to the same address or another address.

    Either way, take a look at the below code snippet. I'm assuming pMsg->extAddress is little endian.

    //  2 chars per byte, 8 bytes and null terminator, equals 17 chars
    char extAddrStr[17];
    const uint8_t *pExtAddr = (uint8_t *)pMsg->extAddress;
    snprintf(extAddrStr, sizeof(extAddrStr), "%02X%02X%02X%02X%02X%02X%02X%02X",
        pExtAddr[7], pExtAddr[6], pExtAddr[5], pExtAddr[4],
        pExtAddr[3], pExtAddr[2], pExtAddr[1], pExtAddr[0]);
    

  • Hey Edvard,

    I think I am doing something wrong with the pointing, because I also tried hard formatting.

    /*!
     Sensor Data message: sent from the sensor to the collector
     */
    typedef struct _Smsgs_sensormsg_t
    {
        /*! Command ID */
        Smsgs_cmdIds_t cmdId;
        /*! Extended Address */
        uint8_t extAddress[SMGS_SENSOR_EXTADDR_LEN];
        /*! Frame Control field - bit mask of Smsgs_dataFields */
        uint16_t frameControl;
        /*!
    ...

    This is the structure pMsg is pointing to and I want to get the member "extAddress". Since it is an array with the length 8, I'd like to pick out each byte one after the other.

    Is it correct, that pMsg -> extAddress will only point to the first array element of extAddress? So in your code, would *pExtAddr point on the value of the first array element of extAddress or the whole array?

    kind regards

    Stefan

  • Edward,

    my goal is to help Stefan.
    You did a job Stefan should do.
    That is O.K.

    One remark to your code:
    // 2 chars per byte, 8 bytes and null terminator, equals 17 chars
    char extAddrStr[17];
    The above is a bad practice.

    Table size should depend on sizeof().
    Nice that you point to endianness.
    I would prefer to handle this by a project config or an include file.

    Hi Stefan,
    <<< Is it correct, that pMsg -> extAddress will only point to the first array element of extAddress?
    Wrong question.
    pMsg->extAddress points to an array.

    <<< So in your code, would *pExtAddr point on the value of the first array element of extAddress or the whole array?
    const uint8_t *pExtAddr = (uint8_t *)pMsg->extAddress;
    points to a value @ address pMsg->extAddress and casts it as uint8_t.
    pExtAddr[3] points to a value ((pMsg->extAddress + 3 * sizeof ("type of *pExtAddr)) and casts it as uint8_t.

    Be patient, learn the C pointer concepts.

  • Tomasz,

    Valid point about the char array size. I would probably make a define for the size based on the size of extAddress (SMGS_SENSOR_EXTADDR_LEN), but since I didn't know about the define I made a comment.

    //  2 chars per byte + NULL terminator
    #define EXT_ADDR_STR_LEN  ((2 * SMGS_SENSOR_EXTADDR_LEN) + 1)
    char extAddrStr[EXT_ADDR_STR_LEN];
    ...
    snprintf(extAddrStr, EXT_ADDR_STR_LEN, ...

    Either way, thanks for pointing it out.

  • Hello Stefan,

    did you fixed your MAC printing?
  • Hey Tomasz,

    I did not have the time to go on with this topic yet, but I worked myself a little bit deeper into pointer aso. I hope I will be able at the weekend.

    Kind regards

    Stefan

  • Do not hesitate to ask for help.
  • I am currently using an online compiler to test some pointer stuff: www.onlinegdb.com

    #include <stdio.h> #define SMGS_SENSOR_EXTADDR_LEN 8 struct test { /*! Command ID */ int cmdId; /*! Extended Address */ int extAddress[SMGS_SENSOR_EXTADDR_LEN]; /*! Frame Control field - bit mask of Smsgs_dataFields */ int frameControl; } test1, *pMsg; int main() { test1.extAddress[8] = (0, 1, 2, 3, 4, 5, 6, 7); pMsg = test1.extAddress; char extAddress_array[17]; for(int i=0; i < 8; i++) { printf("Address: %d and value: %d \n", ((pMsg->extAddress)+i), *((pMsg->extAddress)+i)); sprintf(&extAddress_array[2*i],"%02X", *((pMsg->extAddress)+i)); } extAddress_array[16] = '\0'; printf("One char %c", extAddress_array[15]); return 0; }

    I am still trying the "sprintf" approach. This is my result:

    Address: 6295720 and value: 0                                                                                           
    Address: 6295724 and value: 0                                                                                           
    Address: 6295728 and value: 0                                                                                           
    Address: 6295732 and value: 0                                                                                           
    Address: 6295736 and value: 0                                                                                           
    Address: 6295740 and value: 0                                                                                           
    Address: 6295744 and value: 0                                                                                           
    Address: 6295748 and value: 7                                                                                           
    
    One char 7

    I don't understand why the value of the members of the test1.extAddress array are all 0. Exchange the '(' with '{' causes an compile error, but I assume it has something to do with this...

    But the line "One char 7" looks like it is working though I am still suspicious. Any comment on that approach?

  • You really need to give this approach up. It would be better if you did not understand it!

    It is really bad practice to use a pointer to one object to access the inside of another object.
  • Stefan,
    please, reanalyze your code one more time.
    I will help you.
  • #include <stdio.h>
    
    #define SMGS_SENSOR_EXTADDR_LEN         8
    
    
    typedef struct _test // use typedef, much easier
    {
        /*! Command ID */
        int cmdId;
        /*! Extended Address */
        char extAddress[SMGS_SENSOR_EXTADDR_LEN]; // changed to uint8_t / char ??? why use 32 bit ?
        /*! Frame Control field - bit mask of Smsgs_dataFields */
        int frameControl;
    } Test_t;
    
    
    int main()
    {
        Test_t test1 = {0, {0, 1, 2, 3, 4, 5, 6, 7}, 0}; // init struct
        Test_t *pMsg = &test1; // define a pointer to the struct (for some reason...?)
        
        char extAddress_array[SMGS_SENSOR_EXTADDR_LEN*2 + 1]; // this array will only "live" in this function and at lower function calls, do not return!
        
        for(int i=0; i < SMGS_SENSOR_EXTADDR_LEN; i++)
        {
            printf("Address: %u and value: %u \n", ((pMsg->extAddress)+i), *((pMsg->extAddress)+i));
            
            sprintf(&extAddress_array[2*i],"%02X", *((pMsg->extAddress)+i));
        }
        
        extAddress_array[SMGS_SENSOR_EXTADDR_LEN*2] = '\0';
        printf("One char %c", extAddress_array[15]);
    
        return 0;
    }

    If you need debug print in collector, you could use this:

    static char addrStr[8*2 + 7 + 1]; // Or perhaps use #define size...
    char* csf_GetExtShortAddrStr(ApiMac_sAddr_t *pAddr)
    {
        if(pAddr->addrMode == ApiMac_addrType_short)
        {
            sprintf(&addrStr[0], "0x%04x", pAddr->addr.shortAddr);
        }
        else if(pAddr->addrMode == ApiMac_addrType_extended)
        {
            sprintf(&addrStr[0], "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
                                    pAddr->addr.extAddr[7], pAddr->addr.extAddr[6],
                                    pAddr->addr.extAddr[5], pAddr->addr.extAddr[4],
                                    pAddr->addr.extAddr[3], pAddr->addr.extAddr[2],
                                    pAddr->addr.extAddr[1], pAddr->addr.extAddr[0]);
        }
    
        return &addrStr[0];
    }

  • Just to add to my comment, what you can do, if we are talking about a char array here is point to the first element of the array and work with that:

    &(msg->extAddress[0])

    Now you have a pointer to the first character in the array and can march down along it.
  • Thank you all for participating,

    1. Thank you for the offer Thomasz, I went through the code I postet in my last post and found the error. I was not initializing the array correctly. I do now know how to initialize it within a structure and outside of a structure.
    2. @Keith, getting the address of the first element was also my last idea and it works, though I am doing it a little bit different. I have a pointer pointing to a structure. Inside this structure is an array:

    struct test *p;

    p=test.array; <-- this is my solution to safe the address of the first array element.

    I can now go from address to address by incrementing p: ((p->array)+1)

    Or I can access the value which is at this address: *((p->array)+1)

    Any comment on that? Is there a big difference between our approaches?

    One question regarding your approach:

    Do you increment the address like this: 1+&(pMsg->extAddress[0]) or like this &(pMsg->extAddress[1])?

    Well, now I have to figure out, how to convert these elements from the array into chars and then put together into a string, which I can than display. I wont be able to do this before monday.

    kind regards

    Stefan

  • struct test *p;

    p = &test; // it is ok
    p+1 == p + sizeof(struct test);
    p= test.array; // is wrong: p is struct test pointer, test.array is int* in your code example

    // array is char[] table
    char *pChr;
    for (i=0, pChr=pMsg->array; i<8; i++, pChr++) sprintf(&extAddress_array[2*i],"%02X", *pChr);

  • test.array is probably not a struct test.
  • Thanks for your help. I will work on this after my holidays :)