LPC1768 - CAN - Acceptance Filter - bus fault

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPC1768 - CAN - Acceptance Filter - bus fault

1,594 次查看
rrollfin
Contributor I

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é

 

 

标签 (1)
0 项奖励
回复
3 回复数

1,557 次查看
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

 

 

0 项奖励
回复

1,549 次查看
rrollfin
Contributor I

 

Thanks for the quick reply.

I've tried to reset the CAN module as follows:

LPC_CAN2 -> MOD = 1; /* Reset CAN */

But this write access also results in a bus fault.

Best regards,
René

0 项奖励
回复

1,483 次查看
xiangjun_rong
NXP TechSupport
NXP TechSupport

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:

 

https://www.nxp.com/design/software/mcuxpresso-software-and-tools-/lpcopen-libraries-and-examples/lp...

Hope it is helpful

BR

XiangJun Rong

 

0 项奖励
回复