Other Parts Discussed in Thread: MOTORWARE
I am trying to add CAN support for Motorware 16 proj_lab09. Right now I'm trying to get interrupts to work. I went through spruh18f.pdf section 16.13.3.1, but either I misunderstood/missed something, or it's not enough. Here is how I configure the interrupts:
First this is executed as part of the initialization for eCAN (this bit is between calls to EALLOW; and EDIS;):
// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again // as a matter of precaution. obj->ecanaHandle->ECanaRegs->CANTA.all = 0xFFFFFFFF; /* Clear all TAn bits */ obj->ecanaHandle->ECanaRegs->CANRMP.all = 0xFFFFFFFF; /* Clear all RMPn bits */ obj->ecanaHandle->ECanaRegs->CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */ obj->ecanaHandle->ECanaRegs->CANGIF1.all = 0xFFFFFFFF; //Enable interrupts. ECanaShadow.CANGIM.all = obj->ecanaHandle->ECanaRegs->CANGIM.all; ECanaShadow.CANGIM.bit.AAIM = 1; ECanaShadow.CANGIM.bit.WDIM = 1; ECanaShadow.CANGIM.bit.WUIM = 1; ECanaShadow.CANGIM.bit.BOIM = 1; ECanaShadow.CANGIM.bit.EPIM = 1; ECanaShadow.CANGIM.bit.WLIM = 1; ECanaShadow.CANGIM.bit.GIL = 1; //the GIL (GIM.2) bit can be set to have the global interrupts on another level than the mailbox interrupts ECanaShadow.CANGIM.bit.I0EN = 1; ECanaShadow.CANGIM.bit.I1EN = 1; obj->ecanaHandle->ECanaRegs->CANGIM.all = ECanaShadow.CANGIM.all;
Call from main:
ECAN_configMbox(halHandle->ecanaHandle, 16, 6, 1, 1, 0x07FF, 1, 1);
The function that does most of the configuration:
void ECAN_configMbox(ECAN_Handle handle, uint8_t mboxNum, uint32_t msgid, uint8_t enable, uint8_t rx, uint32_t mask, uint8_t enable_interrupt, uint8_t interrupt_line){
struct ECAN_REGS ecanaShadow;
//Getting reference to the mbox with the given mboxNum.
volatile struct MBOX *mbox = (&(handle->ECanaMboxes->MBOX0)) + (mboxNum);
volatile union CANLAM_REG *lam = (&(handle->ECanaLAMRegs->LAM0)) + (mboxNum);
//Setting local acceptance mask.
//lam->all = mask;
lam->bit.LAM_H = mask;
//Setting msgid.
//mbox->MSGID.all = msgid;
mbox->MSGID.bit.STDMSGID = msgid;
//Setting rx/tx mode.
rx = rx & 1; //Making sure it's only one bit.
ecanaShadow.CANMD.all = handle->ECanaRegs->CANMD.all;
ecanaShadow.CANMD.all = (~((~ecanaShadow.CANMD.all) | (((uint32_t)1) << mboxNum))) | (((uint32_t)rx) << mboxNum);
handle->ECanaRegs->CANMD.all = ecanaShadow.CANMD.all;
//Enable/disable mbox.
enable = enable & 1; //Making sure it's only one bit.
ecanaShadow.CANME.all = handle->ECanaRegs->CANME.all;
ecanaShadow.CANME.all = (~((~ecanaShadow.CANME.all) | (((uint32_t)1) << mboxNum))) | (((uint32_t)enable) << mboxNum);
handle->ECanaRegs->CANME.all = ecanaShadow.CANME.all;
// Specify that 8 bits will be sent/received
mbox->MSGCTRL.bit.DLC = 8;
EALLOW;
//Enable/disable interrupt.
enable_interrupt = enable_interrupt & 1; //Making sure it's only one bit.
ecanaShadow.CANMIM.all = handle->ECanaRegs->CANMIM.all;
ecanaShadow.CANMIM.all = (~((~ecanaShadow.CANMIM.all) | (((uint32_t)1) << mboxNum))) | (((uint32_t)enable_interrupt) << mboxNum);
handle->ECanaRegs->CANMIM.all = ecanaShadow.CANMIM.all;
//Selecting interrupt line 0 or 1.
interrupt_line = interrupt_line & 1; //Making sure it's only one bit.
ecanaShadow.CANMIL.all = handle->ECanaRegs->CANMIL.all;
ecanaShadow.CANMIL.all = (~((~ecanaShadow.CANMIL.all) | (((uint32_t)1) << mboxNum))) | (((uint32_t)interrupt_line) << mboxNum);
handle->ECanaRegs->CANMIL.all = ecanaShadow.CANMIL.all;
//Disable self-test mode.
ecanaShadow.CANMC.all = handle->ECanaRegs->CANMC.all;
ecanaShadow.CANMC.bit.STM = 0; // Disable self-test mode.
handle->ECanaRegs->CANMC.all = ecanaShadow.CANMC.all;
EDIS;
}
The interrupt functions (and halHandle->pieHandle->ECAN0INT / ECAN1INT are correctly pointing to these functions, verified with debugger):
interrupt void ecan0ISR(void){
//ecanTestRead(16);
canIsr0Count++;
ECAN_clearInterrupts(halHandle->ecanaHandle);
HAL_pieAckInt(halHandle, PIE_GroupNumber_9);
return;
}
interrupt void ecan1ISR(void){
//ecanTestRead(16);
canIsr1Count++;
ECAN_clearInterrupts(halHandle->ecanaHandle);
HAL_pieAckInt(halHandle, PIE_GroupNumber_9);
return;
}
The ECAN_clearInterrupts function (used in interrupts above):
void ECAN_clearInterrupts(ECAN_Handle handle){
halHandle->ecanaHandle->ECanaRegs->CANTA.all = 0xFFFFFFFF; /* Clear all TAn bits */
halHandle->ecanaHandle->ECanaRegs->CANRMP.all = 0xFFFFFFFF; /* Clear all RMPn bits */
halHandle->ecanaHandle->ECanaRegs->CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */
halHandle->ecanaHandle->ECanaRegs->CANGIF1.all = 0xFFFFFFFF;
}
The interrupts are enabled in main via this function, before the call to (HAL_enableGlobalInts):
void HAL_enableEcanInt(HAL_Handle handle){
HAL_Obj *obj = (HAL_Obj *)handle;
PIE_enableInt(obj->pieHandle, PIE_GroupNumber_9, PIE_InterruptSource_ECANA0);
PIE_enableInt(obj->pieHandle, PIE_GroupNumber_9, PIE_InterruptSource_ECANA1);
return;
}
When I poll the mailboxes, I am receiving data, but the interrupts do not increase the counters. What am I missing?