大家好!
我的 F28379D MCU 有问题。 问题与 CPU1和 CPU2通信有关。 我将向您发送两个内核的程序(见下文)。
程序非常简单(在代码中、有捷克语的注释、您可以忽略它们)、CPU1请求 CPU2提供数据、CPU2将它们放入消息 RAM 中、CPU1通过 UART 打印它们。 如果第40行的循环延迟形式存在延迟、则可以正常工作、但如果我将其删除、则 UART 输出会发送随机长度的随机数据垃圾。
我不知道为什么拖延如此重要。 我添加了要求 CPU2引导状态的条件、清除了标志32和0、但没有变化。 只有变化是延迟(延迟时间由我随机设置、可能会更短)。
您更容易看到问题的方法是将其加载到 F28379D launchpad 中、并查看第40行上环路延迟存在或注释掉时的差异。 将 COM 端子连接到器件时、您应该会看到该行为。
请、您能给我一个建议、它的行为为什么如此以及如何解决它、这样我就不会在代码中使用随机延迟?
非常感谢您的帮助。
Vojtech Skrivanek
MainCPU1.c:
// Included Files
#include "F2837xD_Ipc_drivers.h"
#include "pin_map.h"
#include "sci.h"
#include "gpio.h"
void Cpu2Start()
{
// cekej, dokud neni CPU2 spusteno (referencni manual kap. 4.10.11.3)
while ((IpcRegs.IPCBOOTSTS & C2_BOOTROM_BOOTSTS_SYSTEM_READY) != C2_BOOTROM_BOOTSTS_SYSTEM_READY);
// cekej, dokud nejsou CPU2 IPC priznaky 0 a 31 dostupne
while ((IpcRegs.IPCFLG.bit.IPC0 == 1U) && (IpcRegs.IPCFLG.bit.IPC31 == 1U));
// nastaveni startovaciho rezimu CPU2 (referencni manual kap. 4.10.8.2)
IpcRegs.IPCBOOTMODE = C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH;
// prikaz na provedeni noveho startu programu CPU2 (referencni manual kap. 4.10.8.2)
IpcRegs.IPCSENDCOM = BROM_IPC_EXECUTE_BOOTMODE_CMD;
// nastaveni priznaku, aby CPU2 provedlo prikaz (referencni manual kap. 4.10.8.1 a
// TMS320F2838x Real-Time Microcontrollers With Connectivity Manager kap. 5.5.2 a 5.7.2
IpcRegs.IPCSET.all = 0x80000001U;
}
// Main
void main(void)
{
Cpu2Start();
// povoli hodinovy signal pro SCIA
EALLOW;
CpuSysRegs.PCLKCR7.bit.SCI_A = 1U;
EDIS;
// nastavi GPIO 42/43 jako TX a RX pro UART
GPIO_setPinConfig(GPIO_42_SCITXDA);
GPIO_setPinConfig(GPIO_43_SCIRXDA);
for(int x = 0U; x < 20000U; x++);
// vstupni frekvence je f_intosc2 (10 MHz) / LSPCLK (4) = 2,5 MHz
SCI_setConfig(SCIA_BASE, 2500000U, 9600U, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE));
uint8_t* messageRamIn = (uint8_t*)0x03F800U;
// posli preruseni 0 pro CPU2
IpcRegs.IPCSET.bit.IPC0 = 1U;
// cekej na potvrzeni od CPU2
while(IpcRegs.IPCFLG.bit.IPC0 == 1U);
// odesli data o dane delce z RAM
SCI_writeCharArray(SCIA_BASE, &messageRamIn[IpcRegs.IPCRECVADDR], IpcRegs.IPCREMOTEREPLY);
// Loop Forever
for(;;)
{}
}
MainCPU2.c:
// Included Files
#include "F2837xD_Ipc_drivers.h"
#include "hw_ints.h"
#include "interrupt.h"
#include "stdio.h"
#include "string.h"
// ukazatel na zacatek message RAM
uint8_t* messageRamOut = (uint8_t*)0x03F800U;
// data
const char data[] = "Data prenesena z CPU2 do CPU1 pomoci Message RAM";
__interrupt void IPC_ISR0()
{
uint8_t datovyPosun = 15U;
memcpy(&messageRamOut[datovyPosun], data, strlen(data));
IpcRegs.IPCSENDADDR = datovyPosun;
IpcRegs.IPCLOCALREPLY = strlen(data);
// vynuluj priznak preruseni
IpcRegs.IPCACK.bit.IPC0 = 1U;
// vymaze priznak preruseni skupiny 1
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
// Main
void main(void)
{
// globalne vypne preruseni jadra
DINT;
// Incializuje radic preruseni
Interrupt_initModule();
// povoli linku 1 preruseni jadra
Interrupt_enableInCPU(INTERRUPT_CPU_INT1);
// povoli preruseni IPC_0
Interrupt_enable(INT_IPC_0);
// zaregistruje funkci do vektoru preruseni pro IPC_0
Interrupt_register(INT_IPC_0, IPC_ISR0);
// globalne povoli preruseni jadra
EINT;
// Loop Forever
for(;;)
{
}
}