双核调试指南
提示
该文档仅适用于ET6001芯片。
ET6001芯片内部包含两个ARM Cortex-M7内核,分别为主核和从核。主核负责系统的初始化,控制和调度,从核负责数据处理和实时任务。 本文档将介绍双核之间的资源分配、调试与程序烧录、通信等方面的内容。
双核间的调试与程序烧录
上电默认状态
芯片上电或者复位(Core复位除外)后,此时,主核处于运行状态,从核处于等待状态 。 从核处于等待状态时,无法进行调试和烧录操作。 此时,主核可以通过调用API函数 DUALCORE_StartCore1(0x08080000); 来使从核进入调试模式。 其中输入参数为从核的启动地址,通常为PFLASH1的起始地址 0x08080000 。
// 主核main函数
int main(void)
{
uint32_t frq = 0;
uint8_t tx_buffer[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint8_t rx_buffer[8] = {0};
SCB_EnableICache();
SCB_EnableDCache();
frq = CRG_GetCPUFreq();
SHM_Init();
IPC_Init();
BSP_Init();
/* 启动CORE1, 开始从 0x08080000 执行程序 */
DUALCORE_StartCore1(0x08080000);
while (1)
{
IPC_SendMessage(tx_buffer, 4);
/* block receive */
IPC_RecvMessage(rx_buffer, 4);
/* 共享内存,core0 向 core1 发送数据 */
SHM_WriteToCore1(tx_buffer, 8);
DELAY_US(1000000);
}
}
芯片的时钟配置及各模块的复位和门控配置均在主核中完成。系统启动文件 SystemInit 函数中,如果检测到代码在从核中运行,则 直接跳过硬件初始化工作。
void SystemInit(void)
{
/* Enable Global Interrupt Mask */
__enable_irq();
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */
#endif
if (DUALCORE_GetCurrentCoreId() == CORE1)
{
return; // 从核不需要进行硬件初始化
}
// 主核的时钟配置
...
调试接口
两个核拥有完全独立的调试接口,主核和从核可以同时进行调试(从核需处于运行状态)。 主从核的调试接口均为SWD,对应的管脚名称分别为:
CPU0_SWJ_TMS
CPU0_SWJ_SWCLKTCK
CPU1_SWJ_TMS
CPU1_SWJ_SWCLKTCK
也就是说,调试双核需要2个SWD(J-Link)调试器,分别连接到主核和从核的调试接口上。
从核调试时,建议将KEIL的 Debug Reset选项中的Reset Target设置为“Core” 或者 “VECTRESET”。 因为从核的复位信号是由主核控制的,使用“System”选项可能会导致从核进入等待状态而无法调试。 主核调试时,建议将KEIL的 Debug Reset选项中的Reset Target设置为默认即可。 KEIL软件Debug配置方式如下:
程序烧录
主核和从核的程序烧录方式相同,均为通过SWD接口进行烧录。建议按照两个核分别使用一个FLASH的方式进行FLASH资源分配。
核 |
PFLASH |
起始地址 |
|---|---|---|
主核 |
PFLASH0 |
0x08000400 |
从核 |
PFLASH1 |
0x08080000 |
当调试器连接到从核的调试接口时,需要确认从核处于运行状态,否则调试器无法连接到从核。
另外,还需要确保用户选项字 OTA_MODE 和 BANK_SWAP 均设置为0。(出厂默认均位0)
API介绍
主核和从核的API函数均在 et6x_dualcore.h 头文件中定义。
DUALCORE_StartCore1(uint32_t start_addr); 使从核进入运行状态
DUALCORE_GetCurrentCoreId(void); 获取当前程序代码运行在哪个核上
双核间资源分配
主核和从核之间,除了每个核的ITCM和DTCM内存区域是独立的以外,其他资源均为共享资源。
ITCM&DTCM
主核和从核各自拥有独立的ITCM和DTCM,MPU,FPU,NVIC,Cache,每个核的ITCM和DTCM内存区域分别为:
ITCM: 0x00000000 ~ 0x0000FFFF
DTCM: 0x20000000 ~ 0x2000FFFF
每个核的ITCM和DTCM内存区域大小均为64KB,主核和从核的ITCM和DTCM内存区域地址相同,各种访问互不影响。 主核和从核的ITCM和DTCM内存区域均为SRAM类型的内存,具有高带宽、低延迟的特点,适合用于存储实时数据和代码。
内存
主核和从核共享256KB的SRAM内存区域,地址范围为0x20400000 ~ 0x2043FFFF。SRAM资源的分别可以按以下方式进行分配:
主核和从核各自划分128KB的SRAM内存区域,主核的SRAM内存区域地址范围为0x20400000 ~ 0x2041FFFF,从核的SRAM内存区域地址范围为0x20420000 ~ 0x2043FFFF。
主核和从核各自划分64KB的SRAM内存区域,主核的SRAM内存区域地址范围为0x20400000 ~ 0x20407FFF,从核的SRAM内存区域地址范围为0x20408000 ~ 0x2040FFFF。 剩余的128KB SRAM内存区域可以用于主核和从核之间的共享内存使用。
中断
主核和从核用于各自的NVIC控制器,共享256个中断源,主核和从核的中断源号相同。中断源号范围为0 ~ 255。 某个中断源号的中断请求可以同时触发主核和从核的中断处理程序。所以在实际使用时,可根据主核和从核的应用场景,每个核可选择是否使能该中断源号的中断请求。
例如:
STIMER只被从核使用,主核不需要使能STIMER的中断请求。
SPRWM的中断,主核和从核均需要响应,则主核和从核均需要使能该中断源号的中断请求。
使能和禁用中断源号的中断请求可以使用以下API函数:
NVIC_EnableIRQ(IRQn_Type IRQn); 使能中断源号的中断请求
NVIC_DisableIRQ(IRQn_Type IRQn); 禁用中断源号的中断请求
NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority); 设置中断源号的中断优先级
NVIC_GetPriority(IRQn_Type IRQn); 获取中断源号的中断优先级
NVIC_ClearPendingIRQ(IRQn_Type IRQn); 清除中断源号的中断请求
外设
主核和从核之间共享所有的外设资源,所以两个核在对外设进行同时访问时,需要进行互斥处理。 主核和从核之间的互斥处理主要利用芯片自带的硬件模块SPINLOCK来实现。
双核间通信
ET6001 针对双核应用,提供了两个硬件模块 IPCM 和 SPINLOCK。
关于该部分的内容,我们提供了示例程序,具体的使用方法可以参考该示例程序。
该示例程序的路径为:
ET6001_Examples/Examples/SPINLOCK
ET6001_Examples/Examples/IPCM
ET6001_Examples/Examples/dualcore_demo
其中dualcore_demo 例程为综合例程,包含了对IPCM和SPINLOCK的使用。并且提供了基于SPINLOCK + shared memory的 shm 中间件以及 基于 IPCM 的 IPC 中间件的使用示例。
IPCM
IPCM是Inter-Processor Communication Module的缩写,意为“核间通信模块”。 该模块提供两个主要的功能:一是触发核间中断,二是核间传递少量数据。 ET6001的IPCM模块共有16个消息邮箱,同时IPCM提供16个通道,每个通道均有独立的中断。 每个邮箱可参数7个32位的消息。
SPINLOCK
在 ET6001中, 主从核对同一个外设资源进行读写时, 会产生资源竞争, 导致读写 同步问题。 这个共享资源可以是同一段 SRAM 空间, 也可以是同一个外设。 这种情况下就需 要保护好共享资源。 ET6001 有硬件自旋锁外设 SPINLOCK 用于保护临界资源。 当资源已被占 用时, 资源申请者” 自旋“等待。
关于双核使用,更多的内容可以参考: ET6001双核编程应用指南