参考AURIX™ System Architecture 和 Multicore_1 for KIT_AURIX_TC397_TFT:
CPU架构;
TC1.6.2P实现:
这一部分手册的内容直接机翻了. 至于怎么用, 这节先不管, 有个概念即可.
AURIX™ TC3xx平台具有三个独立的片上连接资源:
SRI
Fabric)SRI Fabric将TriCore CPU, DMA模块和其他高带宽请求者连接到高带宽存储器和其他资源用于指令提取和数据访问.
SPB将TriCore CPU, DMA模块和其他SPB主设备连接到中低带宽外设, SPB主服务器不会直接连接到SRI Fabric,而是将通过SRI_F2S桥访问SRI附加的资源.
BBB将TriCore CPU, DMA模块和SPB主站与ADAS资源相连. 主SRI不直接连接到BBB, 但通过SFI_S2F桥接器访问BBB连接的资源.
SRI连接TriCore CPU和高性能模块如DMA等. 结构的关键组件是SRI交叉开关, 它将所有代理(agent)连接到一个SRI域. SRI交叉开关承载域的SRI主站和SRI从站之间的事务. SRI交叉开关支持不同SRI主代理和SRI从代理之间的并行事务. 除了并发请求的并行性, 它还支持从SRI主设备到SRI从设备的流水线请求. SRI功能概述:
与以前的基于AURIX™的产品相比,AURIX连接性的主要差异:
上图的解释:
上图的解释:
名词的解释:
Term | Description |
---|---|
Agent 代理,媒介 | An SRI agent is any master or slave device which is connected to the SRI Fabric. |
Master 主 | An SRI master device is an SRI agent which is able to initiate transactions on the SRI Fabric. |
Slave 从 | An SRI slave device is an SRI agent which is not able to initiate transactions on the SRI. It is only able to respond to transactions operations that are directed to it by the SRI Fabric. |
SRI crossbar 交叉开关 | The SRI crossbar provides the interconnects between Masters and Slaves in the same domain. The SRI crossbar includes arbitration mechanisms and error capture capabilities. |
MCI 主连接接口 | Each Master is connected via one Master Connection Interface. The SRI Fabric contains control and status registers which affect MCI priority and provide related error information. |
SCI 从连接接口 | Each Slave is connected via one Slave Connection Interface. The SRI Fabric contains control and status registers which include control and error informations related to the SCI. |
Domain 域 | An SRI domain consists of those agents which are connected to a specific SRI crossbar. There will be at least one Master (or S2S bridge acting as a Master) and at least one Slave (or S2S bridge acting as a Slave), and an instance of a crossbarproviding full or partial connectivity between all the agents in the domain. |
Arbiter 仲裁 | If two (or more) Masters attempt to access the same Slave, the arbiter provides the decisions as to the order in which Masters gain access. The order is determined by the two-level round-robin mechanism implemented in the arbiter and the configuration programmed by the user. |
拍脑袋能想出来的一般多核注意事项:
英飞凌多和单片机应用技术
一书中, 以TC2x举例:
CPU0外的其它CPU上电后会保持在HALT暂停状态, 需要通过CPU0设置它们的PC程序指针寄存器, 设置HALT相应的位, 从HALT状态切换到RUN状态.
我们打开 AURIX Development Studio, File -> New -> New AURIX Project, 新建的空工程默认就有6个Main.c文件对应6个CPU:
Cpu0_Main.c 内容默认为:
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;
void core0_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
* Enable the watchdogs and service them periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
while(1)
{
}
}
Cpu1_Main.c 内容默认为:
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
extern IfxCpu_syncEvent g_cpuSyncEvent;
void core1_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG1 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
while(1)
{
}
}
其中:
IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;
定义在CPU0的Main.c中, 在其它CPU中被引用. 一种共享内存的方法用于核间通信IfxCpu_waitEvent
该函数将一直等到所有内核在事件中都设置了它们相应的位. 该函数与IfxCpu_emitEvent
一起用于实现已配置内核之间的同步, 默认情况下,为所有内核定义IFXCPU_CFG_ALLCORE_DONE
宏Cpu0_Main.c
中 /* Wait for CPU sync event */
注释上面的地方.点灯为例, 如果一个核操作一个LED翻转, 互不干涉, 直接在各个Cpux_Main.c初始化延时翻转即可, 不存在冲突. 官方给的这个例子是3个核控制一个LED:
Cpu0_Main.c 内容(注意LED初始化放到其它CPU初始化之前):
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;
#define LED &MODULE_P13, 0 /* LED D107 */
uint16 g_turnLEDon = FALSE; /* Variable for the LED, CPU0 and CPU1 are toggling the LED depending on its state */
void core0_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
* Enable the watchdogs and service them periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
//initLED
IfxPort_setPinHigh(LED);
IfxPort_setPinMode(LED, IfxPort_Mode_outputPushPullGeneral);
//Initialize the time constants
initTime();
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
while(1)
{
if(g_turnLEDon == TRUE)
{
IfxPort_setPinLow(LED); /* Turn on the LED (LED is low-level active) */
}
}
}
Cpu1_Main.c 内容:
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
extern IfxCpu_syncEvent g_cpuSyncEvent;
#ifndef LED
#define LED &MODULE_P13, 0
#endif
extern uint16 g_turnLEDon;
void core1_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG1 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
while(1)
{
if(g_turnLEDon == FALSE)
{
IfxPort_setPinHigh(LED); /* Turn off the LED (LED is low-level active) */
}
}
}
Cpu2_Main.c 内容:
#include "Ifx_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
extern IfxCpu_syncEvent g_cpuSyncEvent;
#include "Bsp.h"
#ifndef LED
#define LED &MODULE_P13, 0
#endif
extern uint16 g_turnLEDon;
void core2_main(void)
{
IfxCpu_enableInterrupts();
/* !!WATCHDOG2 IS DISABLED HERE!!
* Enable the watchdog and service it periodically if it is required
*/
IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
/* Wait for CPU sync event */
IfxCpu_emitEvent(&g_cpuSyncEvent);
IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
while(1)
{
g_turnLEDon = !g_turnLEDon; /* Toggle the state of the global variable */
wait(TimeConst_1s);
}
}
当然, define或者全局变量的extern可以放到一个公共的头文件如Multicore.h
中, 然后所有.c包含即可.
编译运行, LED每s翻转一次状态.
欢迎扫描关注我的微信公众号, 及时获取最新文章: