1

I have the following code

    typedef struct{
    uint8_t carOpening:2;
    uint8_t fCarElement:4;
}lockState_t;

    enum Doors
{
    DRIVER_DOOR = 0,
    PASSENGER_DOOR,
    ...
    NUMBER_OF_ELEMENTS
};

class DoorState
{
public:
    DoorState(Doors door, uint8_t initialState)
    {
        fState.fCarElement = static_cast<uint8_t>(door);
        if(initialState == SIG_VAL_DOOR_CLOSED)
        {
            fState.carOpening = static_cast<uint8_t>(DOOR_CLOSED);
        }
        else if(initialState == SIG_VAL_DOOR_OPENED)
        {
            fState.carOpening = static_cast<uint8_t>(DOOR_OPENED);
        }
        else
        {
            fState.carOpening = static_cast<uint8_t>(DOOR_UNKNOWN);
        }
    };
    void checkSignal(uint8_t signal);
    enum tState { DOOR_UNKNOWN = 0, DOOR_CLOSED, DOOR_OPENED };
private:
    static const uint8_t SIG_VAL_DOOR_CLOSED = 0x00;
    static const uint8_t SIG_VAL_DOOR_OPENED = 0x01;

    lockState_t fState;
};

Then I have a few instances of this class, like:

DoorState fDriverDoorState;
DoorState fPassengerDoorState;

This is how I initialize the instances:

, fDriverDoorState(DRIVER_DOOR
, DS::instance().get<uint8_t>(DS::ComStatZvKlappen_StDswDrd_ID))
, fPassengerDoorState(PASSENGER_DOOR, DS::instance().get<uint8_t>(DS::ComStatZvKlappen_StDswPsd_ID))

Then I am checking if the state of the door has changed and publising a message if it has:

tState doorState = DOOR_UNKNOWN;
if (SIG_VAL_DOOR_CLOSED == signal)
{
    doorState = DOOR_CLOSED;
}
else if (SIG_VAL_DOOR_OPENED == signal)
{
    doorState = DOOR_OPENED;
}

if(doorState != static_cast<tState>(fState.carOpening))
{
    fState.carOpening = static_cast<uint8_t>(doorState);
    if(DOOR_UNKNOWN != doorState)
    {
        LooperEventBroker::publish(::csm::events::CsmEvents::VEHICLE_LOCK_STATE_EVENT(), &fState);
        Logger::info(VEHICLE, "Door %s event published for %s",
                     doorState == DOOR_OPENED ? "openend" : "closed", opening2string(fState.fCarElement));
    }
}

For the most part it is working perfectly. The strange part is that sometimes I see this log being posted: "Door closed event published for INVALID DOOR", which should not happen as no instance is initialized with INVALID DOOR, and fCarElement, which stores the door type, is never modified. Which means that somehow fCarElement gets corrupted. Question is where or why?

As requested here is the implementation of opening2string function:

static const char* opening2string(uint8_t opening)
{
    switch (opening)
    {
        case DRIVER_DOOR:
            return "DRIVER DOOR";
        case PASSENGER_DOOR:
            return "PASSENGER DOOR";
        ...
        default:
            return "INVALID DOOR";
    }
}

Regards, Gabriel

  • 1
    Given that you use non-standard bit-fields, anything can happen. Maybe the project was ported to another compiler. Apart from that, memory corruptions could happen because of stack overflows or runaway code. If/how that is possible depends on the system. Which compiler and MCU are used? If it supports trace, then a write breakpoint on the variable should immediately locate the bug for you. And generally, C++11 and automotive is a horrible combination. Don't you have quality and safety standards to follow? – Lundin Dec 18 '18 at 12:58
  • @Lundin, it is Diab compiler that we are using and MPC5646C MCU, which is based on PowerPC core. As for quality and safety, this is a small agile project, so we are perfoming module tests, integration tests and code reviews, and all have passed. This issue is encountered very rarelly and never on test environment. I know C++ and automotive is a horrible combination, but this is how we took the project :) – Moraru Gabriel Dec 18 '18 at 13:36
  • Ok I have worked lots with MPC56 and it does have trace. Simply set a write breakpoint on the memory address, then view the instruction trace. If you have a decent debugger, it should have an option to show the trace as C code. As for doing C++11 on a safety MCU, that's pretty much madness - since you apparently have no safety requirements like ASIL/MISRA, you could as well have picked any mainstream ARM instead and saved yourself from all the extra pain involved in using MPC56. – Lundin Dec 18 '18 at 14:00
  • Needless to say, this assumes that the variable is allocated with static storage duration (.data/.bss). If it's stack allocated, then of course any kind of bug could have wiped it out. – Lundin Dec 18 '18 at 14:02
  • 1
    Oh and btw you must absolutely check the errata for these parts and ensure you have no old silicon masksets! The first MPC56 were completely useless, filled with numerous severe hardware bugs. Ensure you have the latest mask and read the errata for that one. This is pretty much the first thing one needs to do before using MPC56 for any project. – Lundin Dec 18 '18 at 14:06
  • Rather unhelpfully, you have elided the code that tells us what value INVALID_DOOR has. – Clifford Dec 18 '18 at 17:53
  • Your instances have no parameters and there is no default constructor. Post the real code, not a description of the code! The chances are in this elided form you have omitted the part that is in error - since you have no idea where the error is, you are not qualified to make those decisions. – Clifford Dec 18 '18 at 17:57
  • The string "INVALID DOOR" is generated by `opening2string()` yet you have chose not to include that code. How can we be sure that `fCarElement` has changed rather then just `opening2string()` is wrong!? – Clifford Dec 18 '18 at 18:01
  • @Clifford I believed it was implicit how INVALID_DOOR is obtained – Moraru Gabriel Dec 19 '18 at 08:47
  • @Clifford this is the real code, it is just not the whole code. It would not make sense to post the whole code. I posted only the code that has anything to do with fCarElement. So actually there is no default constructor. – Moraru Gabriel Dec 19 '18 at 08:49
  • You say you have instantiated for example `DoorState fDriverDoorState;`, but that is not possible since the only constructor defined requires arguments. i..e _not real code_. – Clifford Dec 19 '18 at 09:59
  • @Clifford, that is the declaration of the instance, the initialization is in the next code sequence. – Moraru Gabriel Dec 19 '18 at 12:34
  • No; you still don't get it. You cannot instantiate an object without a matching constructor. – Clifford Dec 19 '18 at 13:12

0 Answers0