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.

TDA4VM: MCU和DSP之间的内存共享以及数据同步

Part Number: TDA4VM

你好,如何在MCU2_0和DSP_C6X_0之间互访内存,IPC的通讯效率有点低,想采用C66X_0直接访问MCU2_0的内存来做,效率应该更好一些。

如果可以,如何保证两个核心访问内存数据的一致性,同一个核心的话可以用互斥锁来保证数据一致性,不通核心之间如何保证?

  • 你好,

    如何在MCU2_0和DSP_C6X_0之间互访内存

    可以用共享内存来实现跨核心的数据共享,再然后用信号量来实现数据的同步和互斥访问,这样就可以提高通讯效率,还确保了数据的一致

    如何保证两个核心访问内存数据的一致性

    使用硬件层面的同步机制,比如:缓存一致性协议,以及在软件层面使用同步原语,如信号量和互斥锁。

  • 有没有代码案例,MCU和DSP之间读写共享内存数据的案例?

  • 另外,

    1.我理解 的是信号量和互斥锁是在同一个核心上可以用,跨核心怎么能用同一个信号量或者互斥锁?

    2.缓存一致性协议这个是怎么定义的,有对应的模块和API么?

  • 为您咨询产品线工程师,这需要一些时间

  • 您好,

    1.您的理解是正确的,信号量和互斥锁通常是在同一个核心上使用的,用于同步不同线程或进程之间的访问。在跨核心的情况下,由于不同核心之间的内存不共享,因此不能直接使用同一个信号量或互斥锁。

    在跨核心的情况下,通常需要使用一些特殊的同步机制,例如消息队列、共享内存等。这些机制可以让不同核心之间进行通信和同步,从而实现跨核心的共享资源访问。

    例如,在使用消息队列时,一个核心可以将消息发送到队列中,另一个核心可以从队列中接收消息。通过这种方式,不同核心之间可以进行通信和同步,而不需要直接访问共享资源。

    在使用共享内存时,不同核心之间可以访问同一块物理内存,从而实现共享资源的访问。但是,由于共享内存的访问需要进行同步,因此通常需要使用一些同步机制,例如信号量或互斥锁,来保证共享内存的正确访问。

    2.缓存一致性协议是指一种协议或机制,用于确保在多个处理器或核心共享同一块内存时,各个处理器或核心的缓存中的数据与主存中的数据保持一致。这样可以避免由于缓存中的数据不一致而导致的错误行为和数据损坏。

  • 由于与数据一致性和同步相关的潜在问题,在系统内不同核心之间访问内存可能会很复杂。在处理MCU和DSP通信时,确保核心之间的数据一致性至关重要。

    1.内存映射和寻址:
       确保两个核心都可以访问的内存区域被正确映射和访问。
       使用硬件或SDK提供的适当内存映射技术来允许内核之间的直接访问。
    2.同步机制:
       实现同步机制以避免并发访问问题。
       互斥锁:使用像互斥锁这样的锁机制来确保对共享资源的独占访问。这样可以防止同时访问并保持数据一致性。
       信号量:使用信号机制来指示何时数据准备好或何时核心完成对共享内存的访问。
    3.缓存一致性:
       确保内核之间的缓存一致性。一个核心所做的更改对另一个核心应该是可见的。
       必要时使缓存无效或刷新,以确保更新的数据跨核心共享。
       使用架构提供的内存屏障或缓存维护操作来同步内存访问。


    我们确保上述所有关键点在IPC机制中都得到满足,它使用DDR中的共享内存在内核之间进行读写,并使用MAILBOX机制获得中断。

  • IPC机制是可以,但是IPC通讯会影响定时器的准确性,我这边场景是MCU用SPI采集ADC数据,采集频率是50K,用定时器来控制频率和时间间隔,同时将采集的数据传输给DSP,如果采用IPC传输数据,数据传输会影响定时器的准确性,导致采集时间间隔不均衡。基于这种情况,所以想用直接内存访问的方式来让MCU传输数据给到DSP,没有其他中断影响定时器的中断,效果会好一些。

    或者您是否有更好的方式,可以MCU和DSP传输大量数据,又不会影响定时器的中断间隔时间。

  • 好的。您可以在 DDR空间 或其他地方选择一个公共共享内存区域,而不是使用 IPC 传递数据,传递此公共共享内存区域的地址,这样可以减少在内核之间传输所需的时间,并且可以传输大量数据。

    但这里的困难在于,核心何时从公共空间读取数据,并需要确保公共空间区域不会因损坏而被覆盖。

  • 但这里的困难在于,核心何时从公共空间读取数据,并需要确保公共空间区域不会因损坏而被覆盖

    对,这就是我上面说的如何保证公共空间读写数据如何保持一致性的问题,有没有什么办法可以保证?

  • 除了IPC之外,我们在SDK中没有任何其他机制可以像您建议的那样进行数据传输。但正如我所说,在将数据写入共享内存后,然后使用IPC传递地址,并让另一个核心在DSP核心上触发邮箱中断后立即读取数据,然后它就会好起来,我认为这不会造成任何问题。

  • 但是目前确实存在问题,我在MCU2_0上用定时器每隔20微秒触发后通过SPI采集一次ADC,如果只采集,不通过IPC传输,定时器的间隔是准确的,但是如果采集后IPC把采集数据传给另外一个核心,定时器就不准了,会偶先间隔30微秒甚至40微秒才触发一次,这个定时器不准的问题是不是有什么办法可以解决?

  • 1.如果没有IPC,那么mc2_0上的定时器是正确的。当您使用IPC时,您在定时器中有延迟,不正确的通过SPI获取数据,我认为是正确的吗?

    2.您可以告诉我在用什么定时器,并且是在引入mc2_0核心上的Ipc后存在不正确吗?

    3.您在mc2_0内核上运行的是什么操作系统?

  • 1.是的,没有IPC,定时器基本是正确的,有了IPC,定时器就会有延时

    2.用的是TimerP定时器,是在MCU2.0上,而且确实是引入了IPC后就开始不正确了

    3.使用的是freeRTOS

    以下是我大概的测试代码,

    static void timerIsr(void *arg)
    {
    	SPI_Transaction   transaction  ={0};
        bool            transferOK = true;
    	uint8_t Received_DATA[8] = {0};
    	uint32_t payload = 0;
    	//timerIsrCount++;
    	int32_t status = 0;
    	uint32_t i = 0;
    	transaction.count = 4;
    	transaction.txBuf = &NO_OP[0];
    	transaction.rxBuf = &Received_DATA[0];
    	transferOK = SPI_transfer((SPI_Handle)arg, &transaction);
    }
    
    
    
    
    void spi_transfer_timer(void * spi)
    {
     TimerP_Params_init(&timerParams);
        timerParams.runMode    = TimerP_RunMode_CONTINUOUS;
        timerParams.startMode  = TimerP_StartMode_USER;
        timerParams.periodType = TimerP_PeriodType_MICROSECS;
        timerParams.period     = 20;
    	timerParams.arg = (void *)spi;
        handle = TimerP_create(1, (TimerP_Fxn)&timerIsr, &timerParams);
        if (handle == NULL)
        {
          appLogPrintf("\n Timer Create 1 error \n");
          //ret = false;
        }
          timerStatus = TimerP_start(handle);
    
          if (timerStatus != TimerP_OK) {
            appLogPrintf("Err: Coult not start the timer 1 \n");
          }
        }

  • 我怀疑IPC任务也在消耗核心中的带宽,因此您的SPI任务正在延迟获取ADC信息。您可以使用SPI DMA,以便它不需要核心干预,它可以获取ADC的数据并将其放在内存中。

  • 我尝试一下试试,如果有问题我再来回复