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é