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.

AM263P4: How to change the SIPC interaction mechanism between the R5 core (HSMclient) and the HSM core (HSMserver) from synchronous blocking to asynchronous notification

Part Number: AM263P4

It is understood that the interaction process between the R5 core and the HSM core is as follows: the R5 core initiates an HSM service, sends an interrupt and related data via SIPC, and the HSM core starts processing the task after receiving the SIPC interrupt. At this time, the R5 core continuously waits for the semaphore to be released. After the HSM core finishes processing the task and triggers an interrupt, the R5 core’s interrupt releases the semaphore, allowing it to proceed to the next step. This is a synchronous blocking approach, as detailed in the flowchart below.

image.png

However, the current situation is that certain tasks requiring processing by the HSM core, such as multiple RSA4096 signatures, are time-consuming. It is unacceptable for the R5 core to wait continuously, so there is a need to modify the existing mechanism to an asynchronous approach.

One idea is for the R5 core (which does not have an RTOS) to periodically check, either continuously or every 50ms (implemented via a timer), whether the semaphore has been released. If the corresponding semaphore is released, it can then process the data returned by the HSM. If this approach is adopted, how can the program be modified with minimal changes to the existing SDK?

For example, directly setting a flag in the SIPC interrupt handler. However, I am curious why the current SDK does not use this method but instead adopts the synchronous semaphore approach. What are the considerations behind this?


Are there any other recommended approaches?

Thank you for the expert's response. This incident is urgent  

  • Hi,

    The SDK focuses on showcasing specific standalone usage of services, because of which it could wait for HSM to respond to R5 and then continue.

    As you mentioned in the flowchart, the communication is based on SIPC, so easiest way would be to trigger a send IPC message from R5 and then continue execution and then poll or check the mailbox interrupt SIPC_mailboxGetPendingIntr(mailboxBaseAddr) and process the same which is received from HSM.

    I believe this should be an approach.

    Thanks and Regards,

    Nikhil Dasan

  • Your meaning is that I should poll the following statements in a loop:
    SIPC_getReadMailbox(&mailboxBaseAddr);
    pendingIntr = SIPC_mailboxGetPendingIntr(mailboxBaseAddr);
    As long as pendingIntr equals 0, it indicates that an SIPC interrupt has occurred and the HSM side has completed processing. At this point, we can proceed to handle the data returned by the HSM. However, I have a few questions:

    1、The normal ISR flow is SIPC_isrHsmClient_isr. We are now using SIPC_mailboxGetPendingIntr to determine whether an SIPC interrupt has occurred. Can it be ensured that if an SIPC interrupt occurs, an HsmClient interrupt will also definitely occur?

    2、Does this approach mean we are no longer using SemaphoreP to synchronize between the HSM core and the R5 core? If so, do the procedures inside HsmClient_isr need to be modified?Furthermore, in the HsmClient_SendAndRecv function, should I remove the SemaphoreP_pend statement and exit directly after completing SIPC_sendMsg?

    3、Upon reviewing the source code, I found that both SIPC_getReadMailbox and SIPC_mailboxGetPendingIntr are static APIs and cannot be called externally. If I want to extract these two APIs separately, can I simply declare the corresponding global variables?

    4、Am I correct in understanding that I only need to check the status in the polling loop, while tasks such as clearing the respective interrupt flags should still be handled within SIPC_isr?

  • Hi,

    1、The normal ISR flow is SIPC_isrHsmClient_isr. We are now using SIPC_mailboxGetPendingIntr to determine whether an SIPC interrupt has occurred. Can it be ensured that if an SIPC interrupt occurs, an HsmClient interrupt will also definitely occur?

    HsmClient_isr is called from SIPC_isr as shown below. So it is a function call from SIPC_Isr. so if SIPC_ISR comes, then HSMClient_ISR will definitely come.

    Also, SIPC is only between R5 core and HSM core, and not between r5 cores.

    2、Does this approach mean we are no longer using SemaphoreP to synchronize between the HSM core and the R5 core? If so, do the procedures inside HsmClient_isr need to be modified?Furthermore, in the HsmClient_SendAndRecv function, should I remove the SemaphoreP_pend statement and exit directly after completing SIPC_sendMsg?

    Yes, you can remove semaphore_pend from HsmClient_SendAndRecv and semaphore_post from HsmClient_isr

    Upon reviewing the source code, I found that both SIPC_getReadMailbox and SIPC_mailboxGetPendingIntr are static APIs and cannot be called externally. If I want to extract these two APIs separately, can I simply declare the corresponding global variables?

    gSIPC_HsmMboxConfig and gSIPC_SecureHostMboxConfig are fixed configurations, you can use them directly 

    Am I correct in understanding that I only need to check the status in the polling loop, while tasks such as clearing the respective interrupt flags should still be handled within SIPC_isr?

    The clearing of interrupt and handling of SIPC will still be in SIPC_isr. 
    The Data from the HSM is populated in HSMClient ISR as shown below 

    Typically in most of our service calls, after calling HsmClient_SendAndRecv, there is a crc check for this received response. This should be taken care and synchronized at your end.

    Thanks and Regards,

    Nikhil Dasan

  • ① Regarding the specific functions that need modification, please verify if my understanding is correct:
    SIPC_mailboxGetPendingIntr: Since the original is directly implemented as static inline in sipc_notify_mailbox.h, including this header in my C file allows calling the function without modification.
    Modification of SIPC_getReadMailbox:
    Option 1: Change the source code of SIPC_getReadMailbox (in sipc_notify_src.c) to a non-static API, declare it in sipc_notify_src.h, recompile the SDK to generate the library, and then use it in my defined .C file.
    Option 2: Directly move the source code of SIPC_getReadMailbox into my own C file, along with the definition of SIPC_Ctrl, and declare gSIPC_ctrl as shown in the figure below.

    Which approach do you recommend? We believe it is generally better to avoid modifying the SDK source code as much as possible.

    HsmClient_isr function: You mentioned masking SemaphoreP_post since this semaphore is no longer needed. Is it possible to leave it unchanged? Similarly, we prefer to avoid modifying the SDK source code whenever possible. Of course, SemaphoreP_pend will be removed in HsmClient_SendAndRecv.

    ② In the original HsmClient_SendAndRecv, after receiving the semaphore, the following operations were performed sequentially:
    crc16_ccit((uint8_t *)&HsmClient->RespMsg, SIPC_MSG_SIZE - 2);
    and
    crc16_ccit((uint8_t *)HsmClient->RespMsg.args, sizeof(HsmAES_t));
    (including SOC_phyToVirt and CacheP_inv).

    Now, with the switch to asynchronous communication, I will first execute SIPC_sendMsg in HsmClient_SendAndRecv and return immediately. Then, during polling, when SIPC_mailboxGetPendingIntr returns 0, I need to sequentially perform CRC checks for HsmClient->RespMsg and HsmClient->RespMsg.args. Is this the correct process?

  • Simulating the loading of programs for the R5 core and HSM core (debug permission for M4 is enabled, loaded via .out files, and HSM functions are operating normally).

    Phase 1: The R5 core sends an SIPC (writes to the mailbox) to the HSM core, triggering the HSM core's SIPC interrupt. However, the HSM core's SIPC interrupt does not proceed further. At this point, reading SIPC_mailboxGetPendingIntr(mailboxBaseAddr) returns 0.

    Phase 2: The R5 core gets stuck at SemaphoreP_pend, waiting for SemaphoreP_post.

    Phase 3: After the HSM core's SIPC interrupt is triggered, HsmServer_isr is invoked, followed by the corresponding handler. The HSM core then sends an SIPC (writes to the mailbox) to the R5 core, triggering the R5 core's SIPC interrupt. After the SIPC interrupt is processed, SemaphoreP_pend can proceed. At this stage, reading SIPC_mailboxGetPendingIntr(mailboxBaseAddr) returns 0.

    My question is: Shouldn't SIPC_mailboxGetPendingIntr return a non-zero value in Phase 1? Because at that point, the R5 core's SIPC interrupt has not been triggered (the HSM has not sent an SIPC (mailbox write) to the R5 core).

    Alternatively, am I using it incorrectly? The described code is only for testing purposes.

    Thank you for your reply. This question is quite urgent

  • Hi,

    Instead of HSM_sendandrecv, Can you check the API HsmClient_EnqueueAndSendMsg() which is a non-blocking SIPC send API, which is used for proc auth boot start, update and stop APIs. 

    Your updation of APIs should be similar to this one.

    Thanks and Regards,

    Nikhil Dasan

  • 1、You mentioned that I should replace HsmClient_SendAndRecv with HsmClient_EnqueueAndSendMsg to send SIPC messages. However, I noticed that this is also a static API. Should I directly copy its code into my C file?

    2、Could you please take a look at this issue? In it, SIPC_getReadMailbox is implemented using method 2 (directly moving the source code of SIPC_getReadMailbox into my own C file, including the definition of SIPC_Ctrl, and declaring gSIPC_ctrl as shown in the figure).

    3、Please take a look at this issue as well, regarding the modification of the HsmClient_isr function.

  • My question is: Shouldn't SIPC_mailboxGetPendingIntr return a non-zero value in Phase 1? Because at that point, the R5 core's SIPC interrupt has not been triggered (the HSM has not sent an SIPC (mailbox write) to the R5 core)

    In this case, first pending interrupt would be on the mailboxBaseAddr of HSM, as R5F had triggered the interrupt. Only when HSM triggers the mailbox interrupt, the pending is non-zero at R5 end.

    3、Please take a look at this issue as well, regarding the modification of the HsmClient_isr function.

    Post without pend is not suggested and tested. As mentioned earlier, the HSMClient APIs are tested for blocking usecases except for the services of proc_auth_boot of mcelf image. 

    Only this service uses non-blocking approach as the situation needs the same.

    May I know what usecase are you looking for in unblock HSM service?

    Thanks and Regards,

    Nikhil Dasan

  • Let me rephrase my understanding.

    Phase 1: After the R5 core performs SIPC_mailboxWrite, it triggers an SIPC interrupt on the HSM core. At this point, the HSM core enters SIPC_isr. Within SIPC_isr, it first executes SIPC_mailboxGetPendingIntr. The value read from the HSM_SOC_CTRL_HSM_MBOX_READ_DONE register at this time is 0x00000001, indicating that there is a pending interrupt on the HSM core side. Then, it executes SIPC_mailboxClearPendingIntr to clear the HSM_SOC_CTRL_HSM_MBOX_READ_DONE register, setting its value to 0x00000000.

    Phase 2: The HSM core executes the corresponding operations (such as TRNG, AES, RSA) and then performs SIPC_mailboxWrite, which triggers an SIPC interrupt on the R5 core.

    Phase 3: At this point, the R5 core enters SIPC_isr. Within SIPC_isr, it first executes SIPC_mailboxGetPendingIntr. The value read from the MSS_CTRL_R5SS0_CORE0_MBOX_READ_DONE register at this time is 0x01000000, indicating that there is a pending interrupt on the R5 core side. Then, it executes SIPC_mailboxClearPendingIntr to clear the MSS_CTRL_R5SS0_CORE0_MBOX_READ_DONE register, setting its value to 0x00000000.

    ①Is my understanding correct?

    Now, returning to the previous question regarding how to determine whether the HSM core has completed the corresponding operations to achieve asynchronous operation, your earlier suggestion was to use SIPC_mailboxGetPendingIntr to query whether there is a pending interrupt after the R5 core triggers the SIPC interrupt on the HSM core.

    Ideally, after the R5 core triggers the interrupt on the HSM core and the HSM core completes its tasks, it triggers an SIPC interrupt on the R5 core. In the R5 core’s interrupt service routine, the pending interrupt is synchronously cleared (by zeroing the MSS_CTRL_R5SS0_CORE0_MBOX_READ_DONE register). Therefore, as long as SIPC_mailboxGetPendingIntr returns 0, it indicates that the HSM core has completed its operations.

    However, I have a question: After the R5 core triggers the SIPC interrupt on the HSM core, and while the HSM core is still processing the task, it has not yet triggered the SIPC interrupt on the R5 core. In this scenario, a simulation shows that executing SIPC_mailboxGetPendingIntr also returns 0.

    How can I distinguish between the case where the HSM core has completed the task and triggered the R5 core interrupt, and the case where the HSM core is still processing the task?

  • Hi,

    Sorry for delay in response due to vacation.

    Phase 1: After the R5 core performs SIPC_mailboxWrite, it triggers an SIPC interrupt on the HSM core. At this point, the HSM core enters SIPC_isr. Within SIPC_isr, it first executes SIPC_mailboxGetPendingIntr. The value read from the HSM_SOC_CTRL_HSM_MBOX_READ_DONE register at this time is 0x00000001, indicating that there is a pending interrupt on the HSM core side. Then, it executes SIPC_mailboxClearPendingIntr to clear the HSM_SOC_CTRL_HSM_MBOX_READ_DONE register, setting its value to 0x00000000.

    Phase 2: The HSM core executes the corresponding operations (such as TRNG, AES, RSA) and then performs SIPC_mailboxWrite, which triggers an SIPC interrupt on the R5 core.

    Phase 3: At this point, the R5 core enters SIPC_isr. Within SIPC_isr, it first executes SIPC_mailboxGetPendingIntr. The value read from the MSS_CTRL_R5SS0_CORE0_MBOX_READ_DONE register at this time is 0x01000000, indicating that there is a pending interrupt on the R5 core side. Then, it executes SIPC_mailboxClearPendingIntr to clear the MSS_CTRL_R5SS0_CORE0_MBOX_READ_DONE register, setting its value to 0x00000000.

    ①Is my understanding correct?

    Yes, correct.

    However, I have a question: After the R5 core triggers the SIPC interrupt on the HSM core, and while the HSM core is still processing the task, it has not yet triggered the SIPC interrupt on the R5 core. In this scenario, a simulation shows that executing SIPC_mailboxGetPendingIntr also returns 0.

    How can I distinguish between the case where the HSM core has completed the task and triggered the R5 core interrupt, and the case where the HSM core is still processing the task?

    As mentioned above, after R5 core triggers SIPC interrupt to HSM core, the pending should be to get 0x01000000 from SIPC_mailboxGetPendingIntr.

    Upon receiving this, we would know that HSM as completed its operation, and then this should be cleared by R5F core.

    May I know what usecase are you looking for in unblock HSM service?

    My question again. May I know the usecase for which HSM service should be unblocked.

    Thanks and Regards,

    Nikhil Dasan

  • Thank you for your response.

    Based on your explanation, after the R5 core triggers the SIPC interrupt to the HSM core and before the HSM core triggers the SIPC interrupt to the R5 core, the value I read via SIPC_mailboxGetPendingIntr should be non-zero. However, during simulation testing, the value I read is still 0. May I ask why this is happening?

    To clarify, I am simulating the HSM program’s .out file, and after the R5 core triggers the SIPC interrupt to the HSM core, I intentionally halt within the ISR below to prevent the HSM core from triggering the SIPC interrupt back to the R5 core.

    I placed the SIPC_mailboxGetPendingIntr call at the following point—after the R5 core triggers the SIPC interrupt to the HSM core—to read the value.

    Regarding your question, since we are now planning to unify the HSM service requests under the AUTOSAR architecture, all HSM services—such as TRNG, AES, SHA, RSA, and ECC—must support both asynchronous and synchronous operation modes. Therefore, we must abandon the previous approach of using SemaphoreP post/pend to determine whether the HSM core has completed a task, and switch to methods such as interrupt flag indicators instead.

  • Hi,

    Based on your explanation, after the R5 core triggers the SIPC interrupt to the HSM core and before the HSM core triggers the SIPC interrupt to the R5 core, the value I read via SIPC_mailboxGetPendingIntr should be non-zero. However, during simulation testing, the value I read is still 0. May I ask why this is happening?

    No, The value of SIPC_mailboxGetPendingIntr would be 0x01000000 only after HSM core triggers the SIPC interrupt to R5 and it would remain with this value, until you clear it.

    Regarding your question, since we are now planning to unify the HSM service requests under the AUTOSAR architecture, all HSM services—such as TRNG, AES, SHA, RSA, and ECC—must support both asynchronous and synchronous operation modes. Therefore, we must abandon the previous approach of using SemaphoreP post/pend to determine whether the HSM core has completed a task, and switch to methods such as interrupt flag indicators instead.

    I see. Thank you for clarifying this.

  • Yes, my understanding is actually the same as yours.

    Briefly describe the entire task execution flow:
    ① The R5 core triggers an SIPC interrupt to the HSM core (PendingIntr = 0x00000001).
    ② The HSM core clears the interrupt (PendingIntr = 0) and then processes the task.
    ③ After completing the task, the HSM core triggers an SIPC interrupt to the R5 core (PendingIntr = 0x01000000).
    ④ The R5 core clears the interrupt (PendingIntr = 0), receives the information, and completes the entire task.

         My original intention was to ask TI to provide a method that, after I execute stage ①, allows me to determine whether the system is in stage ② (HSM core is processing) or stage ③ (HSM core has finished processing).

         However, as I described above, during stage ②, SIPC_mailboxGetPendingIntr reads PendingIntr = 0. In stage ③, although SIPC_mailboxGetPendingIntr reads PendingIntr as 0x01000000 very briefly, it is quickly cleared by the ISR and becomes 0 again. Therefore, if I continuously call SIPC_mailboxGetPendingIntr to read PendingIntr (to obtain the HSM execution status), I can consider that the read PendingIntr is always 0 (except for the very brief moment when it is 0x01000000).

         Based on this logic, I personally believe that using SIPC_mailboxGetPendingIntr alone is insufficient to determine whether the HSM core is processing (stage ②) or has completed processing (stage ③). Therefore, could you provide a practical and reliable method to achieve the functionality described above?

         I had previously considered adding a custom flag directly in the R5 core’s SIPC ISR and then judging the status of this flag to determine whether the HSM core triggered the SIPC interrupt to the R5 core—essentially determining whether the HSM core has completed its task. However, I hope to avoid modifying the original SDK code as much as possible while ensuring program reliability.

  • Hi,

    Sorry for the delay in response. 

    There is no way we can achieve this without modification in the drivers.

    The easiest way to achieve this is to call a callback function in Hsmclient_ISR, which would be a function in the application, (instead of posting semaphore),

    So that you can have the information on the reception of HSM response at the application level.

    This would be a cleaner approach to achieve this.

    Thanks and Regards,

    Nikhil Dasan

  • Hello, we have another approach here:

    Regarding the SemaphoreP_pend function, in the original example code, the timeout parameter for SemaphoreP_pend was set to SystemP_WAIT_FOREVER. This means that once SemaphoreP_pend is called, it continuously polls the semaphore until it is released, which forms the basis for synchronizing the HSMClient in the example. I am now considering changing the timeout to SystemP_NO_WAIT. This way, instead of waiting indefinitely in SemaphoreP_pend, the function would only check once. If the semaphore is not released, it would exit the function and proceed to execute other tasks until the next polling cycle when SemaphoreP_pend is called again. If the semaphore is released, it would then read the data returned by the HSM. This approach aims to achieve asynchronous-like communication. Is this method suitable for implementing asynchronous communication in an application without an OS?

    Below is the specific workflow, which has been verified to work in practice:

    ① Initiate an HSM client request, such as an AES operation.


    ② In the polling loop, check whether the semaphore SemaphoreP has been released.


    In the polling loop,If jobProcessState == JOB_PROCESS_STATE_FINISH in step ②, call HsmClient_AES_Algo_Callback to process the data returned by the HSM.

    The following are HsmClient_Send and HsmClient_Recv, which are derived by splitting the original HsmClient_SendAndRecv API.

    Thank you for your reply!!

  • Sure, 

    Regarding the semaphore implementation here, are you using your own implementation inside Semaphore APIs? Because, in the SDK version, there is a nortos / freertos version of this implementation.

    Assuming you have autosar running, you would be having a autosar version of the same right?

    Thanks and Regards,

    Nikhil Dasan

  • Hello,Thank you for your reply

    The aforementioned SemaphoreP_pend is still based on the SDK, except that the timeToWaitInTicks parameter from the example code has been changed from SystemP_WAIT_FOREVER to SystemP_NO_WAIT. This allows the process to avoid being blocked indefinitely when the semaphore is not immediately released via a post operation. Instead, it can proceed to handle other tasks and check the SemaphoreP status later, achieving an effect similar to asynchronous communication. This approach is the minimal modification I could think of to implement asynchronous communication within the existing program.

    The aforementioned test verification was conducted in a no-OS application. However, issues arose when testing in an application with an OS, as described in the referenced post:AM263P4: Based on the fls_boot_app example from Pre-release MCAL 11.01.00.07, the TRNG cannot be retrieved multiple times, and this is the issue. - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums

    As per your description, are the implementations of semaphores, such as SemaphoreP_pend, different between noRTOS and FreeRTOS? The OS we are using is OSEK. May I ask if the semaphore APIs implemented by TI based on FreeRTOS can also run on an OSEK-based system?

  • Hi,

    Sorry for the delay in response.

    Yes, there are difference in implementation of DPL layers based on the OS used. i.e. nortos vs freertos there are differences, as we use freertos APIs in the case of FREERTOS OS.

    SemaphoreP is a DPL API.
    Device Porting Layer (DPL), aka OS Abstraction Layer, is added to abstract the OS specific APIs.

    OSEK is Autosar, so that would have another way of implementation 

    For nortos, for timeout timers would be needed, whereas in freertos RTOS timers handle timeout, which would also be the case in OSEK I believe. 

    Thanks and Regards,

    Nikhil Dasan