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.

AM2634: Separating peripheral initialization and usage between cores

Part Number: AM2634
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hi,

We want certain peripherals to be accessed from multiple cores, even if the peripheral is initialized on one core via syscfg.

There will only ever be one initializer and one user for our purposes.

As an example. We want core 0_0 to initialize a gpio (configured in syscfg) and core 0_1 to turn the gpio on and off.

We'd imagine this is possible as multiple cores could have knowledge about the hardware register address, and change it.

Is this possible? If not, what are the constraints?

  • Realized I should be a little more specific, the GPIO example was a proof of concept we are having trouble with.

    We want two cores to be able to listen to the same CAN FD RX messages, but only one core is required to TX messages

    • I see there is "additional core configurations" in syscfg for the MCAN peripheral, is this the proper use case?

    And we want one core to be able to set up a ePWM peripheral and another to be able to update the CMPA values

    • A somewhat crazy strategy to this may be having a core configure the ePWM also set up the DMA to route shared memory to the EPWM CMPA, then the other core writes to shared memory -> DMA picks up and writes to EPWM CMPA register. Surely there is there a better way to do this?

    It would still be great to get an explanation of the gpio example above (for one core to configure a gpio and another core to set it) as we may use this, but the other two specific use case examples are also important for us to find answer to.

    Thanks!

  • Apologies for the delay here,

    Have you looked at the IPC or SPINLOCK examples/features at all yet? This would probably be the best way to implement the EPWM application by transferring the data via IPC.

    For GPIO, I know that it's possible to share data across cores, but I am checking with some other team members about controlling a single peripheral from multiples cores. I recall there being some restrictions with the port access (i.e. one core can access one port at a time), but don't remember the details.
    As for CAN, I am checking with our CAN experts. Am I correct in understanding you would like two cores to receive simultaneously?

    Regards,

    Susan

  • Hi Susan,

    For EPWM CMPA register updating, we could use IPC to pass cmpa values from one core to the next, but we are trying to minimize added compute for any mailbox. It would be preferred to allow one core to write directly to the hw register if possible.

    For your GPIO response, it would be very valuable to understand restrictions between sharing peripherals between cores. If you could provide those details that would be fantastic.

    And for CAN, yes we would like two cores to receive code simultaneously.

    Thank you and looking forward to your response!

  • Hello,

    I did some research and spoke with some of our other experts and yes, it is possible to configure peripherals with one CPU core, and then have other cores update, run, and/or control different peripherals. Unfortunately most of our examples are designed with the assumption that you will only be using one core. When using multiple cores, using SPINLOCK is recommended to help mitigate issues when multiple cores are accessing shared memory. 

    So I will do my best here to answer your questions as I understand them:
    For GPIO, it is possible to use one core to configure any GPIO and then use another core to control it. There are two important things to keep in mind with this:

    • The R5F core that is controlling the GPIO pin must be configured/set (this can be changed during run time)
    • Multiple cores cannot access the same GPIO at the same time.

    For EPWM, I think I misunderstood your intentions with usage. As far as I am aware, as with GPIO, it is completely possible to set up and start and EPWM from one CPU core, and then offload control of the peripheral and update the CMPA registers from a different CPU core. 

    For CAN, the additional core configurations are for expanded MCAN functionality, not for CPU cores.

    In terms of receiving CAN data at the same time, the way to view it is that when an CAN data is received, the data is stored in the MSG RAM which can then be accessed by individual CPU cores. It is not possible for multiple cores to access the MSG RAM at the same time. However, it is possible to have the DMA move the data from the MSG RAM to a shared memory location that can then be accessed by multiple cores.

    In general, there are limitations on what you can access within a peripheral by different CPU cores, but the exact limitations are dependent on what you are trying to achieve. To that note, a block diagram of your goals with the whole system across all cores would help understand the distribution across cores. If you could provide a system block diagram, I better explain what you can do to meet those goals.

    I hope this helps,

    Susan

  • Hi Susan, thank you for your response.

    Could you provide instructions using the SDK on how to change which core is controlling the GPIO pin during runtime.

    Also please provide similar SDK instructions for allowing a separate core to control the EPWM and CMPA registers.

    For CAN, is the intent for one core to set up CAN TX/RX and a DMA channel, in which the DMA is triggered to move data from MSG RAM to shared memory from a CAN RX interrupt? Could you please suggest the best flow here.

    Finally for providing details of our project, we are happy to share offline. 

    Thank you!

  • Hello,

    I am writing and pulling code examples for you at the moment, I will update this post as soon as I have them.
    Regards,

    Susan

  • Apologies for the delay, 
    It took longer than planned to run through some examples and detail instructions.


    For GPIO:

    The GPIO_SEL bits of the MSS_IOMUX registers controls which CPU is connected to which GPIO:

    The assignment (with corresponding APIs) is as follows:

    • 0h: GPIO0 (connected to R5FSS0-0)         PIN_GPIO_R5SS0_0
    • 1h: GPIO1 (connected to R5FSS0-1)         PIN_GPIO_R5SS0_1
    • 2h: GPIO2 (connected to R5FSS1-0)         PIN_GPIO_R5SS1_0
    • 3h: GPIO3 (connected to R5FSS1-1)         PIN_GPIO_R5SS1_1

    To update the core ownership, you would need to redefine the PINMUX configuration for the GPIO pins.

    SysConfig automatically does this for you (see the ti_pinmux_config.c file)

    Taking the gpio_led_blink_am263x-cc example, the GPIO is configured as such:

    You would have to write a new configuration for GPIO1 and reconfigure the Pinmux for it:

    It is best to reinitialize your GPIOs after changing the configuration by calling GPIO_init();

    If you will be using GPIO Interrupts, I recommend de-initializing GPIO, reconfiguring, and then re-initializing GPIO:


    For EPWM, every core can connect to every EPWM as an initiator. For every instance of EPWMx, there is a Group Y (for Y = [0:4]). To prevent conflicts, we generally assign a group to each initiator, and then assign that group to the EPWM instance. Each EPWMx_GROUPy has its own set of registers with its own base address.

    Using the below image as a reference, you can access EPWM0 through Group 0 registers (orange) or Group 1 registers (red) from Core 1 (more information is detailed in the System Interconnect chapter of the TRM):

    When you configure an EPWM instance via SysConfig, it assigns an EPWM instance to a Group automatically. Using epwm_up_aq_am263x-cc as an example, the EPWM0, EPWM1, and EPWM2 instances configured by Core0 are assigned to Group 0 (G0, black in above image):

    To update CMPA, there are dedicated EPWM APIs. The one used in this code example is EPWM_setCounterCompareValue() :

    Regardless of which core you use to update the CMPA value, you need to make sure you use the base address that is assigned to the EPWM instance (using the code example here, for EPWM0 you would use CONFIG_EPWM0_BASE_ADDR). It should be possible to call this directly from another core.


    For CAN, the flow you should follow based on recommendation from our CAN experts is:

    • Configure CAN RX and TX on Core 0
    • When a CAN message is received, it is stored in the MSG RAM
      • Upon message receive, trigger the DMA to copy/move MSG RAM contents to shared memory
    • Core 0 and Core 1 can both access the shared memory to read the CAN message.

    I added links to the PINMUX and EPWM APIs in our SDK within the text as well.

    Regards,

    Susan