0

I am experiencing a problem in Atmel Studio when using memcpy or strcpy. When the switch evaluates to TYPE3, only the first 10 bytes are copied. When the order of the cases are exchanged with each other, other strcpy's work. I really cannot see why this could make a difference, and why a simple strcpy won't work. Any help is appreciated.

t_RdmPacket is defined in an include file:

typedef union T_RdmPacket
{
    uint8_t Slot[257];  // Maximale grootte Packet = 255 bytes, + 2 Checksum bytes
    struct
    {
        uint8_t Preamble[8];
        uint8_t ManIDMsbOr0xAA;
        uint8_t ManIDMsbOr0x55;
        uint8_t ManIDLsbOr0xAA;
        uint8_t ManIDLsbOr0x55;
        uint8_t ProdIDMsbOr0xAA;
        uint8_t ProdIDMsbOr0x55;
        uint8_t ProdIDLsbOr0xAA;
        uint8_t ProdIDLsbOr0x55;
        uint8_t SerNrMsbOr0xAA;
        uint8_t SerNrMsbOr0x55;
        uint8_t SerNrLsbOr0xAA;
        uint8_t SerNrLsbOr0x55;
        uint8_t ChecksumMsbOr0xAA;
        uint8_t ChecksumMsbOr0x55;
        uint8_t ChecksumLsbOr0xAA;
        uint8_t ChecksumLsbOr0x55;
    } DiscoveryResponse;
    struct
    {
        uint8_t StartCodeRDM;       //Slot 0
        uint8_t SubStartCode;       //Slot 1
        uint8_t MessageLength;      //Slot 2                Min 24, Max 255
        struct
        {
            uint16_t    ManID;      //Slot 3 & 4    /   9 & 10
            uint16_t    ProdID;     //Slot 5 & 6    /   11 & 12
            uint16_t    SerNr;      //Slot 7 & 8    /   13 & 14
        } Destination, Source;
        uint8_t     TransactionNumber;  //Slot 15
        uint8_t     ResponseType;       //Slot 16
        uint8_t     MessageCount;       //Slot 17
        uint16_t    SubDevice;          //Slot 18 & 19
        uint8_t     CommandClass;       //Slot 20
        uint16_t    ParameterID;        //Slot 21 & 22
        uint8_t     PDL;                //Slot 23           Min 0, Max 231
        uint8_t     ParameterData[231]; //Slot 24 t/m 254
        uint16_t    Checksum;           //Slot 255 & 256
    } Packet;
} t_RdmPacket;

Then in the handling of the packet:

t_RdmPacket Rdm;

void sendGetDeviceModelDescriptionResponse(uint8_t *uid) {
    uint16_t checkSum;
    memset(Rdm.Packet.ParameterData, 0, 231);
    uint8_t size = 0;
    const char* text1 = "1234567890123456";
    const char* text2 = "6543210987654321";
    const char* text3 = "123456789012345";
    const char* responderText = "Multi RDM Responder";
    const char* dummyText = "Dummy RDM Responder";

    if (slaveDevice == -1) 
    {
        strcpy((char*)Rdm.Packet.ParameterData, responderText);
        size = 19;
    }
    else
    {
        switch(SlaveResponder[slaveDevice].DeviceModelID)
        {
            case TYPE1:
                strcpy((char*)Rdm.Packet.ParameterData, text1);
                size = 16;
                break;
            case TYPE2:
                strcpy((char*)Rdm.Packet.ParameterData, text2);
                size = 16;
                break;
            case TYPE3:
                strcpy((char*)Rdm.Packet.ParameterData, text3);
                size = 15;
                if (Rdm.Packet.ParameterData[11]==0)
                {
                    // I get here, I don't know why..
                    PORTD SET_B(3); // Debug LED On
                }
                break;
            default:
                strcpy((char*)Rdm.Packet.ParameterData, dummyText);
                size = 19;
                break;
        }
    }

    createRdmHeader(uid);
    Rdm.Packet.ResponseType = RESPONSE_TYPE_ACK;
    Rdm.Packet.CommandClass = GET_COMMAND_RESPONSE;
    Rdm.Packet.PDL = size;

    Rdm.Packet.MessageLength = 24 + Rdm.Packet.PDL;
    checkSum = calculateCheckSum();
    Rdm.Slot[Rdm.Packet.MessageLength] = (checkSum & 0xFF00) >> 8;
    Rdm.Slot[Rdm.Packet.MessageLength + 1] = checkSum & 0x00FF;

    setWaitTimer();
}
  • Whats `Packet.ParameterData`s type? – tkausl Jan 27 '20 at 18:54
  • The type of Packet.ParameterData is uint8_t: uint8_t Packet.ParameterData[231] I've updated the question with this information. – Bart van Stiphout Jan 27 '20 at 18:57
  • I think the problem is with second argument of the strcpy, imo it should be adress of a string not exact string. I dunno what your compiler do with those string. – dunajski Jan 28 '20 at 11:51
  • Please put exact declaration of the `Packet` structure, and `Packet` variable in the code – AterLux Jan 28 '20 at 13:56
  • Maybe you accidentally stored `Packet` in read-only memory? Please provide an [MCVE]. – David Grayson Jan 28 '20 at 14:50
  • Again updated the question with more context. I've tried Dunajski's suggestion, but unfortunately that had no effect. – Bart van Stiphout Jan 28 '20 at 16:28
  • Probably you have too much data in the RAM (for example, I see you have all string constants placed into the RAM), and there is possible a situation when stack overlaps static variables, damaging them. Make sure you have enough space for both stack and static variables. – AterLux Jan 29 '20 at 14:14
  • Are you sure `(char*)Rdm.Packet.ParameterData` is a valid cast? Why not just to use `&Rdm.Packet.ParameterData` or `&Rdm.Packet.ParameterData[0]` (if `char*` is required) instead? – AterLux Jan 29 '20 at 14:17

1 Answers1

0

I'll expand my comment.
AFAIK I know the function strcpy() has two arguments strcpy(char * to, char* from), where to and from are adresses. You used it with exact string, maybe there is no warnings because your IDE disabled it. Make sure that you use -Wall when compiling.

I think you should try use some const char * constant_value = "5432154321543215", instead of invoking strcpy with second argument as string. For me is hard to say what is your strcpy implementation.

At first in your situation I would make sure, you see all warnings from compilation.

dunajski
  • 381
  • 3
  • 15