ET6001双核编程应用指南

文档编号:AN0008

序号

版本

修改日期

修改说明

1

1.0

2024/10/17

初始发布

双核简介

ET6001系列MCU芯片内置2个ARM Cortex-M7内核,频率200Mhz,最高频率是300Mhz。2个M7内核之间使用同一条AXI总线,除了CPU核内资源外(TCM/SYSTICK/FPU等),共享其他外设资源(FLASH/RAM/PWM/ADC等)。本文从以下方面介绍ET6001的双核应用:

  1. 内存模型

  2. 启动方式

  3. 消息同步

  4. 共享资源竞争和保护

  5. 维护CACHE一致性

内存模型

ET 6001双核的内存模型如下图所示:

AN0008008

由图可得出:

  • CORE0和CORE1有各自的ITCM和DTCM,且地址相同,但互不影响;

  • CORE0不能直接访问CORE1的ITCM/DTCM地址空间,同样CORE1也不能直接访问CORE0的ITCM/DTCM地址空间;

  • CORE0和CORE1可以通过DMA来间接获取对方TCM空间;

  • CORE0和CORE1之间可以共用FLASH/SRAM/外设;

  • CORE0和CORE1有各自的核内外设,比如CACHE/FPU/MPU/NVIC,并且在私有外设空间内,可以标注自身CORE ID,让程序知道当前运行的CORE的ID。

  • CORE0和CORE1可以操作同一个外设,也可以分配到各自的外设。

启动方式

ET 6001双核启动方式是CORE0会在复位后自动启动,CORE1的启动由CORE0唤醒。CORE0的启动地址由BOOT MODE决定,与正常单核操作一致。CORE1的启动地址可以由CORE0指定,并可以为任意地址。在CORE0唤醒CORE1之前,CORE1处于挂起状态不能被仿真器捕捉到。常用的启动模型有以下几种:

  • CORE0和CORE1各自有独立的镜像,并且加载地址互不影响,分别存放在2个地址空间中,各自执行各自的程序代码。此模型通常需要维护2个工程和使用2个调试器。

    AN0008009

  • CORE0的镜像包含CORE1的镜像,可以是从上位机获取并存储在指定位置,也可以是CORE0和CORE1镜像拼接合并而来。由CORE0搬运CORE1镜像到指定位置并执行,比如SRAM空间和ITCM/DTCM空间或者FLASH空间。此模型通常需要2个工程和1个调试器,并使用CORE0进行代码/数据搬运 工作。

    AN0008010

  • CORE0和CORE1共用同一个镜像,并且镜像内包含2个分支,分别是CORE0执行的分支和CORE1执行的分支,通过访问获取当前CORE ID的接口来识别当前运行的CORE。此模型通常只需要1个工程和1个调试器。但是需要注意的是,程序的ram段必须放在ITCM/DTCM空间中,避免DATA/BSS数据相互干扰。

    AN0008011

    SDK双核管理函数接口位于et6x_dualcore.h中,又有2个接口:

函数接口

描述

CORE_IDDUALCORE_GetCurrentCoreId(void);

获取当前COREID,用于识别当前CORE。

void DUALCORE_StartCore1(uint32_tstart_addr);

指定 COER1的镜像入口,通常是CORE1 RESET_HANDLER的地址。

使用方法可参考示例代码IPCM和SPINLOCK模块中的代码。

消息同步

在双核编程应用中,通常CORE0和CORE1之间需要交互数据和传递消息。常用的消息同步的方法有:共享内存,消息邮箱,核间中断等。

在ET6001中,消息的同步可以通过IPCM( internal processor communication message)外设实现,比如,CORE0负责接收数据,CORE1负责计算数据。当CORE0的数据准备好后,将数据通过IPCM发送给CORE1。CORE1发生IPCM中断,及时响应COR E0的计算请求,将IPCM中传递的数据内容获取,并且进行计算。CORE1计算完成后,再通过IPCM,将计算结果传回CORE0,CORE0发生中断获取到计算结果并清空IPCM,完成此次的消息传递,如下图所示:

AN0008012

通过IPCM消息邮箱每次传递的消息实时性高,但每次传递的数据量较少,且交互过程有一点复杂。

在某些实时性不强的交互场景下,ET6001可以通过设置共享内存的方式,交互大量数据。在这种场景下,一片内存区域通常只分配一个读者和一个写者。CORE0和CORE1同时读写会造成错误。通常这种场景下可以通过加锁来保护,在下一章中详细描述加锁保护。如下图所示:

AN0008013

另外,可以结合IPCM和共享内存,使用IPCM与共享内存搭配使用,在IPCM消息邮箱中存储消息内容,比如数据地址,数据大小,数据类型等,然后产生中断到对应的核中,可以在大数据量和实时性中达到一个兼容效果。类似的开源库有OPENAMP等。如下图所示:

AN0008014

使用方法可参考示例代码IPCM中的代码。

共享资源竞争和保护

在ET6001中,CORE0,CORE1对同一个资源进行读写时,会产生资源竞争,导致读写同步问题。这个共享资源可以是同一段SRAM空间,也可以是同一个外设。这种情况下就需要保护好共享资源。ET6001有硬件自旋锁外设SPINLOCK用于保护临界资源。当资源已被占用时,资源申请者”自旋“等待。例如当C ORE0获取UART0资源前,先将此UART0资源加锁,CORE1获取UART0资源时,加锁操作会导致CORE1自旋等待。当CORE0释放资源后,CORE1迅速获取UART0资源,进行操作。应当注意的是,临界资源应当快进快出。如下图所示:

AN0008015

维护CACHE一致性

在ET6001中,Cortex-M7带有CACHE功能。因此,在双核应用中应注意CACHE一致性的维护。

在对外设的操作中,不需要维护CACHE一致性。因为根据Cortex-M7的内存模型,外设内存区间是不能CACHE属性的,如下图:

AN0008016

在共享内存SRAM中,是需要进行CACHE一致性的保护。首先,也可以通过MPU对内存区域的CACHE属性设置,打开或者关闭内存的CACHE属性。同时CACHE默认关闭,需要调用CACHE使能接口打开ICACHE和DCACHE。CACHE维护的接口如下所示:

CACHE维护接口

描述

SCB_EnableICache

使能ICACHE

SCB_DisableICache

失能ICACHE

SCB_InvalidateICache

无效化ICACHE

SCB_InvalidateICache_by_Addr

无效化指定地址的ICACHE

SCB_EnableDCache

使能DCACHE

SCB_DisableDCache

失能DCACHE

SCB_InvalidateDCache

无效化DCACHE

SCB_CleanDCache

将DCACHE中数据写回到内存中

SCB_CleanInvalidateDCache

将DCACHE中数据写回到内存中并无效化DCACHE

SCB_InvalidateDCache_by_Addr

无效化指定地址的ICACHE

SCB_CleanDCache_by_Addr

将指定地址的DCACHE中数据写回到内存中

SCB_CleanInvalidateDCache_by_Addr

将指定地址的DCACHE中数据写回到内存中并无效化DCACHE

在访问带CACHE属性的共享内存时,需要注意以下常见场景:

  • 读取操作时需要提前无效化内存空间。

  • 写入操作后,需要使用Clean相关接口写回到内存中。

  • 进行代码的搬运后,需要对ICAHCE进行无效化操作。

另外,在读写SRAM中,要使用带有volatile修饰的读写操作,避免编译器优化,导致读取到寄存器中的值,也会导致数据不一致现象。