2

I have reading several AUTOSAR Documents. For now, my concern is just developing Software Component. I have two software component designs, take a look to the picture below.

enter image description here

Explanation:

  1. I got a data from port 1 and 2. Each of ports will correspondence with RunnableEntity which running when a new data has come. Then, the RunnableEntity sets that data to InterRunnableVariable. The main RunnableEntity which is RunnableEntity 1 will process the InterRunnableVariable to make an output.
  2. The data freely come to the port and waiting to be proceed in the buffer. Then, The only one RunnableEntity will process the data with some help by common global variable (The purpose of global variable is same with InterRunnableVariable).

My questions are,

  1. Will design 1 and 2 work?
  2. If design 1 and 2 are true, which one do you prefer according the time process, time to implement, etc.?
  3. Are the codes right? how to handle event and InterRunnableVariable?

Thank you for your help.

====================Adding Code After Comment========================

Design 1

/* Runnable Entity 1*/
/* Event : TimeEvent 25ms */
void re1(void){
    data_output out;
    irv irv1 = Rte_IrvIread_re1_irv1(); 
    irv irv2 = Rte_IrvIread_re1_irv2();
    irv irv3 = Rte_IrvIread_re1_irv3();

    out = DataProcess(&irv1,&irv2,&irv3);

    Rte_Write_re1_port3_out();
}

/* Runnable Entity 2*/
/* Event : DataReceiveErrorEvent on port1 */
void re2(void){     
    irv irv2 = Rte_IrvIread_re1_irv2();

    modify(&irv2);

    Rte_IrvIwrite_re1_irv2(irv2);
}

/* Runnable Entity 3*/
/* Event : DataReceiveEvent on port1 */
void re2(void){
    data_input1 in;
    Std_RetrunType status;

    irv irv1 = Rte_IrvIread_re1_irv1(); 
    status = Rte_Receive_re1_port1_input(&in);
    if (status == RTE_E_OK) {
        modify(&irv1,in);
        Rte_IrvIwrite_re1_irv1(irv1);
    }
}

/* Runnable Entity 4*/
/* Event : DataReceiveEvent on port2 */
void re2(void){
    data_input2 in;
    Std_RetrunType status;

    irv irv3 = Rte_IrvIread_re1_irv3(); 
    status = Rte_Receive_re1_port2_input2(&in);
    if (status == RTE_E_OK) {
        modify(&irv3,in2);
        Rte_IrvIwrite_re1_irv3(irv3);
    }
}

Design 2

/*Global Variable*/
global_variable1 gvar1; /* Equal with InterVariable 1 in Design 1*/
global_variable2 gvar2; /* Equal with InterVariable 2 in Design 1*/
global_variable3 gvar3; /* Equal with InterVariable 3 in Design 1*/

/* Runnable Entity 1*/
/* Event : TimeEvent 25ms */
void re1(void){
    data_output out;
    GetData1()
    GetData2()


    out = GetOutputWithGlobalVariable();

    Rte_Write_re1_port3_out(out);
}

/* Get Data 1*/
void getData1(){    
    Std_ReturnType status; /* uint8  */
    data_input1 in;

    do {
        status = Rte_Receive_re1_port1_input1(&in);
        if (status == RTE_E_OK) {
            modifyGlobalVariable(in);
        }
    } while (status != RTE_E_NO_DATA && status != RTE_E_LOST_DATA);

    if(status != RTE_E_LOST_DATA){
        modifyGlobalVariableWhenError();
    }
    return;
}

/* Get Data 2*/
void getData2(){    
    Std_ReturnType status; /* uint8  */
    data_input2 in;

    do {
        status = Rte_Receive_re1_port2_input2(&in);
        if (_status == RTE_E_OK) {
            modifyGlobalVariable2(in);
        }
    } while (status != RTE_E_NO_DATA && status != RTE_E_LOST_DATA);

    return;
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
Whilda Chaq
  • 364
  • 1
  • 6
  • 17

2 Answers2

3

I think both solutions are possible. The main difference is that in the first solution the generated Rte will manage the global buffer whereas in the second design, you have to take care of the buffers yourself. Especially if you have multiple runnables accessing the same buffer, the 'Rte' will either generate interrupt locks to protected data consistency or it will optimize out the locks if the task context in that the ´RunnableEntities´ are running cannot interrupt each other.

Even if you have only one ´RunnableEntity´ as shown in the second design, it might happen that the ´TimingEvent´ activates the ´RunnableEntity´ and the DataReceivedEvent as well (although I don't understand why you left out the DataReceivedEvent in the second design). In this case the ´RunnableEntity´ is running in two different contexts accessing the same data.

To make it short: My proposal is to use interrunnable variables and let the Rte handle the data consistency, initialization etc. It might be a little bit more effort to create the software component description, but then you just need to use the generated IrvRead/IrvWrite functions and you are done.

ZzetT
  • 568
  • 4
  • 16
  • thank`s again for your answer. You are great at AUTOSAR. 1. I though that buffer in the first design and second design are handled by RTE. 2. Please take a look to second design's code, that is why I didn't use DataReceivedEvent. If I am right. – Whilda Chaq Mar 14 '16 at 02:25
  • 1
    The second design looks bad to me. Especially the loop to wait for new data is busy waiting meaning that it could block the whole ECU. For this you should use DataReceivedEvents or configure a blocking Rte_Receive (Rte will wait via WaitEvent() instead of busy waiting). Also I'm still not sure if you could run into a concurrency problem if two different runnables are reading/modifiyng the same global buffer. All in all the first code looks much smaller too. – ZzetT Mar 14 '16 at 21:53
  • Actually, I thought that part of second design is using non-blocking Rte_receive. So, I didn't need wait point and DataReceivedEvents. Am I right? This event still confusing me. – Whilda Chaq Mar 14 '16 at 23:35
  • You could try mutex in this case. – Sivaramakrishna Shriraam Aug 03 '17 at 07:56
0

I'm actually prefering here the first one.

The second one depends a bit on your SWC Description, since there is the specification of the Port Data Access. From this definition it depends, if the RTE creates a blocking or non-blocking Rte_Receive.

[SWS_Rte_01288] A non-blocking Rte_Receive API shall be generated if a VariableAccess in the dataReceivePointByArgument role references a required VariableDataPrototype with ‘event’ semantics. (SRS_Rte_00051)

[SWS_Rte_07638] The RTE Generator shall reject configurations were a VariableDataPrototype with ‘event’ semantics is referenced by a VariableAccess in the dataReceivePointByValue role. (SRS_Rte_00018)

[SWS_Rte_01290] A blocking Rte_Receive API shall be generated if a VariableAccess in the dataReceivePointByArgument role references a required VariableDataPrototype with ‘event’ semantics that is, in turn, referenced by a DataReceivedEvent and the DataReceivedEvent is referenced by a WaitPoint. (SRS_Rte_00051)

On the other side, I'm not sure what happens with your blocking Rte_Receive vs your TimingEvent based RunnableEntity call.

Also consider the following:

RTE_E_LOST_DATA actually means, you lost data due to incoming data overflowing the queue (Rte_Receive only works with swImplPoliy = queued, otherwise if swImplPolicy != queued you get Rte_Read). This is not an excplicit Std_ReturnType value, but a flag added to that return value -> OverlayedError)

RTE_E_TIMEOUT would be for blocking Rte_Receive

RTE_E_NO_DATA would be for non-blocking Rte_Receive

you should then check as:

Std_ReturnType status;
status = Rte_Receive_..(<instance>, <parameters>);
if (Rte_HasOverlayedError(status)) {
    // Handle e.g. RTE_E_LOST_DATA
}
// not with Rte_Receive - if(Rte_IsInfrastructureError(status)) { }
else { /* handle application error with error code status */
    status = Rte_ApplicationError(status);
}
kesselhaus
  • 1,241
  • 8
  • 9