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.

AM5728: AM5728在使用CMEM的情况下,GPMC怎样配置使得DSP获得访问权限,相关问题

Part Number: AM5728

您好Gary,

谢谢您的回复,我基本理解,但是我还有几个问题,想知道答案。

1. DTS里,怎么设,可以让GPMC的owner 让给DSP?我目前就是ARM可以读写GPMC,但是DSP不行。

我只看到omap-gpmc.c里有如下代码,

static int gpmc_gpio_init(struct gpmc_device *gpmc)
{
int ret;

gpmc->gpio_chip.parent = gpmc->dev;
gpmc->gpio_chip.owner = THIS_MODULE;
gpmc->gpio_chip.label = DEVICE_NAME;
gpmc->gpio_chip.ngpio = gpmc_nr_waitpins;
gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction;
gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input;
gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output;
gpmc->gpio_chip.set = gpmc_gpio_set;
gpmc->gpio_chip.get = gpmc_gpio_get;
gpmc->gpio_chip.base = -1;

DTS:黑体是我增加的。另外,GPMC的config那七个寄存器的,我没有变化,映射到0x01000000空间。

reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;

cmem_block_mem_0: cmem_block_mem@a0000000 {
reg = <0x0 0xa0000000 0x0 0x0c000000>;
no-map;
status = "okay";
};

cmem_block_mem_1_ocmc3: cmem_block_mem@40500000 {
reg = <0x0 0x40500000 0x0 0x100000>;
no-map;
status = "okay";
};

cmem_block_mem_2_gpmc: cmem_block_mem@01000000 {
reg = <0x0 0x01000000 0x0 0x100000>;
no-map;
status = "okay";
};

};

2.  CMEM分配时,好像不是每次都成功的,即便我每次都是重新上电。如下只显示Pool 0,没有Pool1,此时Pool1 能不能work?

root@xivi:/lib/firmware# modprobe cmemk phys_start=0xa0000000 phys_end=0xac000000 pools=24x8388608 phys_start_1=0x01000000 phys_end_1=0x01000500 pools_1=1x1024,1x256
root@xivi:/lib/firmware# cat /proc/cmem

Block 0: Pool 0: 1 bufs size 0xc000000 (0xc000000 requested)

Pool 0 busy bufs:
id 0: phys addr 0xa0000000 (cached)

Pool 0 free bufs:
root@xivi:/lib/firmware#

3. 你说的共享内存,区别于CMEM,是指的ARM上,Linux里的如下API吗?那DSP等其他的处理器,是直接访问物理地址,还是有对应的虚拟地址, 怎么映射虚拟地址?有没有相关的例程可以参考?

int shmid = shmget((key_t)1234, sizeof(struct stuShareMemory), 0666|IPC_CREAT);

shm = shmat(shmid, (void*)0, 0);

4. 在ARM与DSP之间,共享CMEM内存,或者使用shmem,DSP写入数据后,ARM这端可以直接读吗?还是需要Cache_Invalidate之类的,我不是很清楚,最好有相关操作例程,帮助理解一下,谢谢!

  • 我试了一下CMEM分配GPMC内存空间, 没有报错

    root@xivi:/lib/firmware# pkill ti-mctd
    root@xivi:/lib/firmware# rmmod cmemk
    [ 9277.753391] cmemk unregistered
    root@xivi:/lib/firmware# modprobe cmemk phys_start=0xa0000000 phys_end=0xac000000 pools=24x8388608 phys_start_1=0x01000000 phys_end_1=0x01100000 pools_1=2x1024
    [ 9277.845866] CMEMK module: reference Linux version 4.9.65
    [ 9277.851993] allocated heap buffer 0x1000000 of size 0xfe000
    [ 9277.857653] cmemk initialized

    root@xivi:~# cat /proc/cmem

    Block 0: Pool 0: 24 bufs size 0x800000 (0x800000 requested)

    Pool 0 busy bufs:
    id 10: phys addr 0xa6800000 (noncached)
    id 9: phys addr 0xa7000000 (noncached)
    id 8: phys addr 0xa7800000 (noncached)
    id 7: phys addr 0xa8000000 (noncached)
    id 6: phys addr 0xa8800000 (noncached)
    id 5: phys addr 0xa9000000 (noncached)
    id 4: phys addr 0xa9800000 (noncached)
    id 3: phys addr 0xaa000000 (noncached)
    id 2: phys addr 0xaa800000 (noncached)
    id 1: phys addr 0xab000000 (noncached)
    id 0: phys addr 0xab800000 (noncached)

    Pool 0 free bufs:
    id 11: phys addr 0xa6000000
    id 12: phys addr 0xa5800000
    id 13: phys addr 0xa5000000
    id 14: phys addr 0xa4800000
    id 15: phys addr 0xa4000000
    id 16: phys addr 0xa3800000
    id 17: phys addr 0xa3000000
    id 18: phys addr 0xa2800000
    id 19: phys addr 0xa2000000
    id 20: phys addr 0xa1800000
    id 21: phys addr 0xa1000000
    id 22: phys addr 0xa0800000
    id 23: phys addr 0xa0000000

    Block 1: Pool 0: 2 bufs size 0x1000 (0x400 requested)

    Pool 0 busy bufs:

    Pool 0 free bufs:
    id 0: phys addr 0x10ff000
    id 1: phys addr 0x10fe000
    root@xivi:~#

    cmem_pool_virtual = CMEM_allocPool2(1, CMEM_getPool(256), &cmemAttrs);
    sem_wait(&sem_printf);
    printf("-- GPMC CMEM alloc.physical_address: 0x%08X\n", CMEM_getPhys(cmem_pool_virtual));
    sem_post(&sem_printf);

    GPMC CMEM alloc.physical_address: 0x010FF000

    现在是CMEM成功了,问题是接下来,一定需要messageQ_put 给DSP,就可以让DSP拥有读写GPMC的权限了吗?

    谢谢!

  •  您好,

    1. GPMC的owner可以通过在设备树中设置

    gpmc@xxxxx {owner = <&dsp>; ...}
    来进行设置,其中
    &dsp
    是指向DSP设备节点的指针。您需要注意的是,这需要在设备树中同时定义DSP设备节点,并在DSP设备驱动中实现对GPMC的访问控制。

    2. CMEM分配时,可能会因为物理地址空间不足或者其他原因导致分配失败。如果分配失败,可以尝试增加物理地址空间或者减小分配的内存池大小。另外,如果您只看到了Pool 0,而没有看到Pool 1,可能是因为你的设备树中没有正确定义第二个CMEM设备节点。

    3. 共享内存可以使用Linux系统中的

    shmget
    shmat
    函数进行创建和映射。对于DSP等其他处理器,可以通过在设备树中定义共享内存的物理地址和大小,并在DSP设备驱动中实现共享内存的访问控制。在DSP端,可以直接访问物理地址,而无需虚拟地址。需要注意的是,不同处理器之间的字节序可能不同,需要进行字节序转换。

    4. 如果ARM与DSP共享了CMEM内存或者使用了共享内存,那么ARM可以直接读取DSP写入的数据。但是您需要注意的是,由于处理器的缓存机制,ARM可能会读取到过期的数据。为了避免这种情况,需要在ARM中使用Cache_Invalidate等函数来刷新缓存。

  • 您好,

    是的,一旦您成功分配了 GPMC 内存空间并获得了物理地址,接下来您需要将这个物理地址传递给 DSP,让 DSP 可以访问这块内存。通常情况下,您可以使用消息队列来传递这个物理地址给 DSP。

    在您的应用程序中,您可以使用消息队列接口将物理地址发送给 DSP。DSP 接收到这个消息后,就可以使用该物理地址来读写 GPMC 内存空间。在 DSP 端,您需要相应的代码来处理消息队列接收,并解析消息中的物理地址,以便 DSP 可以正确地访问 GPMC 内存空间。

    需要注意的是,您需要确保 DSP 端的代码能够正确地处理接收到的物理地址,并且能够以正确的方式访问 GPMC 内存空间。