Introduction
Scope
The scope of the Application Note is to describe different strategies to use BSW NvM Services cross-core.
Definitions and Abbreviations
BSW: AUTOSAR Basic Software, Hardware independent service layer
RTE: AUTOSAR Run-Time Environment
OS: AUTOSAR Operating System
SWC: Software Component
References
[01] 04 - Memory Stack configuration - RTA-CAR 9.2.0 - Step by step guide to create a PIM and configure the BSW
[02] RTA-CAR 9.2.0 - Multicore Configuration - Application note for the creation of a RTA-CAR Multicore Project
Toolchain
It is assumed you are using the RTA-CAR 9.2.0 toolchain and later:
RTA-CAR 9.2.0 toolchain | |
---|---|
ISOLAR-AB | v 9.2.0 |
RTA-RTE | v 7.5.0 |
RTA-BSW | v 6.1.2 |
RTA-OS | v 6.2.0 |
Prerequisites
In order to successfully follow this guide, you must have the RTA-CAR toolchain installed, and you must be familiar with the AUTOSAR specifications, terminology and methodology.
Moreover, it is strongly advised to be familiar with OS and RTE Multicore configurations/concepts (such as Os Partitions, IOC interfaces).
Possible use-cases for NvM Multicore Usage
Use-case 1: Using cross-core PIM from SWCs
The first (and simplest) use case we analyse is the usage of PIMs (PerInstanceMemory) which can access the NvM services cross core. The use-case is depicted in the picture below. The SWC which is allocated in a secondary partition/core (i.e. in a different partition/core than the BSW NvM module) and accesses the NvM services cross-core using the RTE interfaces. (Consult [01] to understand how to create the PIM in your project).
In order to use the PIM, as explained in [01], you need to connect it to the NvM Service SW Component with a NvMService interface. Once you have your SWC connected with the NvM in your SW Composition, you need to create the Server Call Points to grant the access through the port. You now have 2 possibilities: using Synchronous server call points, or Asynchronous server call points.
Using Synch server call points
With Synchronous Server Call Points, the RTE will create the code to call the Server, and then wait for the result. Since the task in which the Client (our SWC) is mapped needs to wait for the Server, the RTE must create an Extended Task. Below some code snippet of the created RTE interfaces and Task.
RTE result using sync server call points:
FUNC(Std_ReturnType, RTE_CODE) Rte_Call_Core1SWC_RPort_NvMCore1_WriteBlock(VAR(NvM_Rb_ConstVoidPtr, AUTOMATIC) SrcPtr) /* 2 */ { VAR(Std_ReturnType, AUTOMATIC) rtn; Rte_CPT_NvM_NvM_NativeBlock_3_WriteBlock_RtnQEType cliQEl; Rte_CPT_NvM_NvM_NativeBlock_3_WriteBlock_QEType srvQEl; srvQEl.SrcPtr = SrcPtr; srvQEl.client_id = RTE_CLIENTID_CPT_CORE1SWC_RPORT_NVMCORE1_WRITEBLOCK; rtn = IocSend_CPT_NvM_NvM_NativeBlock_3_WriteBlock(&srvQEl); if ( ((VAR(StatusType, AUTOMATIC))E_OK) == rtn ) { ActivateTask(OsTask_Events); } if ( ((VAR(Std_ReturnType, AUTOMATIC))RTE_E_OK) == rtn ) { rtn = Rte_WaitWithTimeout(&Rte_Event_CPT_Core1SWC_RPort_NvMCore1_WriteBlock_wd, RTE_EVENT_CPT_Core1SWC_RPort_NvMCore1_WriteBlock, 0); if ( ((VAR(Std_ReturnType, AUTOMATIC))RTE_E_OK) == rtn ) { rtn = IocReceive_CPT_Core1SWC_RPort_NvMCore1_WriteBlock(&cliQEl); if ( ((VAR(Std_ReturnType, AUTOMATIC))RTE_E_OK) == rtn ) { rtn = cliQEl.rtnval; } } } return rtn; }
You also get extended tasks:
TASK(OsTask_ASW_Core1) { for ( ; ; ) { WaitEvent(Rte_Ev_CPT_Core1SWC_DataReceivedEvent_0); ClearEvent(Rte_Ev_CPT_Core1SWC_DataReceivedEvent_0); /* Box: Implicit Buffer Initialization begin */ /* Box: Implicit Buffer Initialization end */ /* Box: Implicit Buffer Fill begin */ /* Box: Implicit Buffer Fill end */ { /* Box: CPT_Core1SWC begin */ RE_Main_Core1(); /* Box: CPT_Core1SWC end */ } /* Box: Implicit Buffer Flush begin */ /* Box: Implicit Buffer Flush end */ } } /* OsTask_ASW_Core1 */
Using Asynch server call points
The Asynch Server Call Points don't need an extended Task to be created, since the caller doesn't have to wait to get the answer from the Server.
In fact, as you can see in the code snipped below, the task is not extended anymore :
TASK(OsTask_ASW_Core1) { /* Box: Implicit Buffer Initialization begin */ /* Box: Implicit Buffer Initialization end */ /* Box: Implicit Buffer Fill begin */ /* Box: Implicit Buffer Fill end */ /* Box: CPT_Core1SWC begin */ if ( Rte_ActCount_CPT_Core1SWC_DataReceivedEvent_0 != FALSE ) { Rte_ActCount_CPT_Core1SWC_DataReceivedEvent_0 = FALSE; RE_Main_Core1(); } /* Box: CPT_Core1SWC end */ /* Box: Implicit Buffer Flush begin */ /* Box: Implicit Buffer Flush end */ TerminateTask(); } /* OsTask_ASW_Core1 */
Also in this case, the RTE interfaces will use IOCs to interface with NvM
FUNC(Std_ReturnType, RTE_CODE) Rte_Call_Core1SWC_RPort_NvMCore1_WriteBlock(VAR(NvM_Rb_ConstVoidPtr, AUTOMATIC) SrcPtr) /* 2 */ { VAR(Std_ReturnType, AUTOMATIC) rtn = RTE_E_LIMIT; boolean invoking_op = FALSE; Rte_CPT_NvM_NvM_NativeBlock_3_WriteBlock_Type srv1; if ( TRUE != Rte_Call_CPT_Core1SWC_RPort_NvMCore1_WriteBlock_Flag ) { Rte_SuspendOSInterrupts(); if ( TRUE != Rte_Call_CPT_Core1SWC_RPort_NvMCore1_WriteBlock_Flag ) { Rte_Call_CPT_Core1SWC_RPort_NvMCore1_WriteBlock_Flag = TRUE; invoking_op = TRUE; } Rte_ResumeOSInterrupts(); if ( TRUE == invoking_op ) { srv1.SrcPtr = SrcPtr; ((void)IocWrite_RTE_CPT_Core1SWC_RPort_NvMCore1_WriteBlock(&srv1)); rtn = ((VAR(Std_ReturnType, AUTOMATIC))RTE_E_OK); } } return rtn; }
Application source code implementation
{ /* Box: CPT_NvM begin */ /* NvM_NativeBlock_3 */ { if ( 0U != Rte_ActCount_CPT_NvM_EWBL_NvM_NativeBlock_3_CPT_Core1SWC_AsynchronousServerCallPoint_10 ) { Rte_CPT_NvM_NvM_NativeBlock_3_WriteBlock_Type callVar; Rte_CPT_NvM_NvM_NativeBlock_3_WriteBlock_RtnType rtnVar; Rte_ActCount_CPT_NvM_EWBL_NvM_NativeBlock_3_CPT_Core1SWC_AsynchronousServerCallPoint_10 = 0U; (void)IocRead_RTE_CPT_Core1SWC_RPort_NvMCore1_WriteBlock(&callVar); rtnVar.rtnval = NvM_WriteBlock(((VAR(NvM_BlockIdType, AUTOMATIC))9), callVar.SrcPtr); (void)IocWrite_RTE_CPT_Core1SWC_RPort_NvMCore1_WriteBlock_Rtn(&rtnVar); } } /* Box: CPT_NvM end */ }
Use-case 2: Crosscore data access with NvBlockSwComponent in the same partition of NvM
Even if this usecase might look like a good option, it is something that AUTOSAR in general does not allow, as shown in this requirement extracted from the RTE AR specs.
From AR specs [SWS_Rte_07343]
Since the direct cross core access is not allowed, an alternative solution would be to use a Proxy NvM SWC. The role of the proxy SWC would be to access the data.
NB: The Proxy SWC needs to be manually created by the user, RTA-CAR tools don't automatically create the Proxy SWC.
Once you have the ProxySWC created, you can connect it with SR or CS interfaces with the ASW placed in the Partition 1.
Use-case 3: Using NvBlockSwComponent in a different partition of NvM
This use case is currently not supported by RTA-RTE. We suggest to use the strategy of the ProxySWC or the Cross-core PIM.