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.

[参考译文] RTOS/TMS320F28377S:SYS-BIOS 上的 CANbus 交叉消息有问题

Guru**** 2487425 points
Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/790124/rtos-tms320f28377s-problem-with-canbus-interrup-message-on-sys-bios

器件型号:TMS320F28377S
主题中讨论的其他器件:C2000WARE

工具/软件:TI-RTOS

你(们)好

我通过 CAN 中断的控制程序有问题、我可以在电路板上发送 CAN 消息并从 ARM debian 获取

但是当我将消息从 debian 发送到 f28377时、它不起作用

此代码如下所示

main.c

/*
=== main.c ======
*/

#include 

#include 

#include 
#include 
#include 
#include 

#include 

#include "F28x_Project.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ca.h"
#include "driverlib/ca.h"

#define CANRXA 70
#define CANTXA 71
#define MUXMODE 5

#define LED_BLUE 13
#define LED_RED 12

#define on 0
#define off 1

#define MSG_DATA_LENGTH 8
#define SCI_MSG_DATA_LENGTH 200
#define TX_MSG_OBJ_ID 1
#define RX_MSG_OBJ_ID 1 //为客户端

// CAN ID 设置 ID //
int CAN_ID = 0x000; //

volatile uint32_t txMsgCount = 0;
volatile uint32_t rxMsgCount = 0;
volatile uint32_t errorFlag = 0;
unsigned char txMsgData[char_data_length];
unsigned rxRXMsgData[char_data_length];
tCANMsgObject sTXMSG Message;tCANMSG Message
;tCANMSG 对象 CANMSG 对象 CANMSG 对象;CANMSG CANMSG
volatile bool dataRecibed = false;
bool mErrorFlag = false;

void initComponent();
void clear_CAN_TX (void);
void print_message();

/*
=== HwiFxn ====
*/

void canaISR (UArg arg)
{
if (dataRecibed == true){
GPIO_WritePin (LED_BLUE、OFF);
dataReciped == false;
}
否则{
GPIO_WritePin (LED_BLUE、ON);
dataReciped == true;
}
}

/*
=== myIdle ======
*/

void myIdleFxn (void){
while (1){
GPIO_WritePin (LED_RED、ON);
Task_sleep (100);
GPIO_WritePin (LED_RED、OFF);
Task_sleep (100);
}
}

/*
=== main ====
*/

int main(){
/*
*使用 ROV->SysMin 查看循环缓冲区中的字符
*
initComponent();
GPIO_WritePin (LED_BLUE、OFF);
GPIO_WritePin (LED_RED、OFF);
system_printf ("enter main()\n");

BIOS_start();/*不返回*/
return (0);
}

void initComponent(){
InitSysCtrl();
InitGpio();

GPIO_SetupPinMux (LED_BLUE、GPIO_MUX_CPU1、0);
GPIO_SetupPinOptions (LED_BLUE、GPIO_OUTPUT、GPIO_PushPull);
GPIO_SetupPinMux (LED_RED、GPIO_MUX_CPU1、0);
GPIO_SetupPinOptions (LED_RED、GPIO_OUTPUT、GPIO_PushPull);

GPIO_SetupPinMux (CANRXA、GPIO_MUX_CPU1、MUXMODE);//GPIO70 - CANRXA
GPIO_SetupPinOptions (CANRXA、GPIO_INPUT、GPIO_异 步);
GPIO_SetupPinMux (CANTXA、GPIO_MUX_CPU1、MUXMODE);//GPIO71 - CANTXA
GPIO_SetupPinOptions (CANTXA、GPIO_OUTPUT、GPIO_PushPull);

CANInit (CANA_base);
CANClkSourceSelect (CANA_base、0);// 500kHz CAN 时钟
CANBitRateSet (CANA_base、200000000、50000);
CANIntEnable (CANA_base、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

sTXCANMessage.ui32MsgID = CAN_ID;
sTXCANMessage.ui32MsgIDMask = 0;
sTXCANMessage.ui32Flags = 0;
sTXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
sTXCANMessage.pucMsgData = txMsgData;

sRXCANMessage.ui32MsgID = CAN_ID;
sRXCANMessage.ui32MsgIDMask = 0;
sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
sRXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
sRXCANMessage.pucMsgData = rxMsgData;

CANMessageSet (CANA_base、RX_MSG_OBJ_ID、&sRXCANMessage、MSG_OBJ_TYPE_RX);
CANEnable (CANA_base);
}

void clear_CAN_TX (void){
int i;
for (i = 0;i < MSG_DATA_LENGTH;i++){
txMsgData[i]= 0;
}
}

//结束文件// 

app.cfg

VAR Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
var Main = xdc.useModule('xdc.runtime.Main');
var SysMin = xdc.useModule('xdc.runtime.SysMin');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');

var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Task = xdc.useModule('ti.sysbios.knl.Task');

var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
VAR Boot = xdc.useModule('ti.catalog.c2800.initF2837x.Boot');
var Idle = xdc.useModule('ti.sysbios.knl.Idle');

/*
取消注释此行以全局禁用断言。
*所有模块继承'库'模块的默认值。 您
*可以使用 Module.common$按模块覆盖这些默认值。
*禁用断言将节省代码空间并提高运行时性能。
Defaults.common$.diags_ASSERT = Diags.always_off;
*/

*
取消注释此行以防止模块名称加载到目标上。
*模块名称字符串放置在.const 段中。 将此
*参数设置为 false 将节省.const 段中的空间。 错误和
*断言消息将包含"未知模块"前缀、而
不是*实际模块名称。
*/
Defaults.common$.namedModule = false;

/*
最小化系统中的退出处理程序数组。 System 模块包括
*一组函数,这些函数在 System_atexit()中注册,
*由 System_exit()调用。
//
System.maxAtexitHandlers = 4;

/*
取消注释此行以禁用错误打印功能。
*禁用时,我们会丢失错误信息,因为
*不打印错误。 如果
*由于 Error_print()函数
*调用 System_printf(),禁用 raiseHook 将节省一些代码空间。
error.raiseHook =空;
*/

/*
取消注释此行以防止*在
目标上加载错误、断言和日志字符串。 这些字符串放置在.const 段中。
*将此参数设置为 false 将节省.const 段中的空间。
*错误、断言和日志消息将打印原始 ID 和 args、而不是
*格式化的消息。
//
text.isLoaded = false;

//
*取消注释此行以在
程序退出时禁用 SysMin *的字符输出。 SysMin 向循环缓冲区写入字符。
*可以使用 ROV 中的 SysMin Output 视图查看该缓冲器。
//
SysMin.flushAtExit = false;

//
* BIOS 模块将为系统创建默认堆。
*指定此默认堆的大小。
//
bios.heapSize = 0x0;

//系统堆栈大小(由 ISR 和 Swi 使用)*/
Program.stack = 0x100;

// System_printf ()的循环缓冲区大小*/
sysmin.bufSize = 128;

//
*为整个系统创建并安装记录
器*/
var logerBufParams = new LoggerBufParams (

var LoggerBufParf);var loggerfParams = 4.buffs (创建并安装记录器);var loggerBufParfParams = loggerfParf4.
Defaults.common$.logger = logger0;
Main.common$.diags_INFO = Diags.RUNTIME_ON;

System.SupportProxy = SysMin;

/*
构建自定义 BIOS 库。 自定义库将小于
*预编译的"已检测"(默认)和"未检测"库。
*
* BIOS.logsEnabled 参数指定
是否在此自定义构建的 BIOS 中启用日志记录*。 RTA 和
* UIA 分析工具使用这些日志。
*
* BIOS.sertsEnabled 参数指定 BIOS 代码是否
*包括 assert()检查。 将此参数设置为"false"将生成
*更小、更快的代码、但建议
在*早期开发中启用断言、因为断言()检查将捕获大量编程
*错误(无效参数等)
//
BIOS.libType = BIOS.LibType_Custom;
BIOS.logsEnabled = true;
BIOS.assertsEnabled = true;

//
*创建任务。 'taskFxn'函数可在 main.c 中找到。

var taskParams = new Task.Params ();
var task = Task.create ("&taskFxn"、taskParams);
*
///BIOS.cpufreq.lo = 200000000;
Main.common$.diags_STATUS = Diags.Runtime_off;
Boot.DataFlashWaitStates = true;taskLocks
=
true;configureBoot.enableCache = true;enableBoot.configureFlashClocks = true;
boot.SPLLIMULT = 40;
boot.OSCCLKSRCSEL = Boot.OSCCLK_INTOSC2;
Boot.SYSCLKDIVSEL = 1;
//BIOS.cpufreq.hi = 0;
BIOS.cpufreq.lo = 200000000;

var hwi0Params = new Hwi.Params ();
hwi0Params.instance.name ="hwiCANA";
hwi0Params.enableInt = true;
Program.global.hwiCANA = Hwi.create (100、"&canaISR"、 hwi0Params);

Idle.addFunc ("&myIdleFxn");

我的目标是当我向 f28377发送 CAN 消息时,它应该打开/关闭蓝色 LED (GPIO 13)。

空闲功能可以正常工作

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您能看到堆栈使用情况是什么吗? 在 Tools->ROV->Hwi->Module 中,您可以看到系统堆栈峰值。 在 ROV->Task->Detailed 中,您可以看到任务堆栈峰值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Thepnimit Suparlert、

    请您回答上述问题吗?

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

    很抱歉耽误你的时间

    当我调试并看到 ROV 时、遵循建议  

    我应该怎么做? 增加堆栈? 当我将 app.cfg 中的 Program.stack 从0x100增加到0x500时、它仍然无效、这是堆栈0x500的图片

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    堆栈看起来不错。 我需要对 CAN 专家进行 Ping 操作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好

    如果您查看 CAN 消息 RAM、您是否会收到数据?

    确保使用正确的 CAN 消息对象 ID 发送数据(看起来您使用的是零)。

    此外、我看不到您在哪里启用 CAN 外设中的 CAN 全局中断线。  

    这将是: CANGLALIntEnable (CANA_base、CAN_GLB_INT_CANINT0);

    此致

    Chris

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用]我可以从板上发送 CAN 消息并从 ARM debian[/quot]获取该消息

    在上面的行中,您意味着您可以从28377发送和接收消息。 但是、在下面的行中、您与自己相矛盾、并说 F28377无法接收。 您能不能确切地说明具体的情况吗?

    [引用]但是当我将消息从 debian 发送到 f28377时、它不起作用
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这是否得到了解决?

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

    感谢你的帮助

    当我按照建议  添加代码 CANGLALIntEnable (CANA_base、CAN_GLB_INT_CANINT0);

    现在、当我发送 CAN 消息时 LED 亮起、但它始终亮起

    我的意思是遵循我的代码时

    void canaISR (UARg arg)
    {
    if (dataRecibed == true){
    GPIO_WritePin (LED_BLUE、OFF);
    dataReciped == false;
    }
    否则{
    GPIO_WritePin (LED_BLUE、ON);
    dataReciped == true;
    }
    } 

    CAN 消息 LED 亮起且变量数据已接收从 false 更改为 true 时的第一轮

    当我再次发送消息(第二轮)时、如果应该关闭 LED 灯、对吗? 但 LED 不会熄灭

    这是否意味着 HwiFnx 只被称为1舍入?

    我是说我可以看到来自 debian 的 CAN 消息

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

    抱歉、超出我的代码、应该会出现

    void canaISR (UARg arg)
    {
    if (dataRecibed == true){
    GPIO_WritePin (LED_BLUE、OFF);
    数据接收= false;
    }
    否则{
    GPIO_WritePin (LED_BLUE、ON);
    数据接收= true;
    }
    } 

    但是、当修复代码时、仍然存在相同的问题、 HwiFnx 只被称为1舍入?

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

    必须在 ISR 结束时清除 CAN 全局中断:CANGLALIntClear (CANA_base、CAN_GLB_INT_CANINT0);
    此外、我不太熟悉使用 BIOS 运行时的情况、但通常您还必须为中断 ACK PIE 组:PieCtrlRegs.PIEACK.all = PIEACK_group9;

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

    我添加代码

    CANGLALIntClear (CANA_base、CAN_GLB_INT_CANINT0);
    PieCtrlRegs.PIEACX.ALL = PIEACK_group9;

    最后一行中的 canaISR 函数

    CAN 报文仍然只有一个中断、空闲任务中的 LED 为红色停止闪烁

    这意味着 在 CANGLALIntClear 程序之后不会返回空闲任务?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您能否在 Tools->ROV 中查看第一个中断前后的 Hwi 状态?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我发现了4项更改

    中断前

      

    中断后

    这些情况表示什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    抱歉、此主题属于两个不同的 TI 组。 我将跟进 C2000团队。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好

    上周、我测试 了 CANGLALIntClear (CANA_base、CAN_GLB_INT_CANINT0)的多路代码;

    1.在 Hwi 函数中插入:

    void canaISR (UARg arg){
    if (!dataRecibed){
    数据接收= true;
    }
    CANGLALIntClear (CANA_base、CAN_GLB_INT_CANINT0);
    } 

    不起作用、硬件中断将关闭、程序将停止

    2.插入空闲函数:

    void canaISR (UARg arg){
    if (!dataRecibed){
    数据接收= true;
    }
    }
    void myIdleFxn (void){
    if (dataRecibed){
    CANGLALIntClear (CANA_base、CAN_GLB_INT_CANINT0);
    Task_sleep (10);
    dataReciped = false;
    GPIO_WritePin (LED_BLUE、ON);
    Task_sleep (50);
    }
    否则、如果(!dataRecibed){
    GPIO_WritePin (LED_BLUE、OFF);
    Task_sleep (50);
    }
    GPIO_WritePin (LED_RED、ON);
    Task_sleep (50);
    GPIO_WritePin (LED_RED、OFF);
    Task_sleep (50);
    } 

    这只起作用一个中断、空闲函数仍然起作用、但当有下一个中断 时、Hwi 函数不起作用

    当从该线程 https://e2e.ti.com/support/microcontrollers/c2000/f/171/p/774381/2866157?tisearch=e2e-sitesearch&keymatch=SySBIOS 引用时

    当我跟着转时、他通过 swi_post 解决问题 eCAP、或者使用另一个任务来清除标志中断

    void canaISR (UARg arg){
    swi_post (swi);
    }
    void swifxn (void){
    if (!dataRecibed){
    CANIntClear (CANA_base、RX_MSG_OBJ_ID);
    数据接收= true;
    }
    }
    void myIdleFxn (void){
    if (dataRecibed){
    dataReciped = false;
    GPIO_WritePin (LED_BLUE、ON);
    Task_sleep (50);
    }
    否则、如果(!dataRecibed){
    GPIO_WritePin (LED_BLUE、OFF);
    Task_sleep (50);
    }
    GPIO_WritePin (LED_RED、ON);
    Task_sleep (50);
    GPIO_WritePin (LED_RED、OFF);
    Task_sleep (50);
    } 

    这将导致1。 如果进入空闲函数、则 会得到2。

    4.当我从 SYS/BIOS doc spruex3t 引用时

    代码时、我将会遇到这一问题

    void myRegister1 (int hookSetId){
    myHookSetId1 = hookSetId;
    }
    void myCreate1 (Hwi_handle hwi、Error_Block * EB){
    hwi_setHookContext (hwi、myHookSetId1、(ptr) 0xdad1);
    }
    void myBegin1 (hwi_handle hwi){
    hwi_setHookContext (hwi、myHookSetId1、(ptr) 0xbeef1);
    }
    void myEnd1 (hwi_handle hwi){
    hwi_setHookContext (hwi、myHookSetId1、(ptr) 0xc0de1);
    }
    //*
    === HwiFxn ====
    */
    void canaISR (UArg arg){
    if (!dataRecibed){
    数据接收= true;
    }
    }
    

    如果在 Hwi 函数结果中插入 CANGLALIntClear、则仍然不起作用。  如果处于空闲状态、则结果为2。

    这意味着使用 SYS/BIOS 的 CANGlobal 中断无法清除?

    我可以看到寄存器和发现寄存器后面没有清除

     -运行 initComponent()之前

     - 运行 initComponent()后

     - 第1个中断之后

      -第2个中断之后

    我不确定 CANGLALIntClear 如何工作? 但寄存器中断标志在第一个中断后不会清除

    最后、 对于 PieCtrlRegs、我不确定它应该在 SYS/BIOS 使用 app.cfg 的 Hwi 函数默认值时使用

    许多线程被告知不使用、这意味着该代码

    /***** 清除所有中断并初始化 PIE 矢量表:***** /
    DINT;//禁用 CPU 中断
    
    /***禁用 CPU 中断并清除所有 CPU 中断标志***/
    IER = 0x0000;//禁用 CPU 中断
    IFR = 0x0000;//清除 CPU 中断标志
    
    EALLOW;
    EDIS;
    
    //
    //在处理器(PIE)上启用 CAN 中断。
    //
    
    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
    IER |= M_INT9;
    EINT;
    
    和
    
    PieCtrlRegs.PIEACX.ALL = PIEACK_group9; 

    不需要它?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您能否查看 C2000Ware 中的 CAN 示例(例如 C2000Ware_1_00_06_00\device_support\f2837xs\examples\CPU1\CAN_loopback_interrupts\cpu01\co_loopback_interrupts.c)并遵循其 ISR 函数的模型(减去中断关键字)。 例如、获取状态并根据需要清除 Tx 和 Rx、然后清除 CANGlobal 和 PieCtrlRegs.PIEACX.ALL。

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

    现在对我来说是可行的。 但我不知道有什么问题

    GPIO_SetupPinMux (CANRXA、GPIO_MUX_CPU1、MUXMODE);//GPIO70 - CANRXA
    GPIO_SetupPinOptions (CANRXA、GPIO_INPUT、GPIO_异 步);
    GPIO_SetupPinMux (CANTXA、GPIO_MUX_CPU1、MUXMODE);//GPIO71 - CANTXA
    GPIO_SetupPinOptions (CANTXA、GPIO_OUTPUT、GPIO_PushPull);
    
    CANInit (CANA_base);
    CANClkSourceSelect (CANA_base、0);// 500kHz CAN 时钟
    CANBitRateSet (CANA_base、200000000、50000);
    CANIntEnable (CANA_base、CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
    dint;
    
    // InitPieCtrl();
    
    IER = 0x0000;
    IFR = 0x0000;
    
    // InitPieVectTable ();
    
    EALLOW;
    // PieVectTable.CANA0_INT = canaISR;
    EDIS;
    
    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
    IER |= M_INT9;
    EINT;
    
    CANGLALIntEnable (CANA_base、CAN_GLB_INT_CANINT0);
    
    //CAN TX 配置
    sTXCANMessage.ui32MsgID = CAN_ID;
    sTXCANMessage.ui32MsgIDMask = 0;
    sTXCANMessage.ui32Flags = 0;
    sTXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
    sTXCANMessage.pucMsgData = txMsgData;
    CANMessageSet (CANA_base、TX_MSG_OBJ_ID、&sTXCANMessage、MSG_OBJ_TYPE_TX);
    
    //CAN RX 配置
    sRXCANMessage.ui32MsgID = CAN_ID;
    sRXCANMessage.ui32MsgIDMask = 0;
    sRXCANMessage.ui32Flags =(MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_EXDED_ID | MSG_OBJ_USE_ID_FILTER);
    sRXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
    sRXCANMessage.pucMsgData = rxMsgData;
    CANMessageSet (CANA_base、RX_MSG_OBJ_ID、&sRXCANMessage、MSG_OBJ_TYPE_RX);
    
    CANEnable (CANA_base); 

    这个代码关键点来自 SYS/BIOS 中实现示例。 在我不添加3个代码之前  

    EALLOW;
    // PieVectTable.CANA0_INT = canaISR;
    EDIS;

    因为我找到了一些你告诉过它不使用的线程。 当我添加它并注释 PieVectTable 时、它是有效的。

    但是、当我再次删除这3行时。 它仍然可以工作吗? 是 的、虽然我将删除(工作1周期是永远工作?)、但它仍有效。

    dint;
    
    // InitPieCtrl();
    
    IER = 0x0000;
    IFR = 0x0000;
    
    // InitPieVectTable ();
    
    EALLOW;
    // PieVectTable.CANA0_INT = canaISR;
    EDIS;
    
    PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
    IER |= M_INT9;
    EINT; 

    好的、没关系、现在我仍然不会删除代码、以确保代码能够永远工作。

    感谢您的长期帮助。