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.

AM572x McASP access from DSP

Other Parts Discussed in Thread: AM5728

Hello,


I am working on the evm am5728 board. I would like to configure and service the MCASP2 bus interrupt on the DSP processor. I started with an IPC example and tried to integrated the example code for MCASP loopabck from the PDK packages. I made a few changes:

1) I made a new function McASP2_Enable() and changed all reference to the correct MCASP2 bus

2) I changed the EDMA from 0 to 1;

3) I changed the parameter when calling mcaspBindDev() to configure MCASP2 instead.

Now the code is blocked in the mcaspCreateChan() function. I am guessing the problem is the results of the conflict when setting up the MCASP channel.

Here is my configuration:


Linux:

- Linux kernel: am57xx-evm 4.4.19-rt25-gf572d285f0 #50 SMP PREEMPT RT Mon Nov 28 11:52:02 EST 2016 armv7l GNU/Linux

- mcasp2 configured and enabled in the dts.

--------------------

&mcasp2 {

    #sound-dai-cells = <0>;
    assigned-clocks = <&mcasp2_ahclkx_mux>;
    assigned-clock-parents = <&sys_clkin2>;
    pinctrl-names = "default";
    pinctrl-0 = <&mcasp2_pins>;
    status = "okay";
    //status = "disabled";

    op-mode = <0>;    /* MCASP_IIS_MODE */
    tdm-slots = <2>;
    /* 4 serializers */
    serial-dir = <    /* 0: INACTIVE, 1: TX, 2: RX */
        2 2 2 2 1 1 1 1
    >;
    tx-num-evt = <8>;
    rx-num-evt = <8>;
};

---------------------------------

DSP: the IPC example code ex02_messageq from the packages below:

ipc_3_43_02_04/examples/DRA7XX_linux_elf/ex02_messageq

pdk_am57xx_1_0_4/packages/ti/drv/mcasp/example/evmAM572x/DeviceLoopback/c66

My MainDsp1.c from IPC:

------------------------------------------------------------

//from MainDsp1.c

Void smain(UArg arg0, UArg arg1)
{
    Int                 status = 0;
    Error_Block         eb;
    Bool                running = TRUE;

    Log_print0(Diags_ENTRY | Diags_INFO, "--> smain:");

    Error_init(&eb);

    /* initialize modules */
    Server_init();

    /* turn on Diags_INFO trace */
    Diags_setMask("Server+F");


    Log_print0(Diags_ENTRY, "\r\nAudio Sample Main\n");


    Log_print0(Diags_ENTRY, "<-- main: wait forever");


    /* code inserted to enable MCASP*/
    /* enable the pinmux & PSC-enable for the mcasp device    */
    configureAudio();

    McaspDevice_init();

    Audio_echo_Task();
    /* code inserted to enable MCASP end*/

    /* loop forever */
    while (running) {

        /* BEGIN server phase */

        /* server setup phase */
        status = Server_create();

        if (status < 0) {
            goto leave;
        }

        /* server execute phase */
        status = Server_exec();

        if (status < 0) {
            goto leave;
        }

        /* server shutdown phase */
        status = Server_delete();

        if (status < 0) {
            goto leave;
        }

        /* END server phase */

    } /* while (running) */

    /* finalize modules */
    Server_exit();

leave:
    Log_print1(Diags_EXIT, "<-- smain: %d", (IArg)status);
    return;
}

Any help would be appreciated. Please let me know if you need anything else. Thank you!!

  • Hi,

    I've moved your thread to the device forum.

    Todd
  • Yun,

    I have not tried this setup, but from experience from previous device, since the DSP-side application will be using the audio driver (I2C, McAsp, AIC) the kernel must disable the Advanced Linux Sound Architecture (ALSA) driver to avoid conflicts. You may be able to disable the ALSA driver from menuconfig.

    On the DSP side, when the code calls into configureAudio, the clocks and the pin mux configuration may conflict with the MCASP setup from the Linux side. Ideally after the clocks and pinmux is configured by the ARM, you shouldn`t need to redo this from the DSP side.

    Please also check that there is no overlap of OCMC and DDR memory regions used by DSP and the ARM but since you are using the IPC examples as the starting point this may have already been taken care off.

    Regards,
    Rahul
  • Hello,


    I have not changed the memory map from the IPC example. I have disabled alsa and MCASP2 in the kernel and dts, such not to have a conflict on the DSP side. On the DSP side, I was able to run the code to setup the clocks and pin mux without problem.


    However, I still am having problems with EDMA.

    • The function to configure XBAR CSL_xbarDmaConfigure() makes Linux kernel freeze half of the time.
    • Even when it passes, later in the function where DMA is being set up, sometimes the DSP freezes, and sometimes both the DSP and the ARM freeze. I was able to see the clock and the frame sync signal after it freezes though.
    • I also tried the code with "isDmaDriven" being false, so it bypasses the DMA setup. Half of the time Linux freezes as above; when it doesn't, everything looks OK except there is no frame sync signal.


    I have tried many other things but there is nothing that would work consistently. It doesn't feel like the right way to make McASP work.

    Any help would be appreciated. Thank you!

  • Any progress on this?

    Thanks!
  • Yun,

    Do you have any kernel crash backtrace log?

    Both EDMA and MCASP register space are not defined in default DSP resource table (ipc_3_43_02_0x/packages/ti/ipc/remoteproc/rsc_table_vayu_dsp.h), are you using a customized resource table in your application? If not, please refer to the wiki processors.wiki.ti.com/.../IPC_Resource_customTable for IPC Resource customTable to add all address space entries that are not in the default resource table but required in your application.

    Regards,
    Garrett
  • Thank you for your reply! It definitely helps moving forward.

    Kernel doesn't always crash: sometimes it just hangs there, completely frozen. When it doesn't freeze, I have this trace:

    [65876.540728] omap-iommu 40d02000.mmu: iommu fault: da 0x45c00000 flags 0x0
    [65876.547555] remoteproc2: crash detected in 40800000.dsp: type mmufault
    [65876.554207] omap-iommu 40d02000.mmu: 40d02000.mmu: errs:0x00000002 da:0x45c00000 pgd:0xecd91170 *pgd:px00000000
    [65876.564494] remoteproc2: handling crash #1 in 40800000.dsp
    [65876.570094] remoteproc2: recovering 40800000.dsp
    [65876.588668] omap_hwmod: mmu1_dsp1: _wait_target_disable failed
    [65876.601711] omap_hwmod: mmu0_dsp1: _wait_target_disable failed
    [65876.607612] remoteproc2: stopped remote processor 40800000.dsp

    My question is this:
    I am looking into how to work with the resource table. I have read the link you posted above but it doesn't tell me what is the register space for MCASP and EDMA. I look into IPC and PDK packages but can't find the information.

    Can you give me some pointers on how to add EDMA and MCASP resources? I need the addresses of the register space.

    Thank you!
  • Yun,

    The mmufault in the log confirms there is illegal memory access due to missing configuration in resource table.

    See AM572x TRM Table 2-1 (AM572x Sitara Processor Technical Reference Manual (Rev. H), www.ti.com/.../technicaldocuments) for the EDMA and MCASP register addresses:
    MCASP: 0x4580_0000 to 0x463F_FFFF
    EDMA: 0x4330_0000 to 0x435F_FFFF

    Regards,
    Garrett
  • Hello Garrett,

    I have created a resource table with 2 additional devmem, and the system (at least the serial port) still hangs when trying configure the transmit channel. Here is my resource table. I have added 2 entries, 1 for MCASP and 1 for EDMA.

    Please let me know if you see I'm missing anything. Thanks!

    -------------------------
    /*
    * ======== rsc_table.h ========
    *
    * Define the resource table entries for all DSP cores. This will be
    * incorporated into corresponding base images, and used by the remoteproc
    * on the host-side to allocated/reserve resources.
    */

    #ifndef _RSC_TABLE_DSP_H_
    #define _RSC_TABLE_DSP_H_

    #include <ti/ipc/remoteproc/rsc_types.h>

    /* DSP Memory Map */
    #define L4_DRA7XX_BASE 0x4A000000

    #define L4_PERIPHERAL_L4CFG (L4_DRA7XX_BASE)
    #define DSP_PERIPHERAL_L4CFG 0x4A000000

    #define L4_PERIPHERAL_L4PER1 0x48000000
    #define DSP_PERIPHERAL_L4PER1 0x48000000

    #define L4_PERIPHERAL_L4PER2 0x48400000
    #define DSP_PERIPHERAL_L4PER2 0x48400000

    #define L4_PERIPHERAL_L4PER3 0x48800000
    #define DSP_PERIPHERAL_L4PER3 0x48800000

    #define L4_PERIPHERAL_L4EMU 0x54000000
    #define DSP_PERIPHERAL_L4EMU 0x54000000

    #define L3_PERIPHERAL_DMM 0x4E000000
    #define DSP_PERIPHERAL_DMM 0x4E000000

    #define L3_PERIPHERAL_ISS 0x52000000
    #define DSP_PERIPHERAL_ISS 0x52000000

    #define L3_TILER_MODE_0_1 0x60000000
    #define DSP_TILER_MODE_0_1 0x60000000

    #define L3_TILER_MODE_2 0x70000000
    #define DSP_TILER_MODE_2 0x70000000

    #define L3_TILER_MODE_3 0x78000000
    #define DSP_TILER_MODE_3 0x78000000

    #define DSP_MEM_TEXT 0x95000000
    /* Co-locate alongside TILER region for easier flushing */
    #define DSP_MEM_IOBUFS 0x80000000
    #define DSP_MEM_DATA 0x95100000
    #define DSP_MEM_HEAP 0x95200000

    //0x85900000
    #define DSP_SR0_VIRT 0xBFC00000
    #define DSP_SR0 0xBFC00000

    #define L3_PERIPHERAL_MCASP 0x45800000
    #define DSP_PERIPHERAL_MCASP 0x45800000

    #define L3_PERIPHERAL_EDMA 0x43300000
    #define DSP_PERIPHERAL_EDMA 0x43300000

    #define DSP_MEM_IPC_DATA 0x9F000000
    #define DSP_MEM_IPC_VRING 0xA0000000
    #define DSP_MEM_RPMSG_VRING0 0xA0000000
    #define DSP_MEM_RPMSG_VRING1 0xA0004000
    #define DSP_MEM_VRING_BUFS0 0xA0040000
    #define DSP_MEM_VRING_BUFS1 0xA0080000

    #define DSP_MEM_IPC_VRING_SIZE SZ_1M
    #define DSP_MEM_IPC_DATA_SIZE SZ_1M
    #define DSP_MEM_TEXT_SIZE SZ_1M
    #define DSP_MEM_DATA_SIZE SZ_1M
    #define DSP_MEM_HEAP_SIZE (SZ_1M * 3)
    #define DSP_MEM_IOBUFS_SIZE (SZ_1M * 89)
    #define DSP_SR0_SIZE (SZ_1M * 1)

    /*
    * Assign fixed RAM addresses to facilitate a fixed MMU table.
    */
    /* This address is derived from current IPU & ION carveouts */
    #define PHYS_MEM_IPC_VRING 0x99000000

    /* Need to be identical to that of IPU */
    #define PHYS_MEM_IOBUFS 0xBA300000

    /*
    * Sizes of the virtqueues (expressed in number of buffers supported,
    * and must be power of 2)
    */
    #define DSP_RPMSG_VQ0_SIZE 256
    #define DSP_RPMSG_VQ1_SIZE 256

    /* flip up bits whose indices represent features we support */
    #define RPMSG_DSP_C0_FEATURES 1

    struct my_resource_table {
    struct resource_table base;

    UInt32 offset[21]; /* Should match 'num' in actual definition */

    /* rpmsg vdev entry */
    struct fw_rsc_vdev rpmsg_vdev;
    struct fw_rsc_vdev_vring rpmsg_vring0;
    struct fw_rsc_vdev_vring rpmsg_vring1;

    /* text carveout entry */
    struct fw_rsc_carveout text_cout;

    /* data carveout entry */
    struct fw_rsc_carveout data_cout;

    /* heap carveout entry */
    struct fw_rsc_carveout heap_cout;

    /* ipcdata carveout entry */
    struct fw_rsc_carveout ipcdata_cout;

    /* trace entry */
    struct fw_rsc_trace trace;

    /* devmem entry */
    struct fw_rsc_devmem devmem0;

    /* devmem entry */
    struct fw_rsc_devmem devmem1;

    /* devmem entry */
    struct fw_rsc_devmem devmem2;

    /* devmem entry */
    struct fw_rsc_devmem devmem3;

    /* devmem entry */
    struct fw_rsc_devmem devmem4;

    /* devmem entry */
    struct fw_rsc_devmem devmem5;

    /* devmem entry */
    struct fw_rsc_devmem devmem6;

    /* devmem entry */
    struct fw_rsc_devmem devmem7;

    /* devmem entry */
    struct fw_rsc_devmem devmem8;

    /* devmem entry */
    struct fw_rsc_devmem devmem9;

    /* devmem entry */
    struct fw_rsc_devmem devmem10;

    /* devmem entry */
    struct fw_rsc_devmem devmem11;

    /* devmem entry */
    struct fw_rsc_devmem devmem12;


    /* devmem entry */
    struct fw_rsc_devmem devmem13;

    /* devmem entry */
    struct fw_rsc_devmem devmem14;
    };

    extern char ti_trace_SysMin_Module_State_0_outbuf__A;
    #define TRACEBUFADDR (UInt32)&ti_trace_SysMin_Module_State_0_outbuf__A

    #pragma DATA_SECTION(ti_ipc_remoteproc_ResourceTable, ".resource_table")
    #pragma DATA_ALIGN(ti_ipc_remoteproc_ResourceTable, 4096)

    struct my_resource_table ti_ipc_remoteproc_ResourceTable = {
    1, /* we're the first version that implements this */
    21, /* number of entries in the table */
    0, 0, /* reserved, must be zero */
    /* offsets to entries */
    {
    offsetof(struct my_resource_table, rpmsg_vdev),
    offsetof(struct my_resource_table, text_cout),
    offsetof(struct my_resource_table, data_cout),
    offsetof(struct my_resource_table, heap_cout),
    offsetof(struct my_resource_table, ipcdata_cout),
    offsetof(struct my_resource_table, trace),
    offsetof(struct my_resource_table, devmem0),
    offsetof(struct my_resource_table, devmem1),
    offsetof(struct my_resource_table, devmem2),
    offsetof(struct my_resource_table, devmem3),
    offsetof(struct my_resource_table, devmem4),
    offsetof(struct my_resource_table, devmem5),
    offsetof(struct my_resource_table, devmem6),
    offsetof(struct my_resource_table, devmem7),
    offsetof(struct my_resource_table, devmem8),
    offsetof(struct my_resource_table, devmem9),
    offsetof(struct my_resource_table, devmem10),
    offsetof(struct my_resource_table, devmem11),
    offsetof(struct my_resource_table, devmem12),
    offsetof(struct my_resource_table, devmem13),
    offsetof(struct my_resource_table, devmem14),
    },

    /* rpmsg vdev entry */
    {
    TYPE_VDEV, VIRTIO_ID_RPMSG, 0,
    RPMSG_DSP_C0_FEATURES, 0, 0, 0, 2, { 0, 0 },
    /* no config data */
    },
    /* the two vrings */
    { DSP_MEM_RPMSG_VRING0, 4096, DSP_RPMSG_VQ0_SIZE, 1, 0 },
    { DSP_MEM_RPMSG_VRING1, 4096, DSP_RPMSG_VQ1_SIZE, 2, 0 },

    {
    TYPE_CARVEOUT,
    DSP_MEM_TEXT, 0,
    DSP_MEM_TEXT_SIZE, 0, 0, "DSP_MEM_TEXT",
    },

    {
    TYPE_CARVEOUT,
    DSP_MEM_DATA, 0,
    DSP_MEM_DATA_SIZE, 0, 0, "DSP_MEM_DATA",
    },

    {
    TYPE_CARVEOUT,
    DSP_MEM_HEAP, 0,
    DSP_MEM_HEAP_SIZE, 0, 0, "DSP_MEM_HEAP",
    },

    {
    TYPE_CARVEOUT,
    DSP_MEM_IPC_DATA, 0,
    DSP_MEM_IPC_DATA_SIZE, 0, 0, "DSP_MEM_IPC_DATA",
    },

    {
    TYPE_TRACE, TRACEBUFADDR, 0x8000, 0, "trace:dsp",
    },

    {
    TYPE_DEVMEM,
    DSP_MEM_IPC_VRING, PHYS_MEM_IPC_VRING,
    DSP_MEM_IPC_VRING_SIZE, 0, 0, "DSP_MEM_IPC_VRING",
    },

    {
    TYPE_DEVMEM,
    DSP_MEM_IOBUFS, PHYS_MEM_IOBUFS,
    DSP_MEM_IOBUFS_SIZE, 0, 0, "DSP_MEM_IOBUFS",
    },

    {
    TYPE_DEVMEM,
    DSP_TILER_MODE_0_1, L3_TILER_MODE_0_1,
    SZ_256M, 0, 0, "DSP_TILER_MODE_0_1",
    },

    {
    TYPE_DEVMEM,
    DSP_TILER_MODE_2, L3_TILER_MODE_2,
    SZ_128M, 0, 0, "DSP_TILER_MODE_2",
    },

    {
    TYPE_DEVMEM,
    DSP_TILER_MODE_3, L3_TILER_MODE_3,
    SZ_128M, 0, 0, "DSP_TILER_MODE_3",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_L4CFG, L4_PERIPHERAL_L4CFG,
    SZ_16M, 0, 0, "DSP_PERIPHERAL_L4CFG",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_L4PER1, L4_PERIPHERAL_L4PER1,
    SZ_2M, 0, 0, "DSP_PERIPHERAL_L4PER1",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_L4PER2, L4_PERIPHERAL_L4PER2,
    SZ_4M, 0, 0, "DSP_PERIPHERAL_L4PER2",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_L4PER3, L4_PERIPHERAL_L4PER3,
    SZ_8M, 0, 0, "DSP_PERIPHERAL_L4PER3",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_L4EMU, L4_PERIPHERAL_L4EMU,
    SZ_16M, 0, 0, "DSP_PERIPHERAL_L4EMU",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_DMM, L3_PERIPHERAL_DMM,
    SZ_1M, 0, 0, "DSP_PERIPHERAL_DMM",
    },

    {
    TYPE_DEVMEM,
    DSP_PERIPHERAL_ISS, L3_PERIPHERAL_ISS,
    SZ_256K, 0, 0, "DSP_PERIPHERAL_ISS",
    },

    {
    TYPE_DEVMEM,
    DSP_SR0_VIRT, DSP_SR0,
    DSP_SR0_SIZE, 0, 0, "DSP_SR0",
    },

    {
    TYPE_DEVMEM,
    L3_PERIPHERAL_MCASP, L3_PERIPHERAL_MCASP,
    SZ_1M*12, 0, 0, "DSP_MCASP",
    },

    {
    TYPE_DEVMEM,
    L3_PERIPHERAL_EDMA, L3_PERIPHERAL_EDMA,
    SZ_1M*3, 0, 0, "DSP_EDMA",
    },
    };

    #endif /* _RSC_TABLE_DSP_H_ */
  • Yun,

    You maybe able to find the culprit from Linux kernel log, for example, in previous log,

    [65876.540728] omap-iommu 40d02000.mmu: iommu fault: da 0x45c00000 flags 0x0

    The da (device address) 0x45c00000 points to MCASP2.

    You probably need to update the EDMA address 0x4330_0000 with DSP_EDMA_* address starting from 0x40D0_5000 for DSP1 and 0x4150_5000 for DSP2, see TRM Table 2-1. L3_MAIN Memory Map.


    Regards,

    Garrett

  • I have made some progress here. I was able to have it boot with the MCASP CLK and frame sync configured and IPC working most of the time. What I did was to move the MCASP configuration, device init and channel creation functions to the main function before BIOS_start().

    I still observe the following problems:

    1. Most of the time the serial console becomes unusable after the login prompt, with scrambled response when I type, for example,  "ls". The output is messed up.

    2. When the serial console is not usable, I am able to log to ssh and have a working prompt. I saw this error in dmsg:

    edma 43300000.edma: dma_ccerr_handler: Error interrupt without error event!

    3. Sometimes the linux just freezes completely before it reaches the login prompt. 

    My resource table configures the EDMA to the following values:

    #define L3_PERIPHERAL_EDMA 0x40D05000

    #define DSP_PERIPHERAL_EDMA 0x40D05000

    I have tried to change it to 0x43300000 and it stil freezes at the same frequency. There seems to be something else I didn't configure right.

    Any thoughts? Thanks!!

  • Yun,

    You can find out the exact EDMA address with the standalone MCASP loopback RTOS project (without IPC), then add it to resource table and debug from there.

    Regards,
    Garrett
  • Hello,

    It's exactly the address of EDMA_TPCC. From the Table 2.1:

    EDMA_TPCC 0x4330_0000 0x433F_FFFF 1MiB EDMA TPCC configuration space

    Can you give me pointers to what exactly is the EDMA_TPCC? I'm probably missing something, but I looked around and can't find much information about what TPCC is. 

    Thanks!

  • Yun,

    Please refer to TRM section 16.2 Enhanced DMA, TPCC is one of the major principle blocks in EDMA controller:

    TPCC - EDMA third-party channel controller (EDMA_TPCC)
    TPTC - EDMA third-party transfer controller (EDMA_TPTC)

    Table 16-111 of TRM (rev.H) lists the system EDMA_TPCC registers mapping starting from L3_main physical address 0x4330_0000.

    Regarding the error message "edma 43300000.edma: dma_ccerr_handler: Error interrupt without error event!", this was added in recent release, patchwork.kernel.org/.../ , which commands eDMA to re-evaluate the errors when actually no pending error edma event exists, thus avoid receiving flood of error interrupts. It should not be the cause of kernel crash.

    Regards,
    Garrett
  • Yun,

    Were you able to resolve the dma_ccerr_handler and kernel frozen issue? Any update on this?
    How does your mcasp2 entry look like in your dts? Is it the default setting:

    mcasp2: mcasp@48464000 {
    compatible = "ti,dra7-mcasp-audio";
    ti,hwmods = "mcasp2";
    reg = <0x48464000 0x2000>,
    <0x45c00000 0x1000>;
    reg-names = "mpu","dat";
    interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
    <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
    interrupt-names = "tx", "rx";
    dmas = <&edma_xbar 131 1>, <&edma_xbar 130 1>;
    dma-names = "tx", "rx";
    clocks = <&mcasp2_aux_gfclk_mux>, <&mcasp2_ahclkx_mux>,
    <&mcasp2_ahclkr_mux>;
    clock-names = "fck", "ahclkx", "ahclkr";
    status = "disabled";
    };

    and edma_tptc0?

    edma_tptc0: tptc@43400000 {
    compatible = "ti,edma3-tptc";
    ti,hwmods = "tptc0";
    reg = <0x43400000 0x100000>;
    interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
    interrupt-names = "edma3_tcerrint";
    };

    Regards,
    Garrett