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.

PROCESSOR-SDK-AM62A: MCU accessing MAIN SPI

Part Number: PROCESSOR-SDK-AM62A
Other Parts Discussed in Thread: SYSCONFIG

Hello TI,

I'm running a program on the MCU R5 core that gets booted by the kernel. The program's goal is to access the Main domain's SPI0 from the MCU domain. But when calling the MCSPI_transfer api, it doesn't return and hangs. Using the XDS110 debugger, I found it's waiting for the Tx Empty bit to be set.

I followed the steps from the link below to make sure the syscfg file is setup correctly. The dts is also updated to ensure there's no instances of main_spi0 defined and no spi0 pins are configured. The dts does however use spi1 so I left that defined. Lastly I configured the RAT so that it covers all of the MCSPI physical addresses. 

https://dev.ti.com/tirex/explore/content/mcu_plus_sdk_am62ax_09_00_00_19/docs/api_guide_am62ax/MAIN_DOMAIN_PERIPHERAL_FROM_MCU.html#autotoc_md155

Is there anything else I'm missing with configuration? I've ran similar SPI code using the mcspi loopback test example and confirmed the MCU SPI is working.

Thanks,

Joseph

/**
 * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
 * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
 * @cliArgs --device "AM62Ax" --package "AMB" --part "Default" --context "mcu-r5fss0-0" --product "MCU_PLUS_SDK_AM62Ax@09.00.00"
 * @versions {"tool":"1.18.0+3266"}
 */

/**
 * Import the modules used in this configuration.
 */
const ipc             = scripting.addModule("/drivers/ipc/ipc");
const mcspi           = scripting.addModule("/drivers/mcspi/mcspi", {}, false);
const mcspi1          = mcspi.addInstance();
const addr_translate  = scripting.addModule("/kernel/dpl/addr_translate", {}, false);
const addr_translate1 = addr_translate.addInstance();
const debug_log       = scripting.addModule("/kernel/dpl/debug_log");
const mpu_armv7       = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false);
const mpu_armv71      = mpu_armv7.addInstance();
const mpu_armv72      = mpu_armv7.addInstance();
const mpu_armv73      = mpu_armv7.addInstance();
const mpu_armv74      = mpu_armv7.addInstance();
const mpu_armv75      = mpu_armv7.addInstance();
const mpu_armv76      = mpu_armv7.addInstance();

/**
 * Write custom configuration values to the imported modules.
 */
ipc.r5fss0_0 = "NONE";
ipc.c75ss0_0 = "NONE";

mcspi1.$name                       = "CONFIG_MCSPI0";
mcspi1.useMcuDomainPeripherals     = false;
mcspi1.intrEnable                  = "POLLED";
mcspi1.mode                        = "MULTI_MASTER";
mcspi1.SPI.$assign                 = "SPI0";
mcspi1.mcspiChannel.create(3);
mcspi1.mcspiChannel[0].$name       = "CONFIG_MCSPI_CH0";
mcspi1.mcspiChannel[0].CSn.$assign = "SPI0_CS0";
mcspi1.mcspiChannel[1].$name       = "CONFIG_MCSPI_CH1";
mcspi1.mcspiChannel[1].CSn.$assign = "SPI0_CS1";
mcspi1.mcspiChannel[2].$name       = "CONFIG_MCSPI_CH2";
mcspi1.mcspiChannel[2].CSn.$assign = "UART0_RTSn";

addr_translate1.$name      = "CONFIG_ADDR_TRANSLATE_REGION0";
addr_translate1.localAddr  = 0xA0000000;
addr_translate1.systemAddr = 0x20000000;

debug_log.enableUartLog = true;
debug_log.enableMemLog  = true;
debug_log.uartLog.$name = "CONFIG_UART0";

mpu_armv71.$name             = "CONFIG_MPU_REGION0";
mpu_armv71.size              = 31;
mpu_armv71.attributes        = "Device";
mpu_armv71.accessPermissions = "Supervisor RD+WR, User RD";
mpu_armv71.allowExecute      = false;

mpu_armv72.$name             = "CONFIG_MPU_REGION1";
mpu_armv72.size              = 15;
mpu_armv72.accessPermissions = "Supervisor RD+WR, User RD";

mpu_armv73.$name             = "CONFIG_MPU_REGION2";
mpu_armv73.baseAddr          = 0x41010000;
mpu_armv73.size              = 15;
mpu_armv73.accessPermissions = "Supervisor RD+WR, User RD";

mpu_armv74.$name             = "CONFIG_MPU_REGION3";
mpu_armv74.accessPermissions = "Supervisor RD+WR, User RD";
mpu_armv74.baseAddr          = 0x79100000;
mpu_armv74.size              = 19;

mpu_armv75.$name             = "CONFIG_MPU_REGION4";
mpu_armv75.baseAddr          = 0x60000000;
mpu_armv75.size              = 28;
mpu_armv75.accessPermissions = "Supervisor RD, User RD";

mpu_armv76.$name    = "CONFIG_MPU_REGION5";
mpu_armv76.baseAddr = 0x80000000;
mpu_armv76.size     = 31;

/**
 * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
 * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
 * re-solve from scratch.
 */
mcspi1.SPI.CLK.$suggestSolution                 = "SPI0_CLK";
mcspi1.SPI.D0.$suggestSolution                  = "SPI0_D0";
mcspi1.SPI.D1.$suggestSolution                  = "SPI0_D1";
debug_log.uartLog.MCU_UART.$suggestSolution     = "MCU_USART0";
debug_log.uartLog.MCU_UART.RXD.$suggestSolution = "MCU_UART0_RXD";
debug_log.uartLog.MCU_UART.TXD.$suggestSolution = "MCU_UART0_TXD";

  • Hi Joseph,

    Thanks for your question.

    By the description I see a mix of DTS/SysConfig settings.

    Can you help me understand what you are using MCU PLUS SDK or Processor SDK ?

    Looking forward to your response.

    Thanks,

    Vaibhav

  • Hi Vaibhav,

    For the linux kernel I'm using ti-processor-sdk-linux-am62axx-evm-08.06.00.45. For the mcu core, I started with a hello world freertos sample project from mcu plus sdk 09.00.00.19.

    I use the binary generated from CCS and boot it through remoteproc.

    Thanks,

    Joseph

  • Hi Joseph,

    Before you proceed further I would request you to go through the following documentation: https://software-dl.ti.com/mcu-plus-sdk/esd/AM62AX/09_01_00_39/exports/docs/api_guide_am62ax/MAIN_DOMAIN_PERIPHERAL_FROM_MCU.html

    Please go through the same as it covers your usecase of accessing main domain peripheral from MCU domain.

    I hope this helps.

    Regards,

    Vaibhav

  • Hi Vaibhav,

    Thanks for your response. That's actually the same guide that I followed in my original post.

    I believe my address translation is correct because in the debugger, I can see the base addresses that are read from the mcspi registers all show the address of the local address that I set in RAT region. Are there specific changes that are needed in the dts other than removing the main_spi0 instance?

    Thanks,

    Joseph

  • Hi Vaibhav,

    I was able to get the Main SPI0 transfers from MCU working by removing the RAT region entry. This works when configuring for both polling and interrupt modes in syscfg. Is this expected?

    When exactly are we supposed to be using the RAT region? I thought this was required for whenever the MCU accesses a peripheral from the Main domain. It also says that in the link you and I provided.

    Thanks,

    Joseph

  • Hi Joseph,

    The newly assigned expert will be helping you with RAT Configuration questions.

    But before all of this, I want you to dive and look at this precise FAQ: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1192281/faq-am62x-am64x-updating-the-region-based-address-translation-rat-settings?tisearch=e2e-sitesearch&keymatch=rat%20configuration#

    Regards,

    Vaibhav

  • Thank you Vaibhav. After speaking with the TI team I was informed that some default configurations of the MPU in syscfg could be automatically translating the system address of the peripherals I'm accessing.

    Can you please point me to documentation on MPU regions and how/when they should be configured? I don't see this discussed in the link shared above.

    Thanks,

    Joseph

  • Hello Joseph,

    Can you show us what you changed when you "removed the RAT region entry"?

    FYI, any time your R5F core accesses a memory region outside of the R5F subsystem, that access physically goes through the RAT circuitry. But typically for R5F cores, I do not see people configuring the RAT to do any address translation, so the memory access basically just "passes through".

    The information on this AM62Ax academy page is the information that I am aware of:
    https://dev.ti.com/tirex/explore/node?node=A__AXBsTEetU2hiTMZSzq4row__AM62A-ACADEMY__WeZ9SsL__LATEST

    When I check sysconfig, the RAT section is the only place I see to configure your RAT settings:

    I have NOT played around with this feature much within SysConfig (usually I'm manually editing the text of the example.syscfg file). So I cannot comment on whether SysConfig sneakily does stuff depending on whether you used the RAT to shift an address that is used by a peripheral or a shared IPC memory region.

    If I were you, I would NOT assume that the tool is doing magic for you. If you are using the RAT to shift addresses, you should manually check that your code, linker.cmd file, etc are using the correct address as documented in that academy page.

    Regards,

    Nick

  • Hi Nick,

    Thanks for your responses! Here's the .syscfg I'm currently using from the default ipc_rpmsg_echo_linux project. In this syscfg there's 3 RAT regions configured by default but none of them are mapping to the system address 0x20100000 (main MCSPI0) that I thought I needed to put in. After checking the linker file, it looks like these regions are there for the IPC shared memory and resource tables, is that correct?

    Also maybe the default MPU settings here are doing this configuration? It's a bit confusing though because I don't see the MCSPI system address or a range of it's address in the text syscfg either.

    /**
     * These arguments were used when this file was generated. They will be automatically applied on subsequent loads
     * via the GUI or CLI. Run CLI with '--help' for additional information on how to override these arguments.
     * @cliArgs --device "AM62Ax" --package "AMB" --part "Default" --context "mcu-r5fss0-0" --product "MCU_PLUS_SDK_AM62Ax@09.00.00"
     * @versions {"tool":"1.18.0+3266"}
     */
    
    /**
     * Import the modules used in this configuration.
     */
    const ipc             = scripting.addModule("/drivers/ipc/ipc");
    const mcspi           = scripting.addModule("/drivers/mcspi/mcspi", {}, false);
    const mcspi1          = mcspi.addInstance();
    const addr_translate  = scripting.addModule("/kernel/dpl/addr_translate", {}, false);
    const addr_translate1 = addr_translate.addInstance();
    const addr_translate2 = addr_translate.addInstance();
    const addr_translate3 = addr_translate.addInstance();
    const debug_log       = scripting.addModule("/kernel/dpl/debug_log");
    const mpu_armv7       = scripting.addModule("/kernel/dpl/mpu_armv7", {}, false);
    const mpu_armv71      = mpu_armv7.addInstance();
    const mpu_armv72      = mpu_armv7.addInstance();
    const mpu_armv73      = mpu_armv7.addInstance();
    const mpu_armv74      = mpu_armv7.addInstance();
    const mpu_armv75      = mpu_armv7.addInstance();
    const mpu_armv76      = mpu_armv7.addInstance();
    const mpu_armv77      = mpu_armv7.addInstance();
    const mpu_armv78      = mpu_armv7.addInstance();
    
    /**
     * Write custom configuration values to the imported modules.
     */
    ipc.vringAllocationPDK = false;
    ipc.c75ss0_0           = "NONE";
    ipc.r5fss0_0           = "NONE";
    ipc.a53ss0_0           = "notify_rpmsg";
    
    mcspi1.$name                   = "CONFIG_MCSPI0";
    mcspi1.intrEnable              = "POLLED";
    mcspi1.useMcuDomainPeripherals = false;
    mcspi1.mcspiChannel[0].$name   = "CONFIG_MCSPI_CH0";
    
    addr_translate1.$name      = "CONFIG_ADDR_TRANSLATE_REGION0";
    addr_translate1.localAddr  = 0x9B000000;
    addr_translate1.systemAddr = 0x9B000000;
    addr_translate1.size       = 24;
    
    addr_translate2.$name      = "CONFIG_ADDR_TRANSLATE_REGION2";
    addr_translate2.localAddr  = 0x9C000000;
    addr_translate2.size       = 24;
    addr_translate2.systemAddr = 0x9C000000;
    
    addr_translate3.$name      = "CONFIG_ADDR_TRANSLATE_REGION1";
    addr_translate3.localAddr  = 0xA0000000;
    addr_translate3.systemAddr = 0xA0000000;
    addr_translate3.size       = 24;
    
    debug_log.enableCssLog       = false;
    debug_log.enableUartLog      = true;
    debug_log.uartLog.$name      = "CONFIG_UART0";
    debug_log.uartLog.intrEnable = "DISABLE";
    
    mpu_armv71.$name             = "CONFIG_MPU_REGION0";
    mpu_armv71.size              = 31;
    mpu_armv71.attributes        = "Device";
    mpu_armv71.accessPermissions = "Supervisor RD+WR, User RD";
    mpu_armv71.allowExecute      = false;
    
    mpu_armv72.$name             = "CONFIG_MPU_REGION1";
    mpu_armv72.size              = 15;
    mpu_armv72.accessPermissions = "Supervisor RD+WR, User RD";
    
    mpu_armv73.$name             = "CONFIG_MPU_REGION2";
    mpu_armv73.baseAddr          = 0x41010000;
    mpu_armv73.size              = 15;
    mpu_armv73.accessPermissions = "Supervisor RD+WR, User RD";
    
    mpu_armv74.$name             = "CONFIG_MPU_REGION3";
    mpu_armv74.accessPermissions = "Supervisor RD+WR, User RD";
    mpu_armv74.baseAddr          = 0x79100000;
    mpu_armv74.size              = 19;
    
    mpu_armv75.$name             = "CONFIG_MPU_REGION4";
    mpu_armv75.baseAddr          = 0x60000000;
    mpu_armv75.size              = 28;
    mpu_armv75.accessPermissions = "Supervisor RD, User RD";
    
    mpu_armv76.$name      = "CONFIG_MPU_REGION5";
    mpu_armv76.attributes = "NonCached";
    mpu_armv76.size       = 24;
    mpu_armv76.baseAddr   = 0x9B000000;
    
    mpu_armv77.$name        = "CONFIG_MPU_REGION6";
    mpu_armv77.baseAddr     = 0xA0000000;
    mpu_armv77.allowExecute = false;
    mpu_armv77.attributes   = "NonCached";
    mpu_armv77.size         = 23;
    
    mpu_armv78.$name      = "CONFIG_MPU_REGION7";
    mpu_armv78.baseAddr   = 0x9C000000;
    mpu_armv78.size       = 25;
    mpu_armv78.attributes = "NonCached";
    
    /**
     * Pinmux solution for unlocked pins/peripherals. This ensures that minor changes to the automatic solver in a future
     * version of the tool will not impact the pinmux you originally saw.  These lines can be completely deleted in order to
     * re-solve from scratch.
     */
    mcspi1.mcspiChannel[0].CSn.$suggestSolution     = "SPI0_CS0";
    mcspi1.SPI.$suggestSolution                     = "SPI0";
    mcspi1.SPI.CLK.$suggestSolution                 = "SPI0_CLK";
    mcspi1.SPI.D0.$suggestSolution                  = "SPI0_D0";
    mcspi1.SPI.D1.$suggestSolution                  = "SPI0_D1";
    debug_log.uartLog.MCU_UART.$suggestSolution     = "MCU_USART0";
    debug_log.uartLog.MCU_UART.RXD.$suggestSolution = "MCU_UART0_RXD";
    debug_log.uartLog.MCU_UART.TXD.$suggestSolution = "MCU_UART0_TXD";
    

    What I meant earlier when I said I removed the RAT region entry was that there was 0 of 16 regions added in this section. This was also when I was working in the hello world project.

    Thanks,

    Joseph

  • Hello Joseph,

    Ahh, ok. I see what you are talking about now.

    Is address translation the issue?

    Those RAT address translations aren't actually doing anything. Notice how the localAddr and the systemAddr are the exact same value? So there isn't any remapping going on. And since all accesses outside of the R5F go through the RAT anyway, not configuring the RAT gives the same behavior as configuring the RAT to have localAddr = systemAddr.

    I do not think that address translation is your issue.

    Some more information on avoiding a resource conflict

    If a devicetree node is defined in the devicetree file, it is automatically enabled and Linux might try to grab it. Instead of messing around with the lower-level .dtsi files that define the peripherals that exist on the processor, I typically suggest adding something like this in your top-level board .dts file:

    &main_spi0 {
        status = "disabled";
    };

    For more information about allocating peripherals in your multicore system, refer to 
    AM62ax academy, multicore module, page "How to allocate peripherals"
    https://dev.ti.com/tirex/explore/node?node=A__ASuOzonPJpyBzKFrqEN1fg__AM62A-ACADEMY__WeZ9SsL__LATEST

    It sounds like things are working for you now, but feel free to reply here if we need to continue the conversation, or create a new thread if you have a different question!

    Regards,

    Nick

  • Hi Nick,

    And since all accesses outside of the R5F go through the RAT anyway, not configuring the RAT gives the same behavior as configuring the RAT to have localAddr = systemAddr.

    Thanks, I do see how the addresses are the same. Just to close the loop on this, are you saying for my case in accessing a main peripheral from the mcu, I don't need to configure the RAT? 

    Some more information on avoiding a resource conflict

    These are helpful thank you. Currently I haven't touched the .dtsi files and I have not pulled in the &main_spi0 node into the top level board .dts file. From my understanding this is also disabled and I can see it's disabled in the .dtsi file.

    Joseph

  • RAT with MAIN/MCU domain

    The RAT does not have anything to do with whether the peripheral is in the MAIN domain or the MCU domain. No RAT configuration is needed here.

    In the academy's RAT page, when I said "For M4F in particular on AM24x/62x/64x, check the RAT settings when the M4F project accesses ... Main domain resources", that was because "M4F has local resources at addresses that are less than 0x6000_0000", so it is highly likely that an M4F core would need to remap resources in the main domain that were in that address range.

    You don't need to worry about that, since AM62A doesn't even have an M4F core.

    Double-checking the Linux side resource allocation 

    Sure enough, it looks like main_spi0 is disabled by default in k3-am62a-main.dtsi for both SDK 8.6 and SDK 9.1. So no changes needed there.

    Regards,

    Nick

  • Thanks for clarifying!

    Joseph