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.

SK-AM64B: Query on sharing memory (MSRAM) between R5 and M4

Part Number: SK-AM64B
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello Team

I was testing the IPC Spinlock Shared memory example. The example works well on SK EVM


I want to add M4 core in this system project. I took the empty example for M4 core and reused the spinlock test code from other cores examples.

My question is:
1. How do I configure the M4 core to use the same shared memory? What configuration do I have to do in .syscfg file?


2. In this example, we are sharing only a single variable (4 bytes long). How do I share a larger memory chunk say an array of 8 (4 bytes each)?

Thanks
Amey

  • Hi Amey,

    What version of the SDK are you working with?

    You want to create an example with R5F0_0, R5F0_1 and M4F0_0, is my understanding correct?

    Regards,

    Nitika

  • Hi Nitika

    I am using mcu_plus_sdk_am64x_09_02_00_50 MCU+SDK

    You want to create an example with R5F0_0, R5F0_1 and M4F0_0, is my understanding correct?

    Yes. The current example in the SDK has R50_0 and R50_1. I want to add M4 to it

  • Hi Amey,

    1. How do I configure the M4 core to use the same shared memory? What configuration do I have to do in .syscfg file?

    To make M4 access the same shared memory, M4 project should have the MPU region defined in sysconfig and having access to the shared memory location. It would be better to add M4 project as part of the system project. You can refer to the IPC_notify_echo or IPC_rpmsg_echo message in the SDK to understand how M4 is added as part of the system project.

    How do I share a larger memory chunk say an array of 8 (4 bytes each)?

    Similar to how we define a variable to shared memory section, you can define an array similarly as well: 

    volatile uint32_t gUserSharedMem[5] __attribute__((aligned(128), section(".bss.user_shared_mem")));
     
    Regards,
    Nitika
  • Thank you Nitika, I will give this a try and get back.

    Is there any link/KB article to understand configuration on syscfg file for memory sharing?

  • You can read about the steps involved in Enabling IPC in an application here

    This might be helpful, do let me know if you face any issues.

    Regards,

    Nitika

  • Hi Nitika

    Thanks for the sharing the link.

    I am trying out following scenario and facing an issue where data is not being shared between the cores:

    I want to transfer the data coming from UART of M4 core to be sent to UART of R50_0 core (single direction only for now). So I believe spinlock is not needed as whenever the value changes I am printing it in R50_0 core.
    I am using the empty example system project and replaced the default project with UART echo example for R50_0 and M4 cores.
    Other cores are not used hence the project linked to those cores are removed from system project. So now system project has two project (See below)

    In the example.syscfg of R50_0 core, I have shared the memory. See the screenshot below.

    Also in the syscfg of M4 core, access to MRAM is added.


    IPC is added to ensure all cores will start together. I have added IpcNotify_syncAll(SystemP_WAIT_FOREVER); at the begining
    of the examples and all cores start together.

    But when I try to run, I see that even the M4 core is placing the data in the shared memory, the same is not seen by R50_0 core. When I used breakpoints, the variable gSharedMem is still 0. But the variable gSharedMem  in M4 core has the value.


    Am I missing any configuration, because of which the memory is not getting shared, but instead they are treated like two independent global variables?

    Thanks
    Amey

  • Hi Amey,

    Can you share the code you are using for the examples above.

    Regards,

    Nitika

  • Here is the code for M4 code, when data is received in M4 the user shared memory counter is incremented.

    In the R5 code, if old value of shared memory is not matching it just prints some string in console

    /*
     *  Copyright (C) 2021 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* This example demonstrates the UART RX and TX operation by echoing char
     * that it recieves in blocking, interrupt mode of operation.
     * When user types 'quit', the application ends.
     */
    
    #include <string.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    #define APP_UART_BUFSIZE              (200U)
    #define APP_UART_RECEIVE_BUFSIZE      (8U)
    
    volatile uint32_t gUserSharedMem __attribute__((aligned(128), section(".bss.user_shared_mem")));
    
    uint8_t gUartBuffer[APP_UART_BUFSIZE];
    uint8_t gUartReceiveBuffer[APP_UART_RECEIVE_BUFSIZE];
    volatile uint32_t gNumBytesRead = 0U, gNumBytesWritten = 0U;
    
    #define APP_UART_ASSERT_ON_FAILURE(transferOK, transaction) \
        do { \
            if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != transaction.status)) \
            { \
                DebugP_assert(FALSE); /* UART TX/RX failed!! */ \
            } \
        } while(0) \
    
    void uart_echo(void *args)
    {
        int32_t          transferOK;
        UART_Transaction trans;
        gUserSharedMem = 0;
    
        Drivers_open();
        Board_driversOpen();
    
        DebugP_log("[UART] Echo example started ...\r\n");
    
        UART_Transaction_init(&trans);
    
        /* Wait for all cores to start */
        IpcNotify_syncAll(SystemP_WAIT_FOREVER);
    
        /* Send entry string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf,"This is uart echo test blocking mode\r\nReceives 8 characters then echo's back. Please input..\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        while(1)
        {
            /* Read 8 chars */
            gNumBytesRead = 0U;
            trans.buf   = &gUartReceiveBuffer[0U];
            trans.count = APP_UART_RECEIVE_BUFSIZE;
            transferOK = UART_read(gUartHandle[CONFIG_UART_CONSOLE], &trans);
            APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
            /* Echo chars entered */
            gNumBytesWritten = 0U;
             trans.buf   = &gUartReceiveBuffer[0U];
            trans.count = APP_UART_RECEIVE_BUFSIZE;
            transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
            APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
            gUserSharedMem++;
        }
    
        /* Read 8 chars */
        gNumBytesRead = 0U;
        trans.buf   = &gUartReceiveBuffer[0U];
        trans.count = APP_UART_RECEIVE_BUFSIZE;
        transferOK = UART_read(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        /* Echo chars entered */
        gNumBytesWritten = 0U;
    //    &gUserSharedMem[0U] = &gUartReceiveBuffer[0U];
    //    memcpy((uint8_t *)gUserSharedMem,(uint8_t *) gUartReceiveBuffer, APP_UART_RECEIVE_BUFSIZE);
        trans.buf   = &gUartReceiveBuffer[0U];
        trans.count = APP_UART_RECEIVE_BUFSIZE;
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        /* Send exit string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf, "\r\nAll tests have passed!!\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        DebugP_log("All tests have passed!!\r\n");
    
        Board_driversClose();
        Drivers_close();
    
        return;
    }
    

    /*
     *  Copyright (C) 2021 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* This example demonstrates the UART RX and TX operation by echoing char
     * that it recieves in blocking, interrupt mode of operation.
     * When user types 'quit', the application ends.
     */
    
    #include <string.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    #define APP_UART_BUFSIZE              (200U)
    #define APP_UART_RECEIVE_BUFSIZE      (8U)
    
    volatile uint32_t gUserSharedMem __attribute__((aligned(128), section(".bss.user_shared_mem")));
    uint32_t oldVal = 0;
    
    uint8_t gUartBuffer[APP_UART_BUFSIZE];
    uint8_t gUartReceiveBuffer[APP_UART_RECEIVE_BUFSIZE];
    volatile uint32_t gNumBytesRead = 0U, gNumBytesWritten = 0U;
    
    #define APP_UART_ASSERT_ON_FAILURE(transferOK, transaction) \
        do { \
            if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != transaction.status)) \
            { \
                DebugP_assert(FALSE); /* UART TX/RX failed!! */ \
            } \
        } while(0) \
    
    void uart_echo(void *args)
    {
        int32_t          transferOK;
        UART_Transaction trans;
    
        Drivers_open();
        Board_driversOpen();
    
        DebugP_log("[UART] Echo example started ...\r\n");
    
        UART_Transaction_init(&trans);
    
        /* Wait for all cores to start */
        IpcNotify_syncAll(SystemP_WAIT_FOREVER);
    
        /* Send entry string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf,"This is uart echo test blocking mode\r\nReceives 8 characters then echo's back. Please input..\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        /* Read 8 chars */
        gNumBytesRead = 0U;
    //    trans.buf   = &gUartReceiveBuffer[0U];
    //    trans.count = APP_UART_RECEIVE_BUFSIZE;
    //    transferOK = UART_read(gUartHandle[CONFIG_UART_CONSOLE], &trans);
    //    APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        while(1)
        {
            if(oldVal != gUserSharedMem)
            {
                /* Echo chars entered */
                gNumBytesWritten = 0U;
                trans.buf   = (uint8_t *)"Data"; //&gUartReceiveBuffer[0U];
                trans.count = APP_UART_RECEIVE_BUFSIZE;
                transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
                APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
                oldVal = gUserSharedMem;
            }
    
        }
    
        /* Echo chars entered */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartReceiveBuffer[0U];
        trans.count = APP_UART_RECEIVE_BUFSIZE;
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        /* Send exit string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf, "\r\nAll tests have passed!!\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
    
        DebugP_log("All tests have passed!!\r\n");
    
        Board_driversClose();
        Drivers_close();
    
        return;
    }
    

    Thanks

    Amey

  • Hi Amey,

    Thank you for sharing the code, let me have a look at it and get back to you.

    Regards,

    Nitika

  • Hi Nitika

    Can you please share an update on this issue

    Thanks

    Amey

  • Hi Amey,

    Apologies for the delayed response.

    I did not go through the UART implementation in your code, but I used the empty system project to implement the shared memory spinlock and it is working for me.

    One thing that I suspect could be going wrong in your implementation is the shared memory MPU region could be marked as 'cached'. This would result in the core reading a stale value and updating the same which is why the update from both the cores is not reflecting.

    In your project, if not defined please add the below MPU region corresponding to the shared memory marked as 'non-cached'.

    Do let me know if this helps.

    Regards,

    Nitika

  • Attaching the working project below for reference

    ipc_shared_spinlock_r5f_m4f.zip

    Regards,

    Nitika

  • Hello Nitika

    I will try this in my project and get back

    Thanks

    Amey

  • Hello Nitika

    I am unable to import the project in the workspace. I created new workspace and tried to import but it is giving error.I also deleted the .setting and Debug folder from project but that didn't help

    Can you please help. 

    Thanks

    Amey

  • Hello Nitika

    Adding a MPU region in the solution helped and now I am able to share the memory between the cores.

    I have added the MPU region in the example.syscfg file of R50_0 project only. I believe that is enough or do I have to also add the same in M4 configuration?

    Why is the address for shared region starting at 0x701D0000? Is the top end of MSRAM?

    Thanks

    Amey

  • Hi Amey,

    Adding the memory region in the R5F0_0 project is enough when working with just one R5 and one M4 core.

    Why is the address for shared region starting at 0x701D0000? Is the top end of MSRAM?

    No, we have 2MB of On-chip RAM starting from 0x70000000, you can read about the memory layout of the MSRAM here - Memory_map_AM64x

    Regards,

    Nitika

  • Thank you Nitika.

    I have assigned the User Shared memory at 0x701C0000 (which is unallocated space as per above page) because I need larger memory for sharing

    Regards

    Amey

  • Hi Nitika,

    Can the SPINLOCK be used between R5F0_0 FreeRTOS and A53 Linux? If so, how to add the A53 Linux app as parts of the system project?

    Best Regards

    xixiguohx

  • Hi

    Since your query is regarding Linux, can you please create a separate thread for this question so we can direct it to the right expert.

    Regards,

    Nitika