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.

[参考译文] CCS/TMS320F2.8379万D:EtherCAT堆栈跳到非法ISR

Guru**** 2436040 points
Other Parts Discussed in Thread: CONTROLSUITE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/664746/ccs-tms320f28379d-ethercat-stack-jumping-to-illegal-isr

部件号:TMS320F2.8379万D
主题中讨论的其他部件:controlSUITETMDSECATCNCD379D

工具/软件:Code Composer Studio

大家好,

我正在运行由controlSUITE提供的EtherCAT堆栈,并在检查它是否正常工作后,我在RAM和闪存中应用了一些片段,以初始化并使用2个ePWM信号,2个eQEP信号和2个ADC。 但是,当我尝试从闪存执行代码时遇到了某种问题(在RAM中,它工作正常)。 它在EtherCAT堆栈的这一特定部分跳进了非法的ISR例程,而在启用上述外围设备之前,它没有这样做

默认controlSUITE程序和HW_Init()函数在RAM和闪存配置中将cmd文件排除在构建之外,以下功能不会导致任何问题:

//#######################################################################
//
//文件:etherCAT_slaver_C28x_hal.c
//
//标题:用于EtherCAT从属控制器(ESC)的C28x HAL级别功能
//
//! \addtogroup C2k_EtherCAT_adapater_examples_list
//! <H1>PDI接口测试示例</H1>
//!
//! 此文件中的功能为EtherCAT从属设备提供HAL层接口
//! 可在C2k EtherCAT适配器板上构建的应用
//!
//! HAL可以是EMIF或SPI,具体取决于所选的PDI接口
//! 或为C2k ET1100 EtherCAT适配器板配置
//!
//------------------------------------------------
//! 用于EMIF PDI的C28x寻址与TwinCat3软件地址
//! 下面使用的C28x地址是ET1100 PDI的一个单词(16b)地址
//! 接口,而Beckhoff EtherCAT文档和TwinCat3软件使用
//! 字节地址。 ET1100上的用户RAM从0x1000偏移字节开始
//! 地址。 将其除以2,以从EMIF2获得正确的16b字偏移
//! 起始地址
//!
//! EMIF PDI一次从ET1100地址空间(即)读取两个字节
//! C28x CPU可读取的最小数据大小
//------------------------------------------------
//------------------------------------------------
//! C28x寻址与SPI PDI的TwinCat3软件地址
//! 对于SPI PDI,ET1100存储空间的寻址是直接的
//! SPI PDI使用8位字符长度进行SPI读/写,但使用HAL API
//! 调整为一次读取16位,以与EMIF PDI一致。
//! 用户可以将SPI PDI修改为从ET1100一次读取/写入一个字节
//! 地址空间。 但由于C28x数据总线的宽度为16位,本示例显示了这一点
//! 16位SPI PDI也可读/写。
//!
//! 不支持在最后一个事务上读取SPI miso针脚以获取错误状态
//! 在本HAL中
//! 此HAL支持SPI模式3
//! 此HAL将忽略miso引脚上的I0和I1字节读取
//------------------------------------------------
//! \b外部连接\n
//! 用户可以将运行TWINCAT3的PC连接到EtherCAT从属设备并查看
//! ET1100的内存窗口,用于寄存器和ET1100 RAM
//!
//! \b监视变量\n
//! -使用某些ET1100寄存器填充escRegs数据结构,可以是
//! 在内存窗口中查看是否启用了HAL Test (HAL测试)。
//!
//!
//#######################################################################
//$TI发行版:C2000 EtherCAT v解决方案支持1.00 $
//$发布日期:07/2017 $
//$Copyright:
//版权所有(C) 2017 Texas Instruments Incorporated - http://www.ti.com/
//
//以源代码和二进制形式重新分发和使用,无论是否使用
//修改,但前提是满足以下条件
//满足:
//
//重新分发源代码必须保留上述版权
//注意,此条件列表和以下免责声明。
//
//以二进制形式重新分发必须复制上述版权
//注意,此条件列表和中的以下免责声明
//随提供的文档和/或其他材料
//分发。
//
//既不是德州仪器(TI)公司的名称,也不是的名称
//其贡献者可用于支持或促销衍生产品
//未经特定的事先书面许可。
//
//本软件由版权所有者和贡献者提供
//“按原样”和任何明示或暗示的担保,包括但不包括
//仅限于适销性和适用性的暗示担保
//不承担特定目的。 在任何情况下,版权都不应享有
//所有者或贡献者对任何直接,间接,附带,
//特殊,典型或后果性损害(包括但不包括
//仅限于采购替代货物或服务;无法使用,
//数据或利润;或业务中断)
//责任理论,无论是合同,严格责任还是侵权行为
//(包括疏忽或其他)因使用而产生的任何问题
//此软件的任何版本,即使已被告知可能会造成此类损坏。
//$
//#######################################################################

//
//包含的文件
//
#include "F28x_Project.h"//设备头文件和示例包括文件
#include "F2837xD_SPI.h"
包含"DCL.h"
#include "AdcSetup.h"
#include "Posspeed.h"
#include "etherCAT_slaver_C28x_hal.h"

//
//定义
//
//#define EtherCAT_stack 1 //仅在使用EtherCAT从属堆栈时使用

//
//全局变量
//
Int AdcaResult0,AdcbResult0,AdcaResult1,AdcbResult1,dc;
浮点类比1 = 0.0f;

DCL_PID pid1 = PID_DEFAULTS;
浮子rk1;
浮子yk1;
浮子lk1;
浮子uk1;
浮子荷兰1;

DCL_PID pid2 = PID_DEFAULTS;
浮子RK2;
浮子yk2;
浮子lk2;
浮子uk2;
浮子荷兰2;

//eQEP
POSSPEED QEP_POSPEED=POSSPEED_DEFAULTS;
uINT16 int1cnt = 0;
uINT16 int2cnt = 0;

float desired pos_high = 360.0 ;
FLOAT desired _pos_low = 0.0 ;
float desired _pos = 360.0 ;
long int raW_pos1,raW_pos2,raW_pos3;
长int angle_count1=0;
unsigned long int pos_init = 2147483647;//0x7fffffffffff
float gwnia1,gwnia2,gwnia3;
float ngwnia1, ngwnia2, ngwnia3;
内部目录=0;


//指向ESC内存的指针,在ESC_INITHW()中初始化
//仅用于ASYNC16 (EMIF1或EMIF2) PDI
//uint16_t *PESC;

#ifdef PDI_HAL_TEST
//用于记录ESC寄存器的调试阵列,仅用于PDI HAL测试
esc_et1100_regs_t escRegs[esc_debug_regs_length];
#endif

#ifdef interface_SPI
// SPI变量
volatile uint16_t SPI_RxData[16];//接收数据缓冲区
易失性uint16_t SPI_XmitInProgress;
#endif


//
//HAL级别函数
//
#ifndef __cplusplus

#ifdef interface_SPI
#pragma code_section (esc_readSPI,".ti.ramfunc");
#pragma code_section (esc_writeSPI,".ti.ramfunc");
#endif
#pragma code_section (esc_timerIncPerMilliSec,".ti.ramfunc");
#pragma code_section (esc_getTimer,".ti.ramfunc");
#endif

/*************************************************************************** /
//为指定的引脚设置GPyDAT寄存器位。

UINT32_t ESC_GETTimer (无效)

/C28x计时器从0xFFFFFFFF递减,而堆栈从开始理解
//增量类型。
返回~(UINT32_t)(CpuTimer0Regs.TIM.All);
}
/*************************************************************************** /
void ESC_clearTimer (void)

CpuTimer0Regs.TIM.All = 0;
}
/*************************************************************************** /
UINT32_t ESC_TIMERIncPerMilliSec (无效)

返回(UINT32_t) 20万UL;// 200MHz
}
/*************************************************************************** /
//
// EtherCAT从属堆栈的SPI HAL功能
//

//SPI peripehral寄存器指针,将根据根据选择的SPI进行初始化
//构建配置
易失性结构spi_regs *SpixRegs;

/*************************************************************************************************
*@fn esc_readSPI
*@brief函数最多可读取12个字节的数据
*
*@参数
* offset_addr -必须从中读取数据的ESC地址
* numbytes -要读取的字节数,由调用方一次限制为12个
*缓冲区-指向必须将读取数据复制到的缓冲区的指针
*-如果传递NULL,则数据被复制到SPI_RxData全局数组
*
*@返回-无
******************* /
void esc_readSPI(uint16_t offset_addr,uint16_t numbytes, uint16_t* buffer)

UINT16_t I,cmd,高级,NumWords = 0,j;
uINT16_t *buf =(uint16_t *)0;
UINT16_t读相[16];


IF ((((void *) buffer)== NULL)

buf =(uint16_t *)&SPI_RxData[0];
}
否则

buf =缓冲;
}

//为SPI xmission将地址cmd字节构建为16位字,
// SPI xmits. MSBit 1st,所以必须交换这个16b字中的字节以进行传输
//读取cmd序列的字节顺序:
//字节0:A[12:5]
//字节1:A[4:0],110b (110b是3字节cmd扩展名)
//字节2:A[15:13],CMD[2:0],00B (011b是使用WS读取的)
//字节3:FFH (等待状态)
//cmd = offset_addr & 0x1f
cmd =(offset_addr & 0x1FE0)<<3;// offset_addr[12:5]是第一个地址阶段字节,转换为高位字节
cmd ||(((offset_addr & 0x1F)<< 3)| ESC_EtherCAT_3BYTEADDR);
readphase [0]= cmd;
NumWords++;
readphase [1]=(offset_addr & 0xE000)|(ESC_EtherCAT_READ_WAIT <<10)| ESC_EtherCAT_WAIT;
NumWords++;

对于(i=2,j =0;j<numbytes;i++){
readphase [i]=(uint16_t) ESC_EtherCAT_CONTINUE;
NumWords++;
J++;
J++;
}
readphase [--i]||(ESC_EtherCAT_RDTERMINATE);//将最后一个字节设置为0xFF

对于(i = 0;i < NumWords;I++){
SpixRegs->SPITXBUF = readphase [i]和(0xFF00);
SpixRegs->SPITXBUF =((readphase [I]&(0xFF))< 8);
}
SPI_XmitInProgress = 1;

DELAY _US (10);

j =数字字节;

While (SpixRegs->SPIFFRX.bit.RXFFST <(NumWords))

ASM (" NOP");//需要12ns延迟
ASM (" NOP");
ASM (" NOP");
};
While (SpixRegs->SPIFFRX.bit.RXFFST!=(数字字节))

////忽略前两个单词(4个字节)
高级= SpixRegs->SPIRXBUF;//忽略

}

对于(I=0;(SpixRegs->SPIFFRX.bit.RXFFST!= 0);i++)

建议=(SpixRegs->SPIRXBUF)和0xFF;
buf[I]=(高级和0xFF);

建议=(SpixRegs->SPIRXBUF)和0xFF;
buf[i]|=(readval和0xFF)<8);


}
DELAY _US (5);
SpixRegs->SPIFFTX.Bit.TXFIFO;//重置Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFORESET =0;//重置FIFO指针
DELAY _US (2);
SpixRegs->SPIFFTX.bit.TXFIFO;//重新启用Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFO = 1;//重新启用FIFO操作
SPI_XmitInProgress = 0;
}


#define FIFO长度12.
/*************************************************************************************************
*@fn esc_writeSPI
*@brief函数最多可写入12字节数据
*
*@参数
* offset_addr -必须向其写入数据的ESC地址
* numbytes -要写入的字节数,由调用方一次限制为12个
* wrdata -指向必须从中将数据写入ESC的缓冲区的指针
*
*
*@返回-无
******************* /
void esc_writeSPI(uint16_t offset_addr,uint16_t *wrdata,uint16_t numbytes)

UINT16_t I,j,cmd,NumWords =0;
UINT16_t wptr =0;
uINT16_t写法[2];


//为SPI xmission将地址cmd字节构建为16位字,
// SPI xmits. MSBit 1st,所以必须交换这个16b字中的字节以进行传输
//读取cmd序列的字节顺序:
//字节0:A[12:5]
//字节1:A[4:0],110b (110b是3字节cmd扩展名)
//字节2:A[15:13],CMD[2:0],00B (110b是3字节cmd扩展)
//字节3:数据的第一字节
//cmd = offset_addr & 0x1f
cmd =(offset_addr & 0x1FE0)<<3;// offset_addr[12:5]是第一个地址阶段字节,转换为高位字节
cmd ||(((offset_addr & 0x1F)<< 3)| ESC_EtherCAT_3BYTEADDR);
writephase[0]= cmd;
NumWords++;
cmd = 0x0000;
cmd =(((offset_addr & 0xE000)|(ESC_EtherCAT_write <<10)));
cmd ||(wrdata[wptr]和0x00FF);
writephase[1]= cmd;
NumWords++;

I = 0;

SpixRegs->SPITXBUF = writephase[i]和(0xFF00);
SpixRegs->SPITXBUF =((writephase[i+]&(0xFF))<8);
SpixRegs->SPITXBUF = writephase[i]和(0xFF00);
SpixRegs->SPITXBUF =((writephase[i]&(0xFF))<<8);
}
wptr=0;
对于(j = 1;j <(数字字节-1);j+=2)

SpixRegs->SPITXBUF =(wrdata[wptr]和0xFF00);
SpixRegs->SPITXBUF=((wrddata[++wptr])和0x00FF)<8);
NumWords++;
}
IF (j ==(numbytes-1))

SpixRegs->SPITXBUF =(wrdata[wptr]和0xFF00);
NumWords++;
}

SPI_XmitInProgress = 1;
while (SpixRegs->SPIFFTX.Bit.TXFFST !=0)

DELAY _US (2);
};
SpixRegs->SPIFFTX.Bit.TXFIFO;//重置Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFORESET =0;//重置FIFO指针
DELAY _US (2);
SpixRegs->SPIFFTX.bit.TXFIFO;//重置Tx FIFO
SpixRegs->SPIFFRX.Bit.RXFIFO = 1;//重新启用FIFO操作
SPI_XmitInProgress = 0;

}
/*************************************************************************** /
uINT16_t ESC_readWordNonISR(uint16_t offset_addr)

UINT16_t数据;
色调;
esc_readSPI (offset_addr,2,&data);
EINT;
返回数据;
}
/*************************************************************************** /
uINT16_t esc_readWordISR(uint16_t offset_addr)

esc_readSPI (offset_addr,2,0);
返回(SPI_RxData[0]);
}
/*************************************************************************** /

uINT32_t ESC_readDWordNonISR (uint16_t offset_addr)

UINT32_t DWORD;

色调;
esc_readSPI (offset_addr,4,(uint16_t *)&DWORD);
EINT;
返回DWORD;
}
/*************************************************************************** /
uINT32_t esc_readDWordISR(uint16_t offset_addr)

UINT32_t DWORD;

esc_readSPI (offset_addr,4,(uint16_t *)&DWORD);

返回DWORD;
}
/*************************************************************************** /
void esc_readBlockISR(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)

uINT16_t i = 0,current_bytes = 0,last_byte = 0;
IF (numbytes和0x1)

current_bytes =(numbytes - 0x1);//偶校准
}
否则

current_bytes =数字字节;
}
而(current_bytes > 0)//输入实际上是以字节为单位

IF (current_bytes >= FIFO长度)

esc_readSPI (offset_addr,iffo_length,(uint16_t *)&pData[I]);
current_bytes == fifo_length;
I+= FIFO长度/2;//数据以16位表示
offset_addr += FIFO长度;
}
否则

esc_readSPI (offset_addr,current_bytes,(uint16_t *)&pData[I]);
offset_addr +=当前字节;
I+=当前字节/2;
current_bytes = 0;
}
}

IF (numbytes和0x1)

last_byte = esc_readWordISR(offset_addr);
pData[i]= pData[i]& 0xFF00;
pData[i]|=最后一个字节;

}

}
/*************************************************************************** /
void esc_readBlockNonISR(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)

色调;
esc_readBlockISR(pData, offset_addr, numbytes);
EINT;

}

/*************************************************************************** /
void esc_writeWordNonISR (uint16_t wrdata,uint16_t offset_addr)

色调;
esc_writeSPI (offset_addr,&wrdata,0x02);
EINT;
}
/*************************************************************************** /
void esc_writeWordISR(uint16_t wrdata,uint16_t offset_addr)

esc_writeSPI (offset_addr,&wrdata,0x02);
}
/*************************************************************************** /
void esc_writeDWordNonISR(UINT32_t wrdata, uint16_t offset_addr)

色调;
esc_writeSPI (offset_addr,(uint16_t *)&wrdata,0x04);
EINT;
}
/*************************************************************************** /
void esc_writeWordISR(UINT32_t wrdata, uint16_t offset_addr)

esc_writeSPI (offset_addr,(uint16_t *)&wrdata,0x04);
}
/*************************************************************************** /

void esc_writeBlockISR(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)

uINT16_t i = 0,current_bytes = 0;

IF (numbytes和0x1)

current_bytes =(numbytes - 0x1);//偶校准
}
否则

current_bytes =(数字字节);
}
而(current_bytes > 0)//输入实际上是以字节为单位

IF (current_bytes >= FIFO长度)

esc_writeSPI (offset_addr,(uint16_t *)&pData[i],FIFO长度);
current_bytes == fifo_length;
I+= FIFO长度/2;//数据以16位表示
offset_addr += FIFO长度;
}
否则

esc_writeSPI (offset_addr,(uint16_t *)&pData[i],current_bytes);
offset_addr +=当前字节;
I+=当前字节/2;
current_bytes = 0;
}
}

IF (numbytes和0x1)

//现在发送带有额外校准字节的最后一个字节
//请注意,我们读取相邻的字节并将其写回
esc_readSPI(offset_addr, 2,&I);
I &= 0xFF00;
i |=(pData[((numbytes-1)>>1)]和0xFF;//pData是16位指针
esc_writeSPI(offset_addr,&I, 2);
}
}
/*************************************************************************** /
void esc_writeBlockNonisr (uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)

色调;
esc_writeBlockISR(pData, offset_addr, numbytes);
EINT;
}


//------------------
//初始化SPI端口的函数
//------------------
void esc_initSPIFIFO (void)

uINT16_t m;
EALLOW;

// FIFO配置
SpixRegs->SPIFFCT.All=0x0;//将SPI置于复位状态
对于(m=0;m<3;m++);
SpixRegs->SPIFFRX.all=0x2040;// RX FIFO已启用,清除FIFO
SpixRegs->SPIFFRX.Bit.RXFFIL =16;//设置RX FIFO级别
SpixRegs->SPIFFTX.all=0xE040;// FIFO已启用,TX FIFO已释放,

// SPI配置
SpixRegs->SPIFFTX.Bit.TXFFIL =16;//设置TX FIFO级别
SpixRegs->SPICCR.bit.SPICHAR = 0x7;//0xF;//字符长度=8
SpixRegs->SPICCR.bit.CLKPOLARITY =1;//上升边缘
SpixRegs->SPICCR.bit.HS_MODE = 0;//非高速模式
SpixRegs->SPICTL.bit.SPIINTENA =1;//已启用
SpixRegs->SPICTL.bit.Talk =1;//
SpixRegs->SPICTL.bit.Master_slave =1;//主模式
SpixRegs->SPICTL.bit.CLK_PHASE =0;//添加Clk wrt SPISTEA的1/2周期延迟
SpixRegs->SPICTL.bit.OVERRUNINTENA =1;//启用了溢出中断
SpixRegs->SPISTS.all=0x0000;//清除状态位(TxBufFull,INT, Overlife)

// SpixRegs->SPIBRR.ALL = 0x63;// LSPCLK/100
ClkCfgRegs.LOSPPCN.ALL = 0x1;// 0 = SYSCLK/1 = 200m;1 = SYSCLK/2 = 100m
SpixRegs->SPIBRR.All=0x004;//波特率= LSPCLK /(SPIBRR+1)[LSPCLK=SYSCLK/4 (默认为50m])
SpixRegs->SPIFFCT.All=0x00;
SpixRegs->SPIPRI.All=0x0020;// EmuStop (EmuStop)时事务完成后停止

SpixRegs->SPIFFTX.bit.TXFFIENA = 0;//禁用TXFF INT
SpixRegs->SPIFFRX.Bit.RXFFIENA = 0;//禁用RXFF INT


SpixRegs->SPICCR.bit.SPISWRESET=1;//启用SPI

EDIS;
}

//------------------
//初始化SPIB端口的GPIO的功能
// GPIO64,GPIO65,GPIO66,GPIO63
//不用于TMDSECATCNCD379D套件
//------------------
void esc_initSPIBGpio(void)

EALLOW;
//在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
gpioCtrlRegs.GPCPUD.all &= 0xFFFFFFF8;
gpioCtrlRegs.GPBPUD.all &= 0xFFFFFFFE;

//启用SPISIMO/SPISOMI/SPICLK引脚
gpioCtrlRegs.GPCGMUX1.bit.GPIO64 = 0x3;
GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0x3;
gpioCtrlRegs.GPCGMUX1.bit.GPIO65 = 0x3;
GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 0x3;
gpioCtrlRegs.GPCGMUX1.bit.GPIO66 = 0x3;
GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 0x3;
gpioCtrlRegs.GPBGMUX2.bit.GPIO63 = 0x3;
gpioCtrlRegs.GPBMUX2.bit.GPIO63 = 0x3;

//启用SPISIMO/SPISOMI/SPICLK引脚作为异步
gpioCtrlRegs.GPCQSEL1.all || 0xF;
gpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 0x3;

EDIS;

}

//------------------
//初始化***端口的GPIO的功能
// GPIO122,GPIO123,GPIO124,GPIO125
//用于TMDSECATCNCD379D套件的功能
//------------------
void esc_initSPICGpio(void)

EALLOW;
//带有HD连接器的新控制卡
//在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
1221.23124125亿
gpioCtrlRegs.GPDPUD.ALL &= 0xC3FFFFFF;

//启用SPISIMO/SPISOMI/SPICLK引脚
gpioCtrlRegs.GPDGMUX2.bit.GPIO122 = 0x1;
gpioCtrlRegs.GPDGMUX2.bit.GPIO123 = 0x1;
gpioCtrlRegs.GPDGMUX2.bit.GPIO124 = 0x1;
gpioCtrlRegs.GPDGMUX2.bit.GPIO125 = 0x1;

gpioCtrlRegs.gPDMUX2.bit.GPIO122 = 0x2;
gpioCtrlRegs.gPDMUX2.bit.GPIO123 = 0x2;
GpioCtrlRegs.GPDMUX2.bit.GPIO124 = 0x2;
gpioCtrlRegs.gPDMUX2.bit.GPIO125 = 0x2;

//启用SPISIMO/SPISOMI/SPICLK引脚作为异步
gpioCtrlRegs.GPDQSEL2.all |= 0x03F0万;
EDIS;
}

//------------------
//初始化SPIÁ 端口的GPIO的函数
// GPIO58 (SIMOA),GPIO59 (Somia),GPIO60 (CLKA),GPIO61 (拉美经济体系)
// GPIO16,GPIO17,GPIO18,GPIO19 (注释掉)
//不用于TMDSECATCNCD379D套件
//------------------
void esc_initSPIAGpio(void)

EALLOW;
/*为所选引脚启用内部上拉*/
//用户可以启用或禁用上拉。
//这将启用指定引脚的上拉。 在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
gpioCtrlRegs.GPBPUD.bit.GPIO58 = 0;//在GPIO58上启用上拉(SPISIMO-A)
gpioCtrlRegs.GPBPUD.bit.GPIO59 = 0;//在GPIO59上启用上拉(SPISOMI-A)
gpioCtrlRegs.GPBPUD.bit.GPIO60 = 0;//在GPIO60上启用上拉(SPICLK-A)
gpioCtrlRegs.GPBPUD.bit.GPIO61 = 0;//在GPIO61上启用上拉(SPISTE-A)

/*将所选引脚的限定条件设置为仅异步*/
//这将为所选引脚选择异步(无限定条件)。

gpioCtrlRegs.GPBQSEL2.bit.GPIO58 = 3;//异步输入GPIO58 (SPISIMO-A)
gpioCtrlRegs.GPBQSEL2.bit.GPIO59 = 3;//异步输入GPIO59 (SPISOMI-A)
gpioCtrlRegs.GPBQSEL2.bit.GPIO60 = 3;//异步输入GPIO60 (SPICLK-A)
gpioCtrlRegs.GPBQSEL2.bit.GPIO61 = 3;//异步输入GPIO61 (SPISTE-A)

//使用GPIO寄存器配置SPI-A引脚
//这指定了哪些GPIO引脚将是SPI功能引脚。

//G-Mux
GpioCtrlRegs.GPBGMUX2.bit.GPIO58 = 3;//启用(SPISIMO-A)
GpioCtrlRegs.GPBGMUX2.bit.GPIO59 = 3;//启用(SPISOMI-A)
GpioCtrlRegs.GPBGMUX2.bit.GPIO60 = 3;//启用(SPISCLK-A)
GpioCtrlRegs.GPBGMUX2.bit.GPIO61 = 3;//启用(SPISTE-A)

//Mux
gpioCtrlRegs.GPBMUX2.bit.GPIO58 = 3;//启用(SPISIMO-A)
GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 3;//启用(SPISOMI-A)
GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 3;//启用(SPISCLK-A)
gpioCtrlRegs.GPBMUX2.bit.GPIO61 = 3;//启用(SPISTE-A)

EDIS;
}
/*EALLOW;(TI针对SPI-A和GPIO 16,17,18,19的旧配置)
//在SPISIMO/SPISOMI/SPICLK/SPISTE引脚上启用上拉拔
gpioCtrlRegs.gpapud.all &= 0xFFF0FFFFFFFFF;

//启用SPISIMO/SPISOMI/SPICLK引脚
gpioCtrlRegs.GPAMUX2.all |= 0x0.0055万;

//启用SPISIMO/SPISOMI/SPICLK引脚作为异步
gpioCtrlRegs.GPAQSEL2.all || 0x0.0003万F;

EDIS;
}*/

/*************************************************************************** /
void ESC_释放ET1100重置(void)

GPIO _SetupPinMux (ESC_RESET_ET1100_GPIO,GPIO _MUX_CPU1,0);
GPIO _WritePin (ESC_RESET_ET1100_GPIO,1);//释放重置
}
/*************************************************************************** /
void esc_holdET1100InReset (void)

GPIO _SetupPinMux (ESC_RESET_ET1100_GPIO,GPIO _MUX_CPU1,0);
GPIO_WritePin (ESC_RESET_ET1100_GPIO,0);//在复位中保持
}
/*************************************************************************** /
void ESC_configureLatch0GPIO (void)

//此功能将SYNC0 GPIO配置为锁存输出(输入到ESC)
GPIO_SetupPinOptions (ESC_SYNC0_GPIO,GPIO输出,GPIO上拉);
GPIO_SetupPinMux (ESC_SYNC0_GPIO,GPIO _MUX_CPU1,0);
}
/*************************************************************************** /
void ESC_configureLatch1GPIO (void)

//此功能将SYNC1 GPIO配置为锁存输出
GPIO_SetupPinOptions (ESC_SYNC1_GPIO,GPIO输出,GPIO上拉);
GPIO_SetupPinMux (ESC_SYNC1_GPIO,GPIO _MUX_CPU1,0);
}


//------------------
// ISR来处理PDI ISR
//------------------
中断void ESC_applicationLayerISR()

//调用从属堆栈ISR例程
#ifdef etherCAT_stack
PDI_ISR();
#endif
PieCtrlRegs.PIEACG.ALL |= 0x01;//发出pie ack
}

//------------------
// ISR来处理SYNC0 ISR
//------------------
中断无效ESC_applicationSync0ISR()

#ifdef etherCAT_stack
Sync0_ISR();
#endif
//XINT5,PIE 12.INT3
PieCtrlRegs.PIEACK/bit.ACK12 = 1;
}

//------------------
// ISR来处理SYNC1 ISR
//------------------
中断无效ESC_applicationSync1ISR()

#ifdef etherCAT_stack
Sync1_ISR();
#endif
//XINT4,PIE 12.INT2
PieCtrlRegs.PIEACK/bit.ACK12 = 1;
}

//------------------
//函数启用controlCARD配置上SYNC0信号的调试
//------------------
void esc_enableSync0DebugOnCCARD(void)

//用于调试SYNC0行。-以下代码将GPIO2连接到SYNC0
//内部原因是在HW板上,我们不能在HighRose连接器上的SYNC0上放置范围

//Connect SYNC0 (GPIO86)是的Input1
EALLOW;
InputXbarRegs.INPUT1SELECT = ESC_SYNC0_GPIO;//input1与GPIO113绑定

OutputXbarRegs.OUTPUT1MUX0TO15CFG.bit.MUX1 = 0x1;//INPUTXBAR1到OUTPUTXBAR1
OutputXbarRegs.OUTPUT1MUXENABLE.Bit.MUX1 = 0x1;

GpioCtrlRegs.GPAGMUX1.bit.GPIO2 = 0x01;//GPIO2到OUTPUTXBAR1
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0x01;
EDIS;
}
//------------------
//在controlCARD配置上配置SYNC0信号的功能
//------------------
void ESC_configureSync0GPIO (void)

GPIO_SetupPinOptions (ESC_SYNC0_GPIO,GPIO输入,GPIO上拉| GPIO异步);
GPIO_SetupPinMux (ESC_SYNC0_GPIO,GPIO _MUX_CPU1,0);

EALLOW;
InputXbarRegs.INPUT14SELECT = ESC_SYNC0_GPIO;//input14与XINT5绑定
PieVectorTable.XINT5_INT =&ESC_applicationSync0ISR;

XintRegs.XINT5CR.bit.Polarity = 1;//下降边缘中断
XintRegs.XINT5CR.bit.enable = 1;

PieCtrlRegs.PIEIER12.bit.INTx3 =1;//启用组12,INT3 (XINT5)
IER |= 0x0800;
EDIS;//这是禁用写入EALLOW保护寄存器所必需的

esc_enableSync0DebugOnCCARD();
}


//------------------
//函数启用controlCARD配置上SYNC0信号的调试
//------------------
void esc_enableSync1DebugOnCCARD(void)

//用于SYNC1行的调试。-以下代码将GPIO3连接到SYNC1
//内部原因是在HW板上,我们不能在HighRose连接器上的SYNC1上放置范围

//Connect SYNC1是的Input1
EALLOW;
InputXbarRegs.INPUT2SELECT = ESC_SYNC1_GPIO;//input2与SYNC1绑定

OutputXbarRegs.OUTPUT2MUX0TO15CFG.bit.MUX3 = 0x1;//INPUTXBAR2到OUTPUTXBAR2
OutputXbarRegs.OUTPUT2MUXENABLE.bit.MUX3 = 0x1;

GpioCtrlRegs.GPAGMUX1.bit.GPIO3 = 0x01;//GPIO3至OUTPUTXBAR2
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0x01;
EDIS;
}

//------------------
//在controlCARD配置上配置SYNC1信号的功能
//------------------
void esc_configureSync1GPIO (void)

GPIO_SetupPinOptions (ESC_SYNC1_GPIO,GPIO输入,GPIO上拉| GPIO异步);
GPIO_SetupPinMux (ESC_SYNC1_GPIO,GPIO _MUX_CPU1,0);

EALLOW;
InputXbarRegs.INPUT13SELECT = ESC_SYNC1_GPIO;//input13与XINT4绑定
PieVectorTable.XINT4_INT =&ESC_applicationSync1ISR;

XintRegs.XINT4CR.bit.polarity = 1;//下降边缘中断
XintRegs.XINT4CR.bit.enable = 1;

PieCtrlRegs.PIEIER12.bit.INTx2 = 1;//启用组12,INT2 (XINT4)
IER |= 0x0800;
EDIS;//这是禁用写入EALLOW保护寄存器所必需的

esc_enableSync1DebugOnCCARD();
}
/*************************************************************************** /
void ESC_resetET1100 (void)

GPIO _SetupPinMux (ESC_RESET_ET1100_GPIO,GPIO _MUX_CPU1,0);
GPIO_WritePin (ESC_RESET_ET1100_GPIO,0);//保持复位低
DELAY _US (500*1000);
GPIO _WritePin (ESC_RESET_ET1100_GPIO,1);//释放重置
DELAY _US (500*1000);
}
/*************************************************************************** /
UINT16_t ESC_ET1100EEPROMLoadedCheck (无效)

uINT16_t ii = 0;
GPIO_SetupPinMux (ESC_EEPROM_LOADD_GPIO,GPIO _MUX_CPU1,0);
while (!gPIO_ReadPin (ESC_EEPROM_LOADD_GPIO))

DELAY _US (500*1000);
II++;
如果(ii > 10)
中断;
}
如果(ii > 10)
返回0;
否则
返回1;
}

/*************************************************************************** /
void ESC_passFailSignalSetup (void)

//注意:-使用EMIF1时不调用此功能,因为存在
//与GPIO31和GPIO34与EMIF1信号和LED冲突
//因此,对于2.0 ,用户只知道是否有错误
//两个LED (GPIO31和GPIO34高或低始终意味着没有错误亮起
// Launchpad XL 2.0)

GPIO_SetupPinMux (34,GPIO _MUX_CPU1,0);
GPIO_SetupPinMux (31,GPIO _MUX_CPU1,0);

GPIO_SetupPinOptions (34,1,GPIO _OPENDRAIN | GPIO _上拉);
GPIO_SetupPinOptions (31,1,GPIO _OPENDRAIN | GPIO _上拉);

//GPIO34和GPIO31处于高位-表示无错误
//默认情况下,保持GPIO31和GPIO34低以供通过
GpioDataRegs.GPADAT.bit.GPIO31 = 1;
GpioDataRegs.GPBDAT.bit.GPIO34 = 1;

}
/*************************************************************************** /
void esc_signalFail (void)

//将GPIO34和GPIO31切换为FAIL
GpioDataRegs.GPBTOGLE.bit.GPIO34 = 1;
GpioDataRegs.GPATOGLE.bit.GPIO31 = 1;
DELAY _US (10 * 1000);
}
/*************************************************************************** /
void esc_signalPass (void)

//保持GPIO31和GPIO34低通
GpioDataRegs.GPADAT.bit.GPIO31 = 1;
GpioDataRegs.GPBDAT.bit.GPIO34 = 1;

DELAY _US (500 * 1000);
}
//------------------
// ISR来处理EPWM1 ISR
// prdTick - EPWM1每4个QCLK计数(一个周期)中断一次
//------------------
中断无效epwm1_isr (无效)

IF (int1cnt == 2)//10kHz控制环路频率

EALLOW;
//取消注释以下行,以便读取第三个编码器的值
//------------------
////读取第三个编码器
////读取eQEp的原始值
qep_posspeed.calc(&qep_posspeed);
//
////读取原始位置eQEP3
// if ((unsigned long int) qep_posspeed.raW_pos3 > pos_init)
// raW_pos3 =(无符号长整型) qep_posspeed.raW_pos3 - pos_init;
//其他
// raW_pos3 =-(pos_init -(无符号长int) qep_posspeed.raW_pos3);
// gwnia3 = 360.0f *(raW_pos3 * 8.0f * 26.0f)
//(2000.0f * 343.0f * 48.0f);//2000行
//------------------

//控制电机1膝部(BLDC)

//读取第一个编码器
//读取eQEp的原始值
qep_posspeed.calc(&qep_posspeed);

//读取原始位置eQEP1
如果(unsigned long int) qep_posspeed.raW_pos1 > pos_init)
raW_pos1 =(无符号长整型) qep_posspeed.raW_pos1 - pos_init;
否则
raW_pos1 =-(pos_init -(无符号长int) qep_posspeed.raW_pos1);

angle_count1=raW_pos1;
//将原始值转换为度
gwnia1 = 360.0f *(raW_pos1 * 8.0f * 26.0f)/(2000.0f * 343.0f * 48.0f);

//标准化gwnia1的值
ngwnia1 =(gwnia1 * 1.0f)/ 360.0f;

//运行PID控制器
uk1 = dcl_runPID_c4(&pid1, rk1, ngwnia1, lk1);

//设置方向
如果(uk1 >= 0.0f)
GPIO写入引脚(dir1_GPIO,0);
否则

GPIO写入引脚(dir1_GPIO,1);
uk1 =-uk1;
}

//更新PWM占空比
//EPwm1Regs.CMPA.bit.CMPA =(1.0f - uk1)* SP;
EPwm1Regs.CMPA.bit.CMPA =(1.0f-SP*LED_Frequency)* 0.01 ;

int1cnt = 0;
}
int1cnt++;

EDIS;
//清除此计时器的INT标志
EPwm1Regs.ETCLR.bit.INT = 1;
//
//确认此__interrupt以接收来自组3的更多__interrupts
//
PieCtrlRegs.PIEACG.ALL = PIEACK_Group3;

}
//------------------
// ISR来处理EPWM2 ISR
// prdTick - EPWM2每4个QCLK计数(一个周期)中断一次
//------------------
中断无效epwm2_isr(void)

IF (int2cnt == 2)//10kHz控制环路频率

EALLOW;
//控制电机2 Hip (刷式直流)

//读取eQEp的原始值
qep_posspeed.calc(&qep_posspeed);
如果(unsigned long int) qep_posspeed.raW_pos2 > pos_init)
raW_pos2 =(无符号长整型) qep_posspeed.raW_pos2 - pos_init;
否则
raW_pos2 =-(pos_init -(无符号长int) qep_posspeed.raW_pos2);

//将原始值转换为度
gwnia2 = 360.0f *(raW_pos2 * 12.0f * 26.0f)/(2000.0f * 637.0f * 48.0f);

//标准化gwnia2的值
ngwnia2 =(gwnia2 * 1.0f)/ 360.0f;

//运行PID控制器
uk2 = DCL_runPID_C4(&pid2, Rk2, ngwnia2, lk2);

//设置方向
如果(uk2 >= 0.0f)
GPIO写入引脚(dir2_GPIO,0);
否则

GPIO写入引脚(dir2_GPIO,1);
uk2 =-uk2;
}

//更新PWM占空比
EPwm2Regs.CMPA.bit.CMPA =(1.0f - uk2)* SP;

//重置中断计数器
int2cnt = 0;

}
int2cnt++;

EDIS;

//清除此计时器的INT标志
EPwm2Regs.ETCLR.bit.INT = 1;
//
//确认此__interrupt以接收来自组3的更多__interrupts
//
PieCtrlRegs.PIEACG.ALL = PIEACK_Group3;

}
//------------------
//处理ADC信号的功能
//------------------
void ReadAnalog (void)

//
//转换,等待完成并存储结果
//通过软件ADCA立即开始转换
//
AdcaRegs.ADCSOCFRC1.ALL = 0x0003;//SOC0和SOC1

//
//立即通过软件ADCB开始转换
//
AdcbRegs.ADCSOCFS2 = 0x0003;//SOC0和SOC1

//
//等待ADCA完成,然后确认标志
//
while (AdcaRegs.ADCINTFLG.bit.ADCINT1 ==0)

ADcaRegs.ADCINTFLGCLL.Bit.ADCINT1 = 1;

//
//等待ADCB完成,然后确认标志
//
while (AdcbRegs.ADCINTFLG.bit.ADCINT1 ==0)

ADcbRegs.ADCINTFLGCLL.bit.ADCINT1 = 1;

//
//存储结果
//
AdcaResult0 = AdcaResultRegs.ADCRESULT0;
AdcaResult1 = AdcaResultRegs.ADCRESULT1;

AdcbResult0 = AdcbResultRegs.ADCRESULT0;
AdcbResult1 = AdcbResultRegs.ADCRESULT1;

}
/*************************************************************************** /
void esc_initHW(void)

#ifdef闪存
//将时间关键代码和闪存设置代码复制到RAM
// RamfuncsLoadStart,RamfuncsLoadEnd和RamfuncsRunStart
//符号由链接器创建。 请参阅链接程序文件。
memcpy (&RamfuncsRunStart,&RamfuncsLoadStart,(UINT32_t)&RamfuncsLoadSize);
#endif


InitSysCtrl();

//仅在从闪存运行时使用
//请注意,变量flash由编译器定义

#ifdef闪存
//呼叫闪存初始化以设置闪存等待
//此功能必须驻留在RAM中
InitFlash();//调用闪存包装程序init函数
#endif //(闪存)


//
//启用PWM1,PWM2和PWM3
//
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;
CpuSysRegs.PCLKCR2.bit.EPWM2 = 1;

//
//清除所有__interrupts并初始化PIE矢量表:
//禁用CPU __interrupts
//
色调;
//将PIE控件寄存器初始化为其默认状态。
//默认状态是禁用所有PIE中断和标志
//被清除。
//此函数位于F2837xD_PIECTRL.c文件中。
InitPieCtrl();

//禁用CPU中断并清除所有CPU中断标志:
EALLOW;
IER = 0x0000;
IFR = 0x0000;
EDIS;

//使用指向外壳中断的指针初始化PIE矢量表
// GService例程(ISR)。
//这将填充整个表,即使中断也是如此
//在本例中不使用。 这对于调试非常有用。
// shell ISR例程位于F2837xD_DefaultIsr.C.中
//此函数位于F2837xD_PieVect.C.中
InitPieVectorTable();

EALLOW;
//初始化GPIO:
//此示例函数可在F2837xD_GPIO.c文件和中找到
//说明了如何将GPIO设置为其默认状态。
//
此示例跳过InitGpio();//
GPIO_SetupPinMux (dir1_GPIO,GPIO _MUX_CPU1,0);
GPIO设置插件选项(dir1_GPIO,GPIO输出,GPIO推送);
GPIO_SetupPinMux (dir2_gPIO,gPIO_MUX_CPU1,0);
GPIO_SetupPinOptions (dir2_gPIO,gPIO_OUTPUT,gPIO_PushPull);

//
//在这种情况下,仅初始化eQEP1,2,3和ePWM1,2的GPIO
//此函数位于F2837xD_eQEP.c中
//
InitEQep1Gpio();
InitEQep2Gpio();
InitEQep3Gpio();
Initepwm1gpio();
Initepwm2gpio();

InitCpuTimers();

//------------------

//TxCnt=0;
SPI_XmitInProgress = 0;

#ifdef use_spia
SpixRegs = SpiaRegs (&S);
esc_initSPIAGpio();
#Elif use_spic
SpixRegs = SpicRegs(&S);
esc_initSPICGpio();
#否则
SpixRegs = SpibRegs (&S);
esc_initSPIBGpio();
#endif
esc_initSPIFIFO();


//本示例中使用的中断被重新映射到
//此文件中找到ISR函数。
EALLOW;//这是写入EALLOW保护寄存器所必需的
PieVectorTable.XINT1_INT =&ESC_applicationLayerISR;
PieVectorTable.EPWM1_INT =&epwm1_ISR;
PieVectorTable.EPWM2_INT =&epwm2_isr;
EDIS;//这是禁用写入EALLOW保护寄存器所必需的
//初始化eQEP外设
qep_posspeed.init(&qep_posspeed);

//
//配置ADC并将其打开
//
CpuSysRegs.PCLKCR13.bit.ADC_A = 1;
配置ADC();

//
//为软件转换设置ADC
//
SetupADCSoftware();

//初始化ePWM外设
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
initEpwm();
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;

//从ET1100配置外部中断
EALLOW;
InputXbarRegs.INPUT4SELECT = ESC_SPI_INT_GPIO;
GPIO_SetupPinOptions (ESC_SPI_INT_GPIO,GPIO输入,GPIO上拉| GPIO异步);

XintRegs.XINT1CR.bit.polarity = 0x0;//下降边缘中断
XintRegs.XINT1CR.bit.enable =1;
//EDIS;

//
//启用连接到EPWM1-3 INT的CPU INT3:
//
IER |= M_INT3;

//
//在PIE中启用TINT0:组3 __interrupt 1
//
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
//PieCtrlRegs.PIEIER3.bit.INTx3 = 1;

//启用此示例所需的中断
PieCtrlRegs.PIECTRL.bit.ENPIE =1;//启用PIE块
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;//启用组1,INT4 (XINT1)

IER || 0x01;//启用CPU INT1
EINT;//启用全局中断
ERTM;//启用全局实时__interrupt DBGM

ESC_passFailSignalSetup();
EALLOW;
//CpuTimer0Regs.tcr.bit.tie = 1;
CpuTimer0Regs.tcr.bit.ts = 0;//开始计时器

ESC_configureSync0GPIO ();
ESC_configureSync1GPIO ();
// esc_configureLatch0gPIO()
// esc_configureLatch1gPIO();

IF(!ESC_ET1100EEPROMLoadedCheck())

// EEPROM加载失败
//信号故障
同时(1)

//失败
esc_signalFail ();
DELAY _US (500 * 1000);
}
}
rk1 = 0.0f;//设定值为0度
RK2 = 0.0f;
//delay_US(2*100万);//wait for 2 sec

}
/*************************************************************************** /

您是否有任何线索,为什么它仅在通过闪存执行时导致此问题?

提前感谢您的参与

Stamatis

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Stamatis,
    是从RAM工作,但不是从闪存工作。 从闪存进行测试时,您已将问题解决到导致问题的功能。 您是否执行了程序集步进并查看函数调用的位置是否具有该函数的正确程序集?

    假设每次运行时都发生问题,当您尝试从闪存执行时,这必须与应用程序链接相关。 您可能希望从RAM运行该函数,但这不包括在.TI.ramfuns中,因此不能从闪存复制到RAM? 要从RAM执行的任何函数都必须包含在.TI.ramfuncs指令中,如ESC_readSPI函数。

    将调试指向链接器命令文件,然后检查应加载此函数的应用程序的映射文件,并查看正在发生的情况。


    此致
    Santosh Athuru
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Santosh先生,

    1)首先,当我构建项目时,唯一出现的警告是“警告#1.0247万-D:创建输出节“dclfuns”而不包含节”。 我认为这是问题的根源! 我正在通过DCL库的DCL_PID_C4.ASM运行PID控制器

    2)其次,正如我在前面的评论中指出的那样,导致ISR例程非法的功能位于EtherCAT堆栈中。 但是,独立EtherCAT堆栈的闪存配置不会触发非法ISR。 相反,现在我添加了一些外围设备,就产生了这种情况。

    3)关于您的第一个问题,是的,我进入了代码,每次信道=3时,以下函数都会发生非法ISR

    void DisableSyncManChannel(UINT8通道)

    UINT16偏移;
    //寄存器0x806仅可从PDI读取=>写入0有效
    VARVOLATILE UINT16 smStatus = SM_setting_PDI_disable;
    OFFSET =(ESC_SYNCMAN_ACTIVE_OFFSET +(SIZEOF_SM_REGISTER*CHANNEL))

    HW_EscWriteWord (smStatus,Offset);

    /*等待直到SyncManager被禁用*/


    HW_EscReadWord (smStatus, Offset);
    } While (!(smStatus & SM_Setting_PDI_disable);
    }

    4)我注意到ESC_readSPI , ESC_writeSPI, ESC_timerIncPerMilliSec和 ESC_getTimer包含在.TI.ramfuns指令中的部分,但我不确定为什么会出现这种情况。 为什么需要从RAM执行这些功能? 如何指定需要从RAM执行应用程序的哪些功能? 我假定中断ISR不需要从ram执行。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Stamatis,

    1)首先,当我构建项目时,唯一出现的警告是“warning #1.0247万-D: creating output section "dclfuns" without a sections”(警告#1.0247万-D:创建输出节“dclfuns”而不包含节)。 我认为这是问题的根源! 我正在通过DCL库的DCL_PID_C4.ASM运行PID控制器

    在上面,是的,它看起来是你不想要的。 检查映射文件并查看放置dclfunctions的位置。 看起来您已经声明了dclfuns,但链接程序命令文件不会指示链接程序将此部分放在任何位置。 请更正链接程序命令文件。

    在#2和#3>上,因此函数对通道1和2正确执行至少2次, 但当它被调用通道3时,它会产生iTRAP。如果你能找到函数中发生的确切问题所在,并且这个函数是否完全从闪存执行,我想不会 此函数可能正在调用从RAM运行的函数,该RAM是否被任何其他中断损坏?

    您需要调试iTRAP发生的位置和原因。当CPU获取非法指令时,iTRAP发生,因此您需要调试确切的位置以及发生这种情况的原因? 是因为您没有足够的堆栈,函数没有返回到它必须执行的位置,还是RAM损坏?

    on #4>通常,我们将时间关键函数放在RAM中,并从RAM中运行。 由应用程序决定。 在我们的参考代码中,我将SPI读/写设置为从RAM执行,因为我希望驱动程序中插入的NOP具有可预测的延迟。

    此致
    Santosh Athuru

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,

    1)检查内存分配窗口,我可以看到dclfuncs被放置在RAMM0中(参见缓存图像)。  

    我尝试通过在2837x_flash_lnk_CPU1.cmd的节组中添加以下代码来更正链接器文件,但仍收到一些错误,如下图所示。 我做错了什么?

    2)和3)我认为ESC_READ和ESC_WRITE导致了非法的ISR例程,可能是因为我在10kHz周期中定义了epwm1_ISR和epwm2_ISR例程。 但我不确定,因为每次进入代码时,它不会在相同点触发。 我认为问题在于cmd文件中的dclfuns定义。  

    4)所以我一定要把 DCL_runPID_C4放在RAM上,因为它对我的应用程序非常重要。 是通过添加来实现的  

    #pragma code_section (DCL_runPID_C4,".TI.ramfunc");在etherCAT_SLAN_C28x_hal.c中,还是我需要执行更多操作? 根据我在类似文章中读到 的内容,我需要将dclfuns加载到闪存中,但在引导时将其复制到RAM,以便从RAM执行。 但是,如果我正确定义了dclfuns,我是否需要 #pragma code_section (DCL_runPID_C4,“.TI.ramfunc”)声明?

    再次感谢,

    Stamatis

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Stamatis,

    谢谢,是的,请将DCL函数放在.TI.ramfuns部分,只需遵循 ESC_readSPI使用的语法,查看它是否起作用。 如果使用.TI.ramfuns,则不必专门为此编辑链接程序命令文件,因为提供的文件处理此部分。 现在,它解决了之后,请花时间了解ram函数的链接器命令文件和main()中用于将函数从Flash移动到RAM的memcpy。

    此致

    Santosh Athuru

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Santosh先生,

    我用以下几行更改了链接器闪存文件,现在似乎工作正常。

    dclfuncs :{} load=flashd,run=RAMD0,table(BINIT)
    binit :{}> FLASHD

    现在我想问您的是,我已经定义了要在闪存中加载并从ram运行的dclfuns,我是否需要在我的堆栈中添加以下行,或者是否已经为所有控制功能指定了适当的行? 因为现在整个DCL funcs部分被声明为从RAM运行。

    #pragma code_section (DCL_runPID_C4,".TI.ramfunc");

    作为记录,我还定义了从RAM运行的控制ISR例程,因为它是我的应用程序的重要组成部分。

    再次感谢

    Stamatis  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Stamatis,
    谢谢。 如果您按照 建议使用#pragma,则DCL_runPID_C4将被放置在“.TI.ramfunc”部分,并且TI示例代码将其从main()中的闪存与参考代码中的其他TI函数一起复制到RAM中。

    根据下面的代码,您似乎正在使用链接器生成的复制表来处理dclfuns。 因此,如果使用 #pragma 或.sect将DCL_runPID_C4放在dclfuns部分中,则需要将其重新放在.TI.ramfunc中。

    dclfuncs :{} load=flashd,run=RAMD0,table(BINIT)
    binit :{}> FLASHD

    TI.ramfunc是另一种更简单的方法,无需使用链接器生成的复制表,并且参考代码显示其用法。

    如果您有足够的RAM,最好像您那样将ISR移动到RAM。

    希望能回答您的问题,如果您需要进一步澄清,或者如果上述问题未完全回答,请告诉我。

    此致
    Santosh Athuru
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复,Santosh先生,

    我只是对以下观察有点困惑

    "根据下面的代码,您似乎正在使用链接程序生成的复制表来处理dclfuns。 因此,如果使用 #pragma 或.sect将DCL_runPID_C4放在dclfuns部分中,则需要将其重新放在.TI.ramfunc中。"

    您的意思是“我不需要再将它放在.TI.ramfunc中”吗? 因为我确实在汇编语言中使用.sect命令将DCL_runPID_C4函数放在了dclfuns部分,并且正如我在前面的消息中所指定的那样,我已经将此部分分配给闪存并从RAM运行。

    谢谢你

    Stamatis

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Stamatis,
    对,如果已经将DCL_runPID_C4放置在dclfuns部分,并且正在创建一个复制表,并且在调用函数之前在main中使用copy_in,则不需要使用.ti.ramfunc方法。

    但是,解决方案似乎没有必要,您只需将DCL_runPID_C4放在.TI.ramfuns中,不更改链接程序命令文件,也不包括其他复制函数。 TI提供的参考代码已负责在main条目处复制RAM函数。

    您可以自由选择适用于您的应用程序的方法。


    此致
    Santosh Athuru
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Santosh先生,

    最初这就是我试图这样做的原因。 将DCL_runPID_C4放入TI.ramfunc中,并保持链接程序文件的状态,但这是导致跳到非法ISR的原因。 现在,我告诉您,我正在刷新程序,没有任何问题,方法是在项目的闪存链接器文件的末尾添加以下行

    dclfuncs :{} load=flashd,run=RAMD0,table(BINIT)
    binit :{}> FLASHD

    非常感谢您的支持

    此致

    Stamatis