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-AM437X: PRU hardware spinlock issue

Part Number: PROCESSOR-SDK-AM437X

Hi, 

I'm going to use the hardware SPINLOCK in PRU for synchronization. However, Linux kernel would output the following warning messages once PRU accesses the SPINLOCK register.

[  166.741227] ------------[ cut here ]------------
[  166.751241] WARNING: CPU: 0 PID: 18 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x254/0x370
[  166.760502] 44000000.ocp:L3 Custom Error: MASTER ICSS1 TARGET L4_PER_1 (Read): Data Access in User mode during Func$
ional access
[  166.772114] Modules linked in: ec_generic(O) ec_master(O) gpio_tpic2810 gpio_pisosr ti_prueth virtio_rpmsg_bus rpms$
_pru rpmsg_char rpmsg_core pruss_soc_bus pru_rproc pruss pruss_intc wkup_m3_rproc remoteproc
[  166.790731] CPU: 0 PID: 18 Comm: irq/21-l3-app-i Tainted: G        W  O    4.14.67-rt40 #1
[  166.799029] Hardware name: Generic AM43 (Flattened Device Tree)
[  166.804971] Backtrace:
[  166.807438] [<c010bf0c>] (dump_backtrace) from [<c010c1f0>] (show_stack+0x18/0x1c)
[  166.815043]  r7:00000009 r6:00000000 r5:c0b12378 r4:ef1a9e48
[  166.820731] [<c010c1d8>] (show_stack) from [<c0879014>] (dump_stack+0x24/0x28)
[  166.827988] [<c0878ff0>] (dump_stack) from [<c012c620>] (__warn+0xec/0x104)
[  166.834982] [<c012c534>] (__warn) from [<c012c678>] (warn_slowpath_fmt+0x40/0x48)
[  166.842499]  r9:00000001 r8:ef18a090 r7:c0b1246c r6:00000002 r5:c0b122a4 r4:c0b12348
[  166.850280] [<c012c63c>] (warn_slowpath_fmt) from [<c0469148>] (l3_interrupt_handler+0x254/0x370)
[  166.859191]  r3:ef181e40 r2:c0b12348
[  166.862780]  r4:80080003
[  166.865327] [<c0468ef4>] (l3_interrupt_handler) from [<c01738fc>] (irq_forced_thread_fn+0x28/0x7c)
[  166.874327]  r10:ef0bfb34 r9:c0dabcda r8:c01738d4 r7:ef164600 r6:00000001 r5:ef164600
[  166.882187]  r4:ef18a440
[  166.884734] [<c01738d4>] (irq_forced_thread_fn) from [<c0173bdc>] (irq_thread+0x108/0x1f4)
[  166.893035]  r7:ef164600 r6:00000001 r5:ffffe000 r4:ef18a440
[  166.898723] [<c0173ad4>] (irq_thread) from [<c014b5a8>] (kthread+0x160/0x168)
[  166.905892]  r10:ef0bfb34 r9:c0173ad4 r8:ef18a440 r7:ef1a8000 r6:00000000 r5:ef18a480
[  166.913755]  r4:ef18a4c0
[  166.916303] [<c014b448>] (kthread) from [<c0107a9c>] (ret_from_fork+0x14/0x38)
[  166.923558]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c014b448
[  166.931419]  r4:ef18a480
[  166.933962] ---[ end trace 000000000000001c ]---
# [  166.938650] ------------[ cut here ]------------

Here is my resource table for PRU:

#define L4_PERIPHERAL_L4PER1    0x48000000

#define SZ_2M                   0x00200000

struct my_resource_table {
        struct resource_table base;

        uint32_t offset[1]; /* Should match 'num' in actual definition */
        struct fw_rsc_devmem l4_perp1;
};

#pragma DATA_SECTION(pru_remoteproc_ResourceTable, ".resource_table")
#pragma RETAIN(pru_remoteproc_ResourceTable)
struct my_resource_table pru_remoteproc_ResourceTable = {
        1,      /* we're the first version that implements this */
        1,      /* number of entries in the table */
        0, 0,   /* reserved, must be zero */
        {
            offsetof(struct my_resource_table, l4_perp1),
        },
        {
                TYPE_DEVMEM,
                L4_PERIPHERAL_L4PER1, L4_PERIPHERAL_L4PER1,
                SZ_2M, 0, 0, "PRU_PERIPHERAL_L4PER1",
        },
};

#endif /* _RSC_TABLE_PRU_H_ */

Is there anything I miss?

Thanks

  • Hello Kang,

    1) What is your PRU code for accessing the Spinlock register?

    2) Why are you adding the Spinlock to the PRU Resource table? As long as your PRU code enables the OCP master port, I would expect you to be able to write to the spinlock registers. In your Linux Processor SDK, see example-applications/pru-icss-x.x/examples/am437x/PRU_RPMsg_... examples for an example of how to enable the OCP master port.

    Regards,

    Nick

  • Hi Nick, 

    Thanks for your reply.

    Nick Saulnier said:

    1) What is your PRU code for accessing the Spinlock register?

    typedef struct {
        volatile uint32_t rev;
        volatile uint32_t reserved0[(0x10-0x04)/4];
        volatile uint32_t sysconfig;
        volatile uint32_t status;
        volatile uint32_t reserved1[(0x800-0x18)/4];
        volatile uint32_t lock[LOCK_REG_NUM];
    } sys_hwspinlock_t;
    
    static sys_hwspinlock_t *hwspinlock = ((sys_hwspinlock_t *)0x480CA000);
    void hwspinlock_init(void)
    {
        hwspinlock->sysconfig |= SPINLOCK_SYSCONFIG_SOFTRESET;  
        while (!(hwspinlock->status & SPINLOCK_SYSSTATUS_RESETDONE));
    }
    
    int hwspinlock_trylock(uint32_t id)
    {
        return hwspinlock->lock[id];
    }
    
    int hwspinlock_unlock(uint32_t id)
    {
        hwspinlock->lock[id] = SPINLOCK_NOTTAKEN ;
        return 0;
    }
    ...
    

    Nick Saulnier said:

    2) Why are you adding the Spinlock to the PRU Resource table?

    I think the reason of the kernel warning is PRU tries to access L4_PER_1 but kernel blocks it, so it is needed to tell the kernel to grant the right by resource table. 

    Nick Saulnier said:

    As long as your PRU code enables the OCP master port, I would expect you to be able to write to the spinlock registers. In your Linux Processor SDK, see example-applications/pru-icss-x.x/examples/am437x/PRU_RPMsg_... examples for an example of how to enable the OCP master port.

    Is it correct to enable the OCP master by " CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;"?

    If it is right, I have done it. 

    Regards,

    George Kang

  • Hello George,

    Yes, that should enable the OCP master port.

    "L3 Custom Error: MASTER ICSS1 TARGET L4_PER_1 (Read): Data Access in User mode during Functional access" - This error does not necessarily mean that Linux is blocking the PRU from reading something. I have seen that error before if a peripheral's clock sources have not been properly initialized.

    Try using a resource table where L4_PERIPHERAL_L4PER1 is not defined. If you are still running into errors, try reading the spinlock from the command line with devmem2 to see if you get the same issues when reading/writing from Linux.

    Regards,

    Nick

  • Hi Nick, 

    Which type of fw_rsc shall be used?

    Here is the header about the resource table but it does not work.

    struct my_resource_table {
            struct resource_table base;
    
            uint32_t offset[1]; /* Should match 'num' in actual definition */
            struct fw_rsc_devmem l4_perp1;
    };
    
    #pragma DATA_SECTION(pru_remoteproc_ResourceTable, ".resource_table")
    #pragma RETAIN(pru_remoteproc_ResourceTable)
    struct my_resource_table pru_remoteproc_ResourceTable = {
            1,      /* we're the first version that implements this */
            1,      /* number of entries in the table */
            0, 0,   /* reserved, must be zero */
            {
                offsetof(struct my_resource_table, l4_perp1),
            },
            {
                    TYPE_DEVMEM,
                    L4_PERIPHERAL_L4PER1, L4_PERIPHERAL_L4PER1,
                    SZ_2M, 0, 0, "PRU_PERIPHERAL_L4PER1",
            },
    };
    

  • Hello George,

    I would start by copying the empty resource table in your Linux Processor SDK, see example-applications/pru-icss-x.x/examples/am437x/PRU_Halt/resource_table_empty.h

    Regards,

    Nick