Hello Nxp support team,
I have an issue when accessing AFMR after CAN and Acceptance Filter are initialized.
Initialization of CAN and Acceptance Filter works as expected. When I try to change the filter I get a bus fault when accessing the AFMR (LPC_CANAF->AFMR = CAN_FILTER_OFF).
Here is my initialization routine for CAN2:
void hal_init_can(void)
{
/* Switch on CANx-Peripheral */
LPC_SC -> PCONP |= PCONP_PCCANx;
/* Set Baudrate (250 kBaud) */
LPC_SC->PCLKSEL0 |= 0x00000000; /* PCLK = CCLK/4 */
LPC_CAN2->BTR = 0x002f0000 + 4; /* Bus-Timing: Prescaler: 5, 1 bit = 20 canclks */
LPC_CAN2 -> MOD = 1; /* Reset CAN */
LPC_CAN2 -> IER = 0; /* Disable Receive Interrupt */
LPC_CAN2 -> GSR = 0; /* Reset error counter when CANxMOD is in reset */
LPC_PINCON->PINSEL4 |= (1u << 14); /* Configure RD Pin for CAN2 (P2.7 RD2) */
LPC_PINCON->PINSEL4 |= (1u << 16); /* Configure TD Pin for CAN2 (P2.8 TD2) */
// Set Acceptance Filter
LPC_CANAF-> AFMR = CAN_FILTER_OFF;
hal_can_set_filter();
LPC_CANAF-> AFMR = CAN_FILTER_OPERATING;
LPC_CAN2->MOD &= ~1; /* Set in Normal Mode */
NVIC_EnableIRQ(CAN_IRQn); /* Activate CAN Interrupt in NVIC */
NVIC_SetPriority(CAN_IRQn, 13); /* Set Priority for CAN-Interrupt */
LPC_CAN2 -> IER = 0x01; /* Enable Rx Interrupt */
return;
}
Here is the routine for setting the Acceptance Filter:
static void hal_can_set_filter(void)
{
uint32_t start_address = 0;
uint32_t i;
uint32_t halfword_0, halfword_1;
/* Set explicit standard Frame */
LPC_CANAF->SFF_sa = start_address;
for (i = 0; i < can_filter_num_entrys; i += 2)
{
halfword_1 = ((uint32_t)(hal_can_id_table[i].scc) << 29) |
((uint32_t)(hal_can_id_table[i].disable) << 28) |
((uint32_t)(hal_can_id_table[i].identifier) << 16);
if ((i + 1) < can_filter_num_entrys)
{
halfword_0 = ((uint32_t)(hal_can_id_table[i+1].scc) << 13) |
((uint32_t)(hal_can_id_table[i+1].disable) << 12) |
((uint32_t)(hal_can_id_table[i+1].identifier) << 0);
}
else
{
// Entry "disable" odd lists
halfword_0 = 0xFFFF;
}
*((volatile uint32_t *)(LPC_CANAF_RAM_BASE + start_address)) = halfword_1 | halfword_0;
start_address += 4;
}
/* Set group standard Frame */
LPC_CANAF->SFF_GRP_sa = start_address;
/* Set explicit extended Frame */
LPC_CANAF->EFF_sa = start_address;
/* Set group extended Frame */
LPC_CANAF->EFF_GRP_sa = start_address;
/* Set End of Table */
LPC_CANAF->ENDofTable = start_address;
return;
}
The table of CAN IDs is defined as follows:
#define NODE_ID_MASTER 1
#define MY_NODE_ID 4
#define SCC_CAN1 0x00
#define SCC_CAN2 0x01
#define CAN_ID_NMT_MODULE_CONTROL 0x000
#define CAN_ID_PDO2 (0x300 + MY_NODE_ID)
#define CAN_ID_PDO4 (0x400 + MY_NODE_ID)
#define CAN_ID_SDO_ACCESS (0x600 + MY_NODE_ID)
#define CAN_ID_HEARTBEAT_FROM_MASTER (0x700 + NODE_ID_MASTER)
#pragma pack(push,1)
typedef struct
{
uint16_t scc:3;
uint16_t disable:1;
uint16_t not_used:1;
uint16_t identifier:11;
} can_filter_entry_explicit_std_t;
#pragma pack(pop)
static const can_filter_entry_explicit_std_t hal_can_id_table [] =
{
{ .scc = SCC_CAN2, .disable = 0, .not_used = 0, .identifier = CAN_ID_NMT_MODULE_CONTROL },
{ .scc = SCC_CAN2, .disable = 0, .not_used = 0, .identifier = CAN_ID_PDO2 },
{ .scc = SCC_CAN2, .disable = 0, .not_used = 0, .identifier = CAN_ID_PDO4 },
{ .scc = SCC_CAN2, .disable = 0, .not_used = 0, .identifier = CAN_ID_SDO_ACCESS },
{ .scc = SCC_CAN2, .disable = 0, .not_used = 0, .identifier = CAN_ID_HEARTBEAT_FROM_MASTER },
};
static const uint32_t can_filter_num_entrys = sizeof(hal_can_id_table) / sizeof(can_filter_entry_explicit_std_t);Here are routines to enable / disable the filters on user action:
// Enable all CAN-IDs in filter
void hal_can_filter_enable_all(void)
{
uint32_t start_address = 0;
LPC_CANAF-> AFMR = CAN_FILTER_BYPASS;
while (start_address < LPC_CANAF->ENDofTable)
{
*((volatile uint32_t *)(LPC_CANAF_RAM_BASE + start_address)) = 0x00000000;
start_address += 4;
}
LPC_CANAF-> AFMR = CAN_FILTER_OPERATING;
}
// Disable all CAN-IDs in filter
void hal_can_filter_disable_all(void)
{
uint32_t start_address = 0;
LPC_CANAF-> AFMR = CAN_FILTER_BYPASS;
while (start_address < LPC_CANAF->ENDofTable)
{
*((volatile uint32_t *)(LPC_CANAF_RAM_BASE + start_address)) = 0xFFFFFFFF;
start_address += 4;
}
LPC_CANAF-> AFMR = CAN_FILTER_OPERATING;
}
I get a bus fault at the line where the filter mode is set to BYPASS:
LPC_CANAF-> AFMR = CAN_FILTER_BYPASS;
Is there any example / application note for the Acceptance Filter on LPC1768?
Are there any known issues for the CAN module on LPC1768?
Best regards,
René
Hi,
After the CAN runs in operational mode with AccOff=0, AccBP=0 and eFCAN = 0, and the Acceptance Filter is working, in the case, you can not reconfigure it in ByPass mode by setting the AccBP bit. If you do want to reconfigure CAN in Bypass mode, you have to execute CAN reset instruction,then all bits AccOff=1, AccBP=1 and eFCAN = 1 automatically, then you can enter Bypass mode. You can rest the CAN module by setting the RM bit in CAN_MOD register.
Hope it can help you
BR
XiangJun Rong
Hi,
I have checked your code, you have enabled the CAN clock with the code:
LPC_SC -> PCONP |= PCONP_PCCANx;
/* Set Baudrate (250 kBaud) */
LPC_SC->PCLKSEL0 |= 0x00000000; /* PCLK = CCLK/4 */
But I do not know why you enter bus fault.
Pls try to download LPCOpen package and check the CAN example for LPC1768:
Hope it is helpful
BR
XiangJun Rong